From 9182c8bdb1f08febf1e6355d928ee2a39dbbdf24 Mon Sep 17 00:00:00 2001 From: DefectDojo release bot Date: Tue, 2 Apr 2024 18:47:54 +0000 Subject: [PATCH 001/138] Update versions in application files --- components/package.json | 2 +- docs/content/en/getting_started/upgrading/2.34.md | 7 +++++++ dojo/__init__.py | 2 +- helm/defectdojo/Chart.yaml | 4 ++-- 4 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 docs/content/en/getting_started/upgrading/2.34.md diff --git a/components/package.json b/components/package.json index 1b5ec25b1a..41e9d22009 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "defectdojo", - "version": "2.33.0", + "version": "2.34.0-dev", "license" : "BSD-3-Clause", "private": true, "dependencies": { diff --git a/docs/content/en/getting_started/upgrading/2.34.md b/docs/content/en/getting_started/upgrading/2.34.md new file mode 100644 index 0000000000..7b0f7d266f --- /dev/null +++ b/docs/content/en/getting_started/upgrading/2.34.md @@ -0,0 +1,7 @@ +--- +title: 'Upgrading to DefectDojo Version 2.34.x' +toc_hide: true +weight: -20240402 +description: No special instructions. +--- +There are no special instructions for upgrading to 2.34.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.34.0) for the contents of the release. diff --git a/dojo/__init__.py b/dojo/__init__.py index dc4f84d168..4758913441 100644 --- a/dojo/__init__.py +++ b/dojo/__init__.py @@ -4,6 +4,6 @@ # Django starts so that shared_task will use this app. from .celery import app as celery_app # noqa: F401 -__version__ = '2.33.0' +__version__ = '2.34.0-dev' __url__ = 'https://github.com/DefectDojo/django-DefectDojo' __docs__ = 'https://documentation.defectdojo.com' diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index 80e11df68c..452ec76724 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 -appVersion: "2.33.0" +appVersion: "2.34.0-dev" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.118 +version: 1.6.119-dev icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap From 518ade523abddee704f44db07e8e1f8754c2c54f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 2 Apr 2024 21:06:20 -0500 Subject: [PATCH 002/138] Update Helm release postgresql from 15.1.4 to ~15.2.0 (helm/defectdojo/Chart.yaml) (#9852) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- helm/defectdojo/Chart.lock | 8 ++++---- helm/defectdojo/Chart.yaml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/helm/defectdojo/Chart.lock b/helm/defectdojo/Chart.lock index a85360d454..04c171e2c5 100644 --- a/helm/defectdojo/Chart.lock +++ b/helm/defectdojo/Chart.lock @@ -4,7 +4,7 @@ dependencies: version: 9.19.1 - name: postgresql repository: https://charts.bitnami.com/bitnami - version: 15.1.4 + version: 15.2.0 - name: postgresql-ha repository: https://charts.bitnami.com/bitnami version: 9.4.11 @@ -13,6 +13,6 @@ dependencies: version: 11.16.2 - name: redis repository: https://charts.bitnami.com/bitnami - version: 19.0.1 -digest: sha256:7c38007c50dd3fddea2d065cf57848cf9ef65f6a3b9fc1ec6bf508214429704b -generated: "2024-03-25T19:30:19.499072006Z" + version: 19.0.2 +digest: sha256:e4fa2641d160547748ba41a729ea67574601003b8f5da322832d88bd18acb6bd +generated: "2024-04-01T09:55:40.430476431Z" diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index 452ec76724..40bd74c814 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -14,7 +14,7 @@ dependencies: repository: "https://charts.bitnami.com/bitnami" condition: mysql.enabled - name: postgresql - version: ~15.1.0 + version: ~15.2.0 repository: "https://charts.bitnami.com/bitnami" condition: postgresql.enabled - name: postgresql-ha From e2d55407dfee727a870c1a1d0b1bc4d87b89fa11 Mon Sep 17 00:00:00 2001 From: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> Date: Tue, 2 Apr 2024 21:20:26 -0500 Subject: [PATCH 003/138] GHA: Update `docker-compose` refs to `docker compose` (#9870) * GHA: Update `docker-compose` refs to `docker compose` * Correct typo * Another typo... --- .github/workflows/fetch-oas.yml | 6 +++--- .github/workflows/integration-tests.yml | 14 +++++++------- .github/workflows/rest-framework-tests.yml | 10 +++++----- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/fetch-oas.yml b/.github/workflows/fetch-oas.yml index 0dd32805b5..c37d0a5254 100644 --- a/.github/workflows/fetch-oas.yml +++ b/.github/workflows/fetch-oas.yml @@ -33,7 +33,7 @@ jobs: docker images - name: Start Dojo - run: docker-compose --profile postgres-redis --env-file ./docker/environments/postgres-redis.env up --no-deps -d postgres nginx uwsgi + run: docker compose --profile postgres-redis --env-file ./docker/environments/postgres-redis.env up --no-deps -d postgres nginx uwsgi env: DJANGO_VERSION: ${{ env.release_version }}-alpine NGINX_VERSION: ${{ env.release_version }}-alpine @@ -44,11 +44,11 @@ jobs: - name: Logs if: always() - run: docker-compose --profile postgres-redis --env-file ./docker/environments/postgres-redis.env logs --tail="2500" + run: docker compose --profile postgres-redis --env-file ./docker/environments/postgres-redis.env logs --tail="2500" - name: Shutdown if: always() - run: docker-compose --profile postgres-redis --env-file ./docker/environments/postgres-redis.env down + run: docker compose --profile postgres-redis --env-file ./docker/environments/postgres-redis.env down - name: Upload oas.${{ matrix.file-type }} as artifact uses: actions/upload-artifact@v3 diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 0a514841ab..f573efdcc7 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -5,7 +5,7 @@ on: jobs: integration_tests: - # run tests with docker-compose + # run tests with docker compose name: User Interface Tests runs-on: ubuntu-latest strategy: @@ -61,34 +61,34 @@ jobs: # phased startup with MySQL and RabbitMQ so we can use the exit code from integrationtest container - name: Start Dojo MySQL + RabbitMQ if: matrix.profile == 'mysql-rabbitmq' - run: docker-compose --profile ${{ matrix.profile }} --env-file ./docker/environments/${{ matrix.profile }}.env up --no-deps -d mysql nginx celerybeat celeryworker mailhog uwsgi rabbitmq + run: docker compose --profile ${{ matrix.profile }} --env-file ./docker/environments/${{ matrix.profile }}.env up --no-deps -d mysql nginx celerybeat celeryworker mailhog uwsgi rabbitmq env: DJANGO_VERSION: ${{ matrix.os }} NGINX_VERSION: ${{ matrix.os }} - name: Start Dojo PostgreSQL + Redis if: matrix.profile == 'postgres-redis' - run: docker-compose --profile ${{ matrix.profile }} --env-file ./docker/environments/${{ matrix.profile }}.env up --no-deps -d postgres nginx celerybeat celeryworker mailhog uwsgi redis + run: docker compose --profile ${{ matrix.profile }} --env-file ./docker/environments/${{ matrix.profile }}.env up --no-deps -d postgres nginx celerybeat celeryworker mailhog uwsgi redis env: DJANGO_VERSION: ${{ matrix.os }} NGINX_VERSION: ${{ matrix.os }} - name: Initialize - run: docker-compose --profile ${{ matrix.profile }} --env-file ./docker/environments/${{ matrix.profile }}.env up --no-deps --exit-code-from initializer initializer + run: docker compose --profile ${{ matrix.profile }} --env-file ./docker/environments/${{ matrix.profile }}.env up --no-deps --exit-code-from initializer initializer env: DJANGO_VERSION: ${{ matrix.os }} NGINX_VERSION: ${{ matrix.os }} - name: Integration tests - run: docker-compose --profile ${{ matrix.profile }} --env-file ./docker/environments/${{ matrix.profile }}.env up --no-deps --exit-code-from integration-tests integration-tests + run: docker compose --profile ${{ matrix.profile }} --env-file ./docker/environments/${{ matrix.profile }}.env up --no-deps --exit-code-from integration-tests integration-tests env: DD_INTEGRATION_TEST_FILENAME: ${{ matrix.test-case }} INTEGRATION_TESTS_VERSION: debian - name: Logs if: always() - run: docker-compose --profile ${{ matrix.profile }} --env-file ./docker/environments/${{ matrix.profile }}.env logs --tail="2500" + run: docker compose --profile ${{ matrix.profile }} --env-file ./docker/environments/${{ matrix.profile }}.env logs --tail="2500" - name: Shutdown if: always() - run: docker-compose --profile ${{ matrix.profile }} --env-file ./docker/environments/${{ matrix.profile }}.env down + run: docker compose --profile ${{ matrix.profile }} --env-file ./docker/environments/${{ matrix.profile }}.env down diff --git a/.github/workflows/rest-framework-tests.yml b/.github/workflows/rest-framework-tests.yml index c02c6c22a1..d50c837efb 100644 --- a/.github/workflows/rest-framework-tests.yml +++ b/.github/workflows/rest-framework-tests.yml @@ -28,24 +28,24 @@ jobs: docker load -i django/django-${{ matrix.os }}_img docker images - # run tests with docker-compose + # run tests with docker compose - name: Set unit-test mode run: docker/setEnv.sh unit_tests_cicd # phased startup so we can use the exit code from unit test container - name: Start MySQL - run: docker-compose --env-file ./docker/environments/mysql-redis.env up -d mysql + run: docker compose --env-file ./docker/environments/mysql-redis.env up -d mysql # no celery or initializer needed for unit tests - name: Unit tests - run: docker-compose --profile mysql-redis --env-file ./docker/environments/mysql-redis.env up --no-deps --exit-code-from uwsgi uwsgi + run: docker compose --profile mysql-redis --env-file ./docker/environments/mysql-redis.env up --no-deps --exit-code-from uwsgi uwsgi env: DJANGO_VERSION: ${{ matrix.os }} - name: Logs if: failure() - run: docker-compose --profile mysql-redis --env-file ./docker/environments/mysql-redis.env logs --tail="2500" uwsgi + run: docker compose --profile mysql-redis --env-file ./docker/environments/mysql-redis.env logs --tail="2500" uwsgi - name: Shutdown if: always() - run: docker-compose --profile mysql-redis --env-file ./docker/environments/mysql-redis.env down + run: docker compose --profile mysql-redis --env-file ./docker/environments/mysql-redis.env down From 0dc0b2296662bbed52c77859df741d74cab5b7d7 Mon Sep 17 00:00:00 2001 From: kiblik Date: Wed, 3 Apr 2024 16:56:41 +0200 Subject: [PATCH 004/138] Add NOTIFICATIONS_SYSTEM_LEVEL_TRUMP (#9699) * Add NOTIFICATIONS_SYSTEM_LEVEL_TRUMP * Update docs/content/en/integrations/notifications.md Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Update unittests/test_notifications.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> --------- Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> --- docs/content/en/integrations/notifications.md | 10 ++++ dojo/notifications/helper.py | 19 +++++--- dojo/settings/settings.dist.py | 6 +++ unittests/test_notifications.py | 46 +++++++++++++++++++ 4 files changed, 74 insertions(+), 7 deletions(-) diff --git a/docs/content/en/integrations/notifications.md b/docs/content/en/integrations/notifications.md index 648d8ff1bf..d5af295f0e 100644 --- a/docs/content/en/integrations/notifications.md +++ b/docs/content/en/integrations/notifications.md @@ -115,3 +115,13 @@ To activate notifications to Microsoft Teams, you have to: - Configure an Incoming Webhook in a Teams channel and copy the URL of the webhook to the clipboard - Activate `Enable Microsoft Teams notifications` in the System Settings - Paste the URL of the Incoming Webhook into the field `Msteams url` + +## Specific overrides + +System notification settings (scope: system) describe the sending of notifications to superadmins. User notification settings (scope: personal) describe sending notifications to the specific user. + +However, there is a specific use-case when the user decides to disable notifications (to decrease noise) but the system setting is used to override this behavior. These overrides apply only to `user_mentioned` and `review_requested` by default. + +The scope of this setting is customizable (see environmental variable `DD_NOTIFICATIONS_SYSTEM_LEVEL_TRUMP`). + +For more information about this behavior see the [related pull request #9699](https://github.com/DefectDojo/django-DefectDojo/pull/9699/) \ No newline at end of file diff --git a/dojo/notifications/helper.py b/dojo/notifications/helper.py index d4a95109d9..4cfa65bdda 100644 --- a/dojo/notifications/helper.py +++ b/dojo/notifications/helper.py @@ -1,6 +1,7 @@ import logging import requests +from django.conf import settings from django.core.mail import EmailMessage from django.db.models import Q, Count, Prefetch from django.template import TemplateDoesNotExist @@ -30,12 +31,17 @@ def create_notification(event=None, **kwargs): # mimic existing code so that when recipients is specified, no other system or personal notifications are sent. logger.debug('creating notifications for recipients: %s', kwargs['recipients']) for recipient_notifications in Notifications.objects.filter(user__username__in=kwargs['recipients'], user__is_active=True, product=None): - # merge the system level notifications with the personal level - # this allows for system to trump the personal - merged_notifications = Notifications.merge_notifications_list([system_notifications, recipient_notifications]) - merged_notifications.user = recipient_notifications.user - logger.debug('Sent notification to %s', merged_notifications.user) - process_notifications(event, merged_notifications, **kwargs) + if event in settings.NOTIFICATIONS_SYSTEM_LEVEL_TRUMP: + # merge the system level notifications with the personal level + # this allows for system to trump the personal + merged_notifications = Notifications.merge_notifications_list([system_notifications, recipient_notifications]) + merged_notifications.user = recipient_notifications.user + logger.debug('Sent notification to %s', merged_notifications.user) + process_notifications(event, merged_notifications, **kwargs) + else: + # Do not trump user preferences and send notifications as usual + logger.debug('Sent notification to %s', recipient_notifications.user) + process_notifications(event, recipient_notifications, **kwargs) else: logger.debug('creating system notifications for event: %s', event) @@ -322,7 +328,6 @@ def send_alert_notification(event, user=None, *args, **kwargs): except Exception as e: logger.exception(e) log_alert(e, "Alert Notification", title=kwargs['title'], description=str(e), url=kwargs['url']) - pass def get_slack_user_id(user_email): diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index 611bad2b65..2126ad82d9 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -285,6 +285,8 @@ # When set to True, use the older version of the qualys parser that is a more heavy handed in setting severity # with the use of CVSS scores to potentially override the severity found in the report produced by the tool DD_QUALYS_LEGACY_SEVERITY_PARSING=(bool, True), + # Use System notification settings to override user's notification settings + DD_NOTIFICATIONS_SYSTEM_LEVEL_TRUMP=(list, ["user_mentioned", "review_requested"]), ) @@ -1704,6 +1706,10 @@ def saml2_attrib_map_format(dict): USE_FIRST_SEEN = env('DD_USE_FIRST_SEEN') USE_QUALYS_LEGACY_SEVERITY_PARSING = env('DD_QUALYS_LEGACY_SEVERITY_PARSING') +# ------------------------------------------------------------------------------ +# Notifications +# ------------------------------------------------------------------------------ +NOTIFICATIONS_SYSTEM_LEVEL_TRUMP = env('DD_NOTIFICATIONS_SYSTEM_LEVEL_TRUMP') # ------------------------------------------------------------------------------ # Ignored Warnings diff --git a/unittests/test_notifications.py b/unittests/test_notifications.py index 462843f2c6..202d289a2c 100644 --- a/unittests/test_notifications.py +++ b/unittests/test_notifications.py @@ -1,5 +1,8 @@ from .dojo_test_case import DojoTestCase from dojo.models import Product, User, Notifications +from dojo.models import DEFAULT_NOTIFICATION +from dojo.notifications.helper import create_notification, send_alert_notification +from unittest.mock import patch class TestNotifications(DojoTestCase): @@ -55,3 +58,46 @@ def test_merge_notifications_list(self): self.assertEqual('slack' in merged_notifications.other, True) # default alert from global self.assertEqual(len(merged_notifications.other), 3) self.assertEqual(merged_notifications.other, {'alert', 'mail', 'slack'}) + + @patch('dojo.notifications.helper.send_alert_notification', wraps=send_alert_notification) + def test_notifications_system_level_trump(self, mock): + notif_user, _ = Notifications.objects.get_or_create(user=User.objects.get(username='admin')) + notif_system, _ = Notifications.objects.get_or_create(user=None, template=False) + + last_count = 0 + with self.subTest('user off, system off'): + notif_user.user_mentioned = () # no alert + notif_user.save() + notif_system.user_mentioned = () # no alert + notif_system.save() + create_notification(event="user_mentioned", title="user_mentioned", recipients=['admin']) + self.assertEqual(mock.call_count, last_count) + + last_count = mock.call_count + with self.subTest('user off, system on'): + notif_user.user_mentioned = () # no alert + notif_user.save() + notif_system.user_mentioned = DEFAULT_NOTIFICATION # alert only + notif_system.save() + create_notification(event="user_mentioned", title="user_mentioned", recipients=['admin']) + self.assertEqual(mock.call_count, last_count + 1) + + # Small note for this test-cast: Trump works only in positive direction - system is not able to disable some kind of notification if user enabled it + last_count = mock.call_count + with self.subTest('user on, system off'): + notif_user.user_mentioned = DEFAULT_NOTIFICATION # alert only + notif_user.save() + notif_system.user_mentioned = () # no alert + notif_system.save() + create_notification(event="user_mentioned", title="user_mentioned", recipients=['admin']) + self.assertEqual(mock.call_count, last_count + 1) + + last_count = mock.call_count + with self.subTest('user on, system on'): + notif_user.user_mentioned = DEFAULT_NOTIFICATION # alert only + notif_user.save() + notif_system.user_mentioned = DEFAULT_NOTIFICATION # alert only + notif_system.save() + create_notification(event="user_mentioned", title="user_mentioned", recipients=['admin']) + self.assertEqual(mock.call_count, last_count + 1) + last_count = mock.call_count From f00566130db82d1a2ded04de0bded4b9fd90ec9f Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Wed, 3 Apr 2024 16:57:31 +0200 Subject: [PATCH 005/138] :sparkler: refactor sonarqube and add JSON parsing for api export (#9734) * :sparkler: refactor sonarqube and add JSON parsing for api export * :construction: start with api json * continue work * update * update * fix * :tada: also advance to support multiple files at once via zip due to pagination * advance unittests * advance documentation * update documentation * update documentation * add tags to distinguish between findings * :pencile: docs * add cve * add cwe * add cvssscore * :lipstick: * :tada: add components * add ghsa * :bug: fix for empty zip file * empty json file * fix documentation * :bug: fix for different message structure * parse hotspots * fix according to review * ruff --- .../en/integrations/parsers/file/sonarqube.md | 26 +- dojo/tools/sonarqube/parser.py | 317 ++---------------- .../tools/sonarqube/sonarqube_restapi_json.py | 226 +++++++++++++ dojo/tools/sonarqube/sonarqube_restapi_zip.py | 12 + dojo/tools/sonarqube/soprasteria_helper.py | 146 ++++++++ dojo/tools/sonarqube/soprasteria_html.py | 83 +++++ dojo/tools/sonarqube/soprasteria_json.py | 69 ++++ unittests/scans/sonarqube/empty_zip.zip | Bin 0 -> 174 bytes .../scans/sonarqube/findings_over_api.json | 177 ++++++++++ .../scans/sonarqube/findings_over_api.zip | Bin 0 -> 2466 bytes .../sonarqube/findings_over_api_empty.json | 14 + .../sonarqube/findings_over_api_hotspots.json | 127 +++++++ unittests/tools/test_sonarqube_parser.py | 84 +++++ 13 files changed, 984 insertions(+), 297 deletions(-) create mode 100644 dojo/tools/sonarqube/sonarqube_restapi_json.py create mode 100644 dojo/tools/sonarqube/sonarqube_restapi_zip.py create mode 100644 dojo/tools/sonarqube/soprasteria_helper.py create mode 100644 dojo/tools/sonarqube/soprasteria_html.py create mode 100644 dojo/tools/sonarqube/soprasteria_json.py create mode 100644 unittests/scans/sonarqube/empty_zip.zip create mode 100644 unittests/scans/sonarqube/findings_over_api.json create mode 100644 unittests/scans/sonarqube/findings_over_api.zip create mode 100644 unittests/scans/sonarqube/findings_over_api_empty.json create mode 100644 unittests/scans/sonarqube/findings_over_api_hotspots.json diff --git a/docs/content/en/integrations/parsers/file/sonarqube.md b/docs/content/en/integrations/parsers/file/sonarqube.md index 4f5e90ed12..4734796dd7 100644 --- a/docs/content/en/integrations/parsers/file/sonarqube.md +++ b/docs/content/en/integrations/parsers/file/sonarqube.md @@ -2,7 +2,26 @@ title: "SonarQube" toc_hide: true --- -## SonarQube Scan (Aggregates findings per cwe, title, description, file\_path.) +# SonarQube Scan +There are two ways to retrieve findings from SonarQube. You can either use the [soprasteria package](https://github.com/soprasteria/sonar-report) or the SonarQube REST API directly. +Both ways (**SonarQube REST API** and **Soprasteria**) are depicted below. + +### Sample Scan Data +Sample SonarQube scans can be found [here](https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans/sonarqube). + +## SonarQube REST API +You can retrieve the JSON directly from SonarQube if you use one of the following REST API endpoint: +- `/api/issues/search?projects=` +- `/api/hotspots/search?projectKey=` + +### JSON +The REST API JSON output can be uploaded to DefectDojo with "SonarQube Scan". + +### ZIP +If you have too many findings in one project, you can implement a small script to handle pagination and put all JSON files in a .zip file. This zip file can also be parsed from DefectDojo with "SonarQube Scan". + +## Soprasteria +### Soprasteria SonarQube Scan (Aggregates findings per cwe, title, description, file\_path.) SonarQube output file can be imported in HTML format or JSON format. JSON format generated by options `--save-report-json` and have same behavior with HTML format. @@ -12,7 +31,7 @@ To generate the report, see Version: \>= 1.1.0 Recommend version for both format \>= 3.1.2 -## SonarQube Scan Detailed (Import all findings from SonarQube html report.) +### Soprasteria SonarQube Scan Detailed (Import all findings from SonarQube html report.) SonarQube output file can be imported in HTML format or JSON format. JSON format generated by options `--save-report-json` and have same behavior with HTML format. @@ -23,5 +42,4 @@ Version: \>= 1.1.0. Recommend version for both format \>= 3.1.2 -### Sample Scan Data -Sample SonarQube scans can be found [here](https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans/sonarqube). + diff --git a/dojo/tools/sonarqube/parser.py b/dojo/tools/sonarqube/parser.py index e7a04c545d..b4491d1164 100644 --- a/dojo/tools/sonarqube/parser.py +++ b/dojo/tools/sonarqube/parser.py @@ -1,12 +1,11 @@ import logging -import re - -from django.utils.html import strip_tags +from dojo.tools.sonarqube.soprasteria_json import SonarQubeSoprasteriaJSON +from dojo.tools.sonarqube.soprasteria_html import SonarQubeSoprasteriaHTML +from dojo.tools.sonarqube.sonarqube_restapi_json import SonarQubeRESTAPIJSON +from dojo.tools.sonarqube.sonarqube_restapi_zip import SonarQubeRESTAPIZIP from lxml import etree +import zipfile import json - -from dojo.models import Finding - logger = logging.getLogger(__name__) @@ -24,301 +23,33 @@ def get_label_for_scan_types(self, scan_type): def get_description_for_scan_types(self, scan_type): if scan_type == "SonarQube Scan": - return "Aggregates findings per cwe, title, description, file_path. SonarQube output file can be imported in HTML format or JSON format. Generate with https://github.com/soprasteria/sonar-report version >= 1.1.0, recommend version >= 3.1.2" + return "Aggregates findings per cwe, title, description, file_path. SonarQube output file can be imported in HTML format or JSON format. You can get the JSON output directly if you use the SonarQube API or generate with https://github.com/soprasteria/sonar-report version >= 1.1.0, recommend version >= 3.1.2" else: return "Import all findings from sonarqube html report or JSON format. SonarQube output file can be imported in HTML format or JSON format. Generate with https://github.com/soprasteria/sonar-report version >= 1.1.0, recommend version >= 3.1.2" - def get_findings(self, filename, test): - if filename.name.strip().lower().endswith(".json"): - json_content = json.load(filename) - return self.get_json_items(json_content, test, self.mode) + def get_findings(self, file, test): + if file.name.endswith(".json"): + json_content = json.load(file) + if json_content.get("date") and json_content.get("projectName") and json_content.get("hotspotKeys"): + return SonarQubeSoprasteriaJSON().get_json_items(json_content, test, self.mode) + elif json_content.get("paging") and json_content.get("components"): + return SonarQubeRESTAPIJSON().get_json_items(json_content, test, self.mode) + else: + return [] + if file.name.endswith(".zip"): + if str(file.__class__) == "": + input_zip = zipfile.ZipFile(file.name, 'r') + else: + input_zip = zipfile.ZipFile(file, 'r') + zipdata = {name: input_zip.read(name) for name in input_zip.namelist()} + return SonarQubeRESTAPIZIP().get_items(zipdata, test, self.mode) else: parser = etree.HTMLParser() - tree = etree.parse(filename, parser) + tree = etree.parse(file, parser) if self.mode not in [None, "detailed"]: raise ValueError( "Internal error: Invalid mode " + self.mode + ". Expected: one of None, 'detailed'" ) - - return self.get_items(tree, test, self.mode) - - def get_json_items(self, json_content, test, mode): - dupes = dict() - rules = json_content["rules"] - issues = json_content["issues"] - for issue in issues: - key = issue["key"] - line = str(issue["line"]) - mitigation = issue["message"] - title = issue["description"] - file_path = issue["component"] - severity = self.convert_sonar_severity(issue["severity"]) - rule_id = issue["rule"] - - if title is None or mitigation is None: - raise ValueError( - "Parser ValueError: can't find a title or a mitigation for vulnerability of name " - + rule_id - ) - - try: - issue_detail = rules[rule_id] - parser = etree.HTMLParser() - html_desc_as_e_tree = etree.fromstring(issue_detail["htmlDesc"], parser) - issue_description = self.get_description(html_desc_as_e_tree) - logger.debug(issue_description) - issue_references = self.get_references( - rule_id, html_desc_as_e_tree - ) - issue_cwe = self.get_cwe(issue_references) - except KeyError: - issue_description = "No description provided" - issue_references = "" - issue_cwe = 0 - - if mode is None: - self.process_result_file_name_aggregated( - test, - dupes, - title, - issue_cwe, - issue_description, - file_path, - line, - severity, - mitigation, - issue_references, - ) - else: - self.process_result_detailed( - test, - dupes, - title, - issue_cwe, - issue_description, - file_path, - line, - severity, - mitigation, - issue_references, - key, - ) - return list(dupes.values()) - - def get_items(self, tree, test, mode): - # Check that there is at least one vulnerability (the vulnerabilities - # table is absent when no vuln are found) - detailTbody = tree.xpath( - "/html/body/div[contains(@class,'detail')]/table/tbody" - ) - dupes = dict() - if len(detailTbody) == 2: - # First is "Detail of the Detected Vulnerabilities" (not present if no vuln) - # Second is "Known Security Rules" - vulnerabilities_table = list(detailTbody[0].iter("tr")) - rules_table = list(detailTbody[1].xpath("tr")) - - # iterate over the rules once to get the information we need - rulesDic = dict() - for rule in rules_table: - rule_properties = list(rule.iter("td")) - rule_name = list(rule_properties[0].iter("a"))[0].text.strip() - rule_details = list(rule_properties[1].iter("details"))[0] - rulesDic[rule_name] = rule_details - - for vuln in vulnerabilities_table: - vuln_properties = list(vuln.iter("td")) - rule_key = list(vuln_properties[0].iter("a"))[0].text - vuln_rule_name = rule_key and rule_key.strip() - vuln_severity = self.convert_sonar_severity( - vuln_properties[1].text and vuln_properties[1].text.strip() - ) - vuln_file_path = vuln_properties[2].text and vuln_properties[2].text.strip() - vuln_line = vuln_properties[3].text and vuln_properties[3].text.strip() - vuln_title = vuln_properties[4].text and vuln_properties[4].text.strip() - vuln_mitigation = vuln_properties[5].text and vuln_properties[5].text.strip() - vuln_key = vuln_properties[6].text and vuln_properties[6].text.strip() - if vuln_title is None or vuln_mitigation is None: - raise ValueError( - "Parser ValueError: can't find a title or a mitigation for vulnerability of name " - + vuln_rule_name - ) - try: - vuln_details = rulesDic[vuln_rule_name] - vuln_description = self.get_description(vuln_details) - vuln_references = self.get_references( - vuln_rule_name, vuln_details - ) - vuln_cwe = self.get_cwe(vuln_references) - except KeyError: - vuln_description = "No description provided" - vuln_references = "" - vuln_cwe = 0 - if mode is None: - self.process_result_file_name_aggregated( - test, - dupes, - vuln_title, - vuln_cwe, - vuln_description, - vuln_file_path, - vuln_line, - vuln_severity, - vuln_mitigation, - vuln_references, - ) - else: - self.process_result_detailed( - test, - dupes, - vuln_title, - vuln_cwe, - vuln_description, - vuln_file_path, - vuln_line, - vuln_severity, - vuln_mitigation, - vuln_references, - vuln_key, - ) - return list(dupes.values()) - - # Process one vuln from the report for "SonarQube Scan detailed" - # Create the finding and add it into the dupes list - def process_result_detailed( - self, - test, - dupes, - vuln_title, - vuln_cwe, - vuln_description, - vuln_file_path, - vuln_line, - vuln_severity, - vuln_mitigation, - vuln_references, - vuln_key, - ): - # vuln_key is the unique id from tool which means that there is - # basically no aggregation except real duplicates - aggregateKeys = "{}{}{}{}{}".format( - vuln_cwe, vuln_title, vuln_description, vuln_file_path, vuln_key - ) - find = Finding( - title=vuln_title, - cwe=int(vuln_cwe), - description=vuln_description, - file_path=vuln_file_path, - line=vuln_line, - test=test, - severity=vuln_severity, - mitigation=vuln_mitigation, - references=vuln_references, - false_p=False, - duplicate=False, - out_of_scope=False, - mitigated=None, - impact="No impact provided", - static_finding=True, - dynamic_finding=False, - unique_id_from_tool=vuln_key, - ) - dupes[aggregateKeys] = find - - # Process one vuln from the report for "SonarQube Scan" - # Create the finding and add it into the dupes list - # For aggregated findings: - # - the description is enriched with each finding line number - # - the mitigation (message) is concatenated with each finding's mitigation value - def process_result_file_name_aggregated( - self, - test, - dupes, - vuln_title, - vuln_cwe, - vuln_description, - vuln_file_path, - vuln_line, - vuln_severity, - vuln_mitigation, - vuln_references, - ): - aggregateKeys = "{}{}{}{}".format( - vuln_cwe, vuln_title, vuln_description, vuln_file_path - ) - descriptionOneOccurence = "Line: {}".format(vuln_line) - if aggregateKeys not in dupes: - find = Finding( - title=vuln_title, - cwe=int(vuln_cwe), - description=vuln_description - + "\n\n-----\nOccurences:\n" - + descriptionOneOccurence, - file_path=vuln_file_path, - # No line number because we have aggregated different - # vulnerabilities that may have different line numbers - test=test, - severity=vuln_severity, - mitigation=vuln_mitigation, - references=vuln_references, - false_p=False, - duplicate=False, - out_of_scope=False, - mitigated=None, - impact="No impact provided", - static_finding=True, - dynamic_finding=False, - nb_occurences=1, - ) - dupes[aggregateKeys] = find - else: - # We have already created a finding for this aggregate: updates the - # description, nb_occurences and mitigation (message field in the - # report which may vary for each vuln) - find = dupes[aggregateKeys] - find.description = "{}\n{}".format( - find.description, descriptionOneOccurence - ) - find.mitigation = "{}\n______\n{}".format( - find.mitigation, vuln_mitigation - ) - find.nb_occurences = find.nb_occurences + 1 - - def convert_sonar_severity(self, sonar_severity): - sev = sonar_severity.lower() - if sev == "blocker": - return "Critical" - elif sev == "critical": - return "High" - elif sev == "major": - return "Medium" - elif sev == "minor": - return "Low" - else: - return "Info" - - def get_description(self, vuln_details): - rule_description = etree.tostring( - vuln_details, pretty_print=True - ).decode("utf-8", errors="replace") - rule_description = rule_description.split("

See", 1)[0] - rule_description = (str(rule_description)).replace("

", "**") - rule_description = (str(rule_description)).replace("

", "**") - rule_description = strip_tags(rule_description).strip() - return rule_description - - def get_references(self, rule_name, vuln_details): - rule_references = rule_name - for a in vuln_details.iter("a"): - rule_references += "\n" + str(a.text) - return rule_references - - def get_cwe(self, vuln_references): - # Match only the first CWE! - cweSearch = re.search("CWE-([0-9]*)", vuln_references, re.IGNORECASE) - if cweSearch: - return cweSearch.group(1) - else: - return 0 + return SonarQubeSoprasteriaHTML().get_items(tree, test, self.mode) diff --git a/dojo/tools/sonarqube/sonarqube_restapi_json.py b/dojo/tools/sonarqube/sonarqube_restapi_json.py new file mode 100644 index 0000000000..281e574ac6 --- /dev/null +++ b/dojo/tools/sonarqube/sonarqube_restapi_json.py @@ -0,0 +1,226 @@ +from dojo.models import Finding +import re + + +class SonarQubeRESTAPIJSON(object): + def get_json_items(self, json_content, test, mode): + items = [] + if json_content.get("issues"): + for issue in json_content.get("issues"): + if issue.get("type") == "BUG": + key = issue.get("key") + rule = issue.get("rule") + component = issue.get("component") + project = issue.get("project") + line = str(issue.get("line")) + textRange = str(issue.get("textRange")) + flows = str(issue.get("flows")) + status = issue.get("status") + message = issue.get("message") + tags = str(issue.get("tags")) + type = issue.get("type") + scope = issue.get("scope") + quickFixAvailable = str(issue.get("quickFixAvailable")) + codeVariants = str(issue.get("codeVariants")) + description = "" + description += "**key:** " + key + "\n" + description += "**rule:** " + rule + "\n" + description += "**component:** " + component + "\n" + description += "**project:** " + project + "\n" + description += "**line:** " + line + "\n" + description += "**textRange:** " + textRange + "\n" + description += "**flows:** " + flows + "\n" + description += "**status:** " + status + "\n" + description += "**message:** " + message + "\n" + description += "**tags:** " + tags + "\n" + description += "**type:** " + type + "\n" + description += "**scope:** " + scope + "\n" + description += self.returncomponent(json_content, component) + item = Finding( + title=rule + "_" + key, + description=description, + test=test, + severity=self.severitytranslator(issue.get("severity")), + static_finding=True, + dynamic_finding=False, + tags=["bug"], + ) + elif issue.get("type") == "VULNERABILITY": + key = issue.get("key") + rule = issue.get("rule") + component = issue.get("component") + project = issue.get("project") + flows = str(issue.get("flows")) + status = issue.get("status") + message = issue.get("message") + cve = None + if "Reference: CVE" in message: + cve_pattern = r'Reference: CVE-\d{4}-\d{4,7}' + cves = re.findall(cve_pattern, message) + if cves: + cve = cves[0].split("Reference: ")[1] + elif "References: CVE" in message: + cve_pattern = r'References: CVE-\d{4}-\d{4,7}' + cves = re.findall(cve_pattern, message) + if cves: + cve = cves[0].split("References: ")[1] + elif "Reference: GHSA" in message and cve is None: + cve_pattern = r'Reference: GHSA-[23456789cfghjmpqrvwx]{4}-[23456789cfghjmpqrvwx]{4}-[23456789cfghjmpqrvwx]{4}' + cves = re.findall(cve_pattern, message) + if cves: + cve = cves[0].split("Reference: ")[1] + elif "References: GHSA" in message and cve is None: + cve_pattern = r'References: GHSA-[23456789cfghjmpqrvwx]{4}-[23456789cfghjmpqrvwx]{4}-[23456789cfghjmpqrvwx]{4}' + cves = re.findall(cve_pattern, message) + if cves: + cve = cves[0].split("References: ")[1] + cwe = None + if "Category: CWE-" in message: + cwe_pattern = r'Category: CWE-\d{1,5}' + cwes = re.findall(cwe_pattern, message) + if cwes: + cwe = cwes[0].split("Category: CWE-")[1] + cvss = None + if "CVSS Score: " in message: + cvss_pattern = r'CVSS Score: \d{1}.\d{1}' + cvsss = re.findall(cvss_pattern, message) + if cvsss: + cvss = cvsss[0].split("CVSS Score: ")[1] + component_name = None + component_version = None + if "Filename: " in message and " | " in message: + component_pattern = r'Filename: .* \| ' + comp = re.findall(component_pattern, message) + if comp: + component_result = comp[0].split("Filename: ")[1].split(" | ")[0] + component_name = component_result.split(":")[0] + try: + component_version = component_result.split(":")[1] + except IndexError: + component_version = None + scope = issue.get("scope") + quickFixAvailable = str(issue.get("quickFixAvailable")) + codeVariants = str(issue.get("codeVariants")) + tags = str(issue.get("tags")) + description = "" + description += "**key:** " + key + "\n" + description += "**rule:** " + rule + "\n" + description += "**component:** " + component + "\n" + description += "**project:** " + project + "\n" + description += "**flows:** " + flows + "\n" + description += "**status:** " + status + "\n" + description += "**message:** " + message + "\n" + description += "**scope:** " + scope + "\n" + description += "**quickFixAvailable:** " + quickFixAvailable + "\n" + description += "**codeVariants:** " + codeVariants + "\n" + description += "**tags:** " + tags + "\n" + description += self.returncomponent(json_content, component) + item = Finding( + title=rule + "_" + key, + description=description, + test=test, + severity=self.severitytranslator(issue.get("severity")), + static_finding=True, + dynamic_finding=False, + component_name=component_name, + component_version=component_version, + cve=cve, + cwe=cwe, + cvssv3_score=cvss, + tags=["vulnerability"], + ) + elif issue.get("type") == "CODE_SMELL": + key = issue.get("key") + rule = issue.get("rule") + component = issue.get("component") + project = issue.get("project") + line = str(issue.get("line")) + textRange = str(issue.get("textRange")) + flows = str(issue.get("flows")) + status = issue.get("status") + message = issue.get("message") + tags = str(issue.get("tags")) + scope = issue.get("scope") + quickFixAvailable = str(issue.get("quickFixAvailable")) + codeVariants = str(issue.get("codeVariants")) + description = "" + description += "**rule:** " + rule + "\n" + description += "**component:** " + component + "\n" + description += "**project:** " + project + "\n" + description += "**line:** " + line + "\n" + description += "**textRange:** " + textRange + "\n" + description += "**flows:** " + flows + "\n" + description += "**status:** " + status + "\n" + description += "**message:** " + message + "\n" + description += "**tags:** " + tags + "\n" + description += "**scope:** " + scope + "\n" + description += "**quickFixAvailable:** " + quickFixAvailable + "\n" + description += "**codeVariants:** " + codeVariants + "\n" + description += self.returncomponent(json_content, component) + item = Finding( + title=rule + "_" + key, + description=description, + test=test, + severity=self.severitytranslator(issue.get("severity")), + static_finding=True, + dynamic_finding=False, + tags=["code_smell"], + ) + items.append(item) + if json_content.get("hotspots"): + for hotspot in json_content.get("hotspots"): + key = hotspot.get("key") + component = hotspot.get("component") + project = hotspot.get("project") + securityCategory = hotspot.get("securityCategory") + status = hotspot.get("status") + line = str(hotspot.get("line")) + message = hotspot.get("message") + textRange = str(hotspot.get("textRange")) + flows = str(hotspot.get("flows")) + ruleKey = hotspot.get("ruleKey") + messageFormattings = str(hotspot.get("messageFormattings")) + description = "" + description += "**key:** " + key + "\n" + description += "**component:** " + component + "\n" + description += "**project:** " + project + "\n" + description += "**securityCategory:** " + securityCategory + "\n" + description += "**status:** " + status + "\n" + description += "**line:** " + line + "\n" + description += "**message:** " + message + "\n" + description += "**textRange:** " + textRange + "\n" + description += "**flows:** " + flows + "\n" + description += "**ruleKey:** " + ruleKey + "\n" + description += "**messageFormattings:** " + messageFormattings + "\n" + description += self.returncomponent(json_content, component) + item = Finding( + title=ruleKey + "_" + key, + description=description, + test=test, + severity=self.severitytranslator(hotspot.get("vulnerabilityProbability")), + static_finding=True, + dynamic_finding=False, + tags=["hotspot"], + ) + items.append(item) + return items + + def severitytranslator(self, severity): + if severity == "BLOCKER": + return "High" + elif severity == "MAJOR": + return "Medium" + elif severity == "MINOR": + return "Low" + else: + return severity.lower().capitalize() + + def returncomponent(self, json_content, key): + components = json_content.get("components") + description = "" + for comp in components: + if comp.get("key") == key: + componentkeys = comp.keys() + for ck in componentkeys: + description += "**Componentkey " + ck + "**: " + str(comp.get(ck)) + "\n" + return description diff --git a/dojo/tools/sonarqube/sonarqube_restapi_zip.py b/dojo/tools/sonarqube/sonarqube_restapi_zip.py new file mode 100644 index 0000000000..0242939878 --- /dev/null +++ b/dojo/tools/sonarqube/sonarqube_restapi_zip.py @@ -0,0 +1,12 @@ +from dojo.tools.sonarqube.sonarqube_restapi_json import SonarQubeRESTAPIJSON +import json + + +class SonarQubeRESTAPIZIP(object): + def get_items(self, files, test, mode): + total_findings_per_file = list() + for dictkey in files.keys(): + if dictkey.endswith(".json"): + json_content = json.loads(files[dictkey].decode('ascii')) + total_findings_per_file += SonarQubeRESTAPIJSON().get_json_items(json_content, test, mode) + return total_findings_per_file diff --git a/dojo/tools/sonarqube/soprasteria_helper.py b/dojo/tools/sonarqube/soprasteria_helper.py new file mode 100644 index 0000000000..26f9662b8d --- /dev/null +++ b/dojo/tools/sonarqube/soprasteria_helper.py @@ -0,0 +1,146 @@ +import logging +import re +from django.utils.html import strip_tags +from lxml import etree +from dojo.models import Finding +logger = logging.getLogger(__name__) + + +class SonarQubeSoprasteriaHelper(object): + def convert_sonar_severity(self, sonar_severity): + sev = sonar_severity.lower() + if sev == "blocker": + return "Critical" + elif sev == "critical": + return "High" + elif sev == "major": + return "Medium" + elif sev == "minor": + return "Low" + else: + return "Info" + + def get_description(self, vuln_details): + rule_description = etree.tostring( + vuln_details, pretty_print=True + ).decode("utf-8", errors="replace") + rule_description = rule_description.split("

See", 1)[0] + rule_description = (str(rule_description)).replace("

", "**") + rule_description = (str(rule_description)).replace("

", "**") + rule_description = strip_tags(rule_description).strip() + return rule_description + + def get_references(self, rule_name, vuln_details): + rule_references = rule_name + for a in vuln_details.iter("a"): + rule_references += "\n" + str(a.text) + return rule_references + + def get_cwe(self, vuln_references): + # Match only the first CWE! + cweSearch = re.search("CWE-([0-9]*)", vuln_references, re.IGNORECASE) + if cweSearch: + return cweSearch.group(1) + else: + return 0 + + # Process one vuln from the report for "SonarQube Scan" + # Create the finding and add it into the dupes list + # For aggregated findings: + # - the description is enriched with each finding line number + # - the mitigation (message) is concatenated with each finding's mitigation value + def process_result_file_name_aggregated( + self, + test, + dupes, + vuln_title, + vuln_cwe, + vuln_description, + vuln_file_path, + vuln_line, + vuln_severity, + vuln_mitigation, + vuln_references, + ): + aggregateKeys = "{}{}{}{}".format( + vuln_cwe, vuln_title, vuln_description, vuln_file_path + ) + descriptionOneOccurence = "Line: {}".format(vuln_line) + if aggregateKeys not in dupes: + find = Finding( + title=vuln_title, + cwe=int(vuln_cwe), + description=vuln_description + + "\n\n-----\nOccurences:\n" + + descriptionOneOccurence, + file_path=vuln_file_path, + # No line number because we have aggregated different + # vulnerabilities that may have different line numbers + test=test, + severity=vuln_severity, + mitigation=vuln_mitigation, + references=vuln_references, + false_p=False, + duplicate=False, + out_of_scope=False, + mitigated=None, + impact="No impact provided", + static_finding=True, + dynamic_finding=False, + nb_occurences=1, + ) + dupes[aggregateKeys] = find + else: + # We have already created a finding for this aggregate: updates the + # description, nb_occurences and mitigation (message field in the + # report which may vary for each vuln) + find = dupes[aggregateKeys] + find.description = "{}\n{}".format( + find.description, descriptionOneOccurence + ) + find.mitigation = "{}\n______\n{}".format( + find.mitigation, vuln_mitigation + ) + find.nb_occurences = find.nb_occurences + 1 + + # Process one vuln from the report for "SonarQube Scan detailed" + # Create the finding and add it into the dupes list + def process_result_detailed( + self, + test, + dupes, + vuln_title, + vuln_cwe, + vuln_description, + vuln_file_path, + vuln_line, + vuln_severity, + vuln_mitigation, + vuln_references, + vuln_key, + ): + # vuln_key is the unique id from tool which means that there is + # basically no aggregation except real duplicates + aggregateKeys = "{}{}{}{}{}".format( + vuln_cwe, vuln_title, vuln_description, vuln_file_path, vuln_key + ) + find = Finding( + title=vuln_title, + cwe=int(vuln_cwe), + description=vuln_description, + file_path=vuln_file_path, + line=vuln_line, + test=test, + severity=vuln_severity, + mitigation=vuln_mitigation, + references=vuln_references, + false_p=False, + duplicate=False, + out_of_scope=False, + mitigated=None, + impact="No impact provided", + static_finding=True, + dynamic_finding=False, + unique_id_from_tool=vuln_key, + ) + dupes[aggregateKeys] = find diff --git a/dojo/tools/sonarqube/soprasteria_html.py b/dojo/tools/sonarqube/soprasteria_html.py new file mode 100644 index 0000000000..090fa59ec1 --- /dev/null +++ b/dojo/tools/sonarqube/soprasteria_html.py @@ -0,0 +1,83 @@ +import logging +from dojo.tools.sonarqube.soprasteria_helper import SonarQubeSoprasteriaHelper +logger = logging.getLogger(__name__) + + +class SonarQubeSoprasteriaHTML(object): + def get_items(self, tree, test, mode): + # Check that there is at least one vulnerability (the vulnerabilities + # table is absent when no vuln are found) + detailTbody = tree.xpath( + "/html/body/div[contains(@class,'detail')]/table/tbody" + ) + dupes = dict() + if len(detailTbody) == 2: + # First is "Detail of the Detected Vulnerabilities" (not present if no vuln) + # Second is "Known Security Rules" + vulnerabilities_table = list(detailTbody[0].iter("tr")) + rules_table = list(detailTbody[1].xpath("tr")) + + # iterate over the rules once to get the information we need + rulesDic = dict() + for rule in rules_table: + rule_properties = list(rule.iter("td")) + rule_name = list(rule_properties[0].iter("a"))[0].text.strip() + rule_details = list(rule_properties[1].iter("details"))[0] + rulesDic[rule_name] = rule_details + + for vuln in vulnerabilities_table: + vuln_properties = list(vuln.iter("td")) + rule_key = list(vuln_properties[0].iter("a"))[0].text + vuln_rule_name = rule_key and rule_key.strip() + vuln_severity = SonarQubeSoprasteriaHelper().convert_sonar_severity( + vuln_properties[1].text and vuln_properties[1].text.strip() + ) + vuln_file_path = vuln_properties[2].text and vuln_properties[2].text.strip() + vuln_line = vuln_properties[3].text and vuln_properties[3].text.strip() + vuln_title = vuln_properties[4].text and vuln_properties[4].text.strip() + vuln_mitigation = vuln_properties[5].text and vuln_properties[5].text.strip() + vuln_key = vuln_properties[6].text and vuln_properties[6].text.strip() + if vuln_title is None or vuln_mitigation is None: + raise ValueError( + "Parser ValueError: can't find a title or a mitigation for vulnerability of name " + + vuln_rule_name + ) + try: + vuln_details = rulesDic[vuln_rule_name] + vuln_description = SonarQubeSoprasteriaHelper().get_description(vuln_details) + vuln_references = SonarQubeSoprasteriaHelper().get_references( + vuln_rule_name, vuln_details + ) + vuln_cwe = SonarQubeSoprasteriaHelper().get_cwe(vuln_references) + except KeyError: + vuln_description = "No description provided" + vuln_references = "" + vuln_cwe = 0 + if mode is None: + SonarQubeSoprasteriaHelper().process_result_file_name_aggregated( + test, + dupes, + vuln_title, + vuln_cwe, + vuln_description, + vuln_file_path, + vuln_line, + vuln_severity, + vuln_mitigation, + vuln_references, + ) + else: + SonarQubeSoprasteriaHelper().process_result_detailed( + test, + dupes, + vuln_title, + vuln_cwe, + vuln_description, + vuln_file_path, + vuln_line, + vuln_severity, + vuln_mitigation, + vuln_references, + vuln_key, + ) + return list(dupes.values()) diff --git a/dojo/tools/sonarqube/soprasteria_json.py b/dojo/tools/sonarqube/soprasteria_json.py new file mode 100644 index 0000000000..b7e85011ad --- /dev/null +++ b/dojo/tools/sonarqube/soprasteria_json.py @@ -0,0 +1,69 @@ +import logging +from dojo.tools.sonarqube.soprasteria_helper import SonarQubeSoprasteriaHelper +from lxml import etree +logger = logging.getLogger(__name__) + + +class SonarQubeSoprasteriaJSON(object): + def get_json_items(self, json_content, test, mode): + dupes = dict() + rules = json_content["rules"] + issues = json_content["issues"] + for issue in issues: + key = issue["key"] + line = str(issue["line"]) + mitigation = issue["message"] + title = issue["description"] + file_path = issue["component"] + severity = SonarQubeSoprasteriaHelper().convert_sonar_severity(issue["severity"]) + rule_id = issue["rule"] + + if title is None or mitigation is None: + raise ValueError( + "Parser ValueError: can't find a title or a mitigation for vulnerability of name " + + rule_id + ) + + try: + issue_detail = rules[rule_id] + parser = etree.HTMLParser() + html_desc_as_e_tree = etree.fromstring(issue_detail["htmlDesc"], parser) + issue_description = SonarQubeSoprasteriaHelper().get_description(html_desc_as_e_tree) + logger.debug(issue_description) + issue_references = SonarQubeSoprasteriaHelper().get_references( + rule_id, html_desc_as_e_tree + ) + issue_cwe = SonarQubeSoprasteriaHelper().get_cwe(issue_references) + except KeyError: + issue_description = "No description provided" + issue_references = "" + issue_cwe = 0 + + if mode is None: + SonarQubeSoprasteriaHelper().process_result_file_name_aggregated( + test, + dupes, + title, + issue_cwe, + issue_description, + file_path, + line, + severity, + mitigation, + issue_references, + ) + else: + SonarQubeSoprasteriaHelper().process_result_detailed( + test, + dupes, + title, + issue_cwe, + issue_description, + file_path, + line, + severity, + mitigation, + issue_references, + key, + ) + return list(dupes.values()) diff --git a/unittests/scans/sonarqube/empty_zip.zip b/unittests/scans/sonarqube/empty_zip.zip new file mode 100644 index 0000000000000000000000000000000000000000..c82ad8319bb5ce8f89a008df7cf53236dfdc10ea GIT binary patch literal 174 zcmWIWW@h1H0D+5Z3M0S_D8a)Z!;qR=P*RzepOcbWq#qi>$-sOvOKb7~VR9n5d?*LQKUlk(CXkmJtYpfV3Nk!vFv*awSs$ literal 0 HcmV?d00001 diff --git a/unittests/scans/sonarqube/findings_over_api.json b/unittests/scans/sonarqube/findings_over_api.json new file mode 100644 index 0000000000..d39671bcda --- /dev/null +++ b/unittests/scans/sonarqube/findings_over_api.json @@ -0,0 +1,177 @@ +{ + "total": 42, + "p": 1, + "ps": 100, + "paging": { + "pageIndex": 1, + "pageSize": 100, + "total": 3 + }, + "effortTotal": 87, + "issues": [ + { + "key": "fjioefjwoefijo", + "rule": "OWASP:UsingComponentWithKnownVulnerability", + "severity": "MAJOR", + "component": "testapplication", + "project": "testapplication", + "flows": [], + "status": "OPEN", + "message": "Filename: package:1.1.2 | Reference: CVE-2024-2529 | CVSS Score: 6.4 | Category: CWE-120 | Versions of the package vulndescription .", + "author": "", + "tags": [ + "cve", + "cwe", + "cwe-937", + "owasp-a9", + "vulnerability" + ], + "creationDate": "2023-10-16T15:05:35+0000", + "updateDate": "2023-11-03T08:00:46+0000", + "type": "VULNERABILITY", + "scope": "MAIN", + "quickFixAvailable": false, + "messageFormattings": [], + "codeVariants": [] + }, + { + "key": "asdfwfewfwefewf", + "rule": "Web:TableWithoutCaptionCheck", + "severity": "MINOR", + "component": "testapplication:src/app/pages/fjiowefjewio/fjwieof/fjiwoe/details.html", + "project": "testapplication", + "line": 59, + "hash": "1de6211e802eff1bb25bff705a0a4cf5", + "textRange": { + "startLine": 59, + "endLine": 59, + "startOffset": 6, + "endOffset": 113 + }, + "flows": [], + "status": "OPEN", + "message": "Add a description to this table.", + "effort": "5min", + "debt": "5min", + "author": "name.name@name.de", + "tags": [ + "accessibility", + "wcag2-a" + ], + "creationDate": "2023-07-25T13:16:32+0000", + "updateDate": "2023-08-18T08:33:52+0000", + "type": "BUG", + "scope": "MAIN", + "quickFixAvailable": false, + "messageFormattings": [], + "codeVariants": [] + }, + { + "key": "fjoiewfjoweifjoihugu-", + "rule": "typescript:S1533", + "severity": "MINOR", + "component": "testapplication:src/app/services/fjweiofwefjiofiwofjwof.fjewoi", + "project": "testapplication", + "line": 15, + "hash": "fw0fu90weu90u3904u1094u1409", + "textRange": { + "startLine": 15, + "endLine": 15, + "startOffset": 49, + "endOffset": 56 + }, + "flows": [], + "status": "OPEN", + "message": "Replace this \"Boolean\" wrapper object with primitive type \"boolean\".", + "effort": "1min", + "debt": "1min", + "author": "name.name@name.de", + "tags": [ + "pitfall" + ], + "creationDate": "2024-01-29T13:50:11+0000", + "updateDate": "2024-01-29T13:50:11+0000", + "type": "CODE_SMELL", + "scope": "MAIN", + "quickFixAvailable": true, + "messageFormattings": [], + "codeVariants": [] + }, + { + "key": "fjioefjwoefisdfjo", + "rule": "OWASP:UsingComponentWithKnownVulnerability", + "severity": "MAJOR", + "component": "testapplication", + "project": "testapplication", + "flows": [], + "status": "OPEN", + "message": "Filename: package:1.1.2 | Reference: GHSA-frr2-c345-p7c2 | CVSS Score: 6.4 | Category: CWE-120 | Versions of the package vulndescription .", + "author": "", + "tags": [ + "cve", + "cwe", + "cwe-937", + "owasp-a9", + "vulnerability" + ], + "creationDate": "2023-10-16T15:05:35+0000", + "updateDate": "2023-11-03T08:00:46+0000", + "type": "VULNERABILITY", + "scope": "MAIN", + "quickFixAvailable": false, + "messageFormattings": [], + "codeVariants": [] + }, + { + "key": "fjioefjwoefisdfjo", + "rule": "OWASP:UsingComponentWithKnownVulnerability", + "severity": "CRITICAL", + "component": "testapplication", + "project": "testapplication", + "flows": [], + "status": "OPEN", + "message": "Filename: nimbus-jose-jwt-9.24.4.jar | Highest CVSS Score: 7.5 | Amount of CVSS: 1 | References: CVE-2023-52428 (7.5)", + "author": "", + "tags": [ + "cve", + "cwe", + "cwe-937", + "owasp-a9", + "vulnerability" + ], + "creationDate": "2023-10-16T15:05:35+0000", + "updateDate": "2023-11-03T08:00:46+0000", + "type": "VULNERABILITY", + "scope": "MAIN", + "quickFixAvailable": false, + "messageFormattings": [], + "codeVariants": [] + } + ], + "components": [ + { + "key": "testapplication", + "enabled": true, + "qualifier": "TRK", + "name": "testapplication", + "longName": "testapplication" + }, + { + "key": "testapplication:src/app/pages/fjiowefjewio/fjwieof/fjiwoe/details.html", + "enabled": true, + "qualifier": "FIL", + "name": "details.html", + "longName": "src/app/pages/fjiowefjewio/fjwieof/fjiwoe/details.html", + "path": "src/app/pages/fjiowefjewio/fjwieof/fjiwoe/details.html" + }, + { + "key": "testapplication:src/app/services/fjweiofwefjiofiwofjwof.fjewoi", + "enabled": true, + "qualifier": "FIL", + "name": "fjweiofwefjiofiwofjwof.fjewoi", + "longName": "src/app/services/fjweiofwefjiofiwofjwof.fjewoi", + "path": "src/app/services/fjweiofwefjiofiwofjwof.fjewoi" + } + ], + "facets": [] + } \ No newline at end of file diff --git a/unittests/scans/sonarqube/findings_over_api.zip b/unittests/scans/sonarqube/findings_over_api.zip new file mode 100644 index 0000000000000000000000000000000000000000..92a82faf5acc359d3ce5c6731780abc1870f92fa GIT binary patch literal 2466 zcmajhc{CJi9|!QkSX0zx?A_3vv1F36-3G-ZW$bi^Q6uZMGb4sugc!2RlETQEb#lpw z>>|B}YK$dDS!Sl}L!yLtwA{D1-p+fT^E=P)`R99{zdq+{Zp;M~0RRAe09=eWQVHB< zy$c8cC<_4qAb>Q$)!oP0-Ny}!_6>BwpfCElLp`v*J~r0;050b~mWz4QvdbmhE&vDc z+2Kwd1buyC!UfrH~#p-iwm7xc$tf}Sd z@)sq$)ULoOjddn65r4}T3UpX!OlRb_dR*~Ld@pd4yVR)nNQH;CTE?4Lgo%Sosp}Mm zUyMK7pr?~>*(99i*FPAg=B89_>vaBibooSFaW?rtl-xXlbr-DLi}$p0qts2+$G354{=!N=WnOR#*=QYZkF-}m?y0_+ z8~bX@5_XJnA}JS z5(~>KALihw_Vh7=gtYiD2#nas=?th6f^_}i?st8~ilR19Dl1u#r4K!5is49=l9daU zjOYTE&cOTg*CIi&!`Y8L)0}@P26rVyn+GXGVJ97q<`<+)C1~l%@0YIt`T17%E#>`n z2r7PA=_Pzjn@S^}N8sZ+=C8Liqp{rJj~`GaV!MkL;%43}&GF& zpk6Ds`voreXm!Sbupx?0B)10KEt3dU8P^{kl0gbPq&XHS7AOe~4_A*ISAe(;uk#G7 zy3>Mk3=|+t4IRz2#;Qf{kP3yC`px-mvIgO7IKnIid~qByqE$oM>tkA54-6%QRQ+XN zCR&KyE8^gE;CX=L!EE_{Mh&?Q+ z^FWJ5MWp>`>-H%+HAxU7lp4c*&tVNk*MGu?{8;HoS7hw5G)_e5R!U3Nrx!YcYi|~4 zXULFGE3e43Qe;|N(zk(2u}_WQ0jgB>+vcP0;$=FMRt*c$N#Z2>f~STp(ZQFu zgv|e;<-Uavvel?95W=QKpG}L{|Dr|hKelwWEW32D=LcJiv6EWDR~J{5?d>7p)Pyrj z?)(OI!?Hah!j`DxC{(*ocuX}cBmM@N(PH*5HZFqG{>VLDGx&j-!J*|2$gZ%jwj{D` z;oY(2YBDwXlPv~EF6`Liw>Gz9OAFf;6}Bzi^ujN;=-7U;g}!aqKpceARK^Ov*ph15 z%?&O78}rsH%{7HT4|9n!7q&taH5^Z^fp-bdO5K5=owB++4qcaZk>AUI1^w=vDt_Rx zUvyj_-DZcEm7nl3{Q4z*^)oMn&4)hmLbS+<`^rn)7hY=qKQB$EDYw7pCG;O&G`{0S z;#*$K{)?9zUwA?Lm4Cy_03>%YguuV`B;4&x3}Y5L0A9G7{kyJgXl3(6{^E^x9FErH zwRX!b$H#4n`J!52x_vT##I}4U2>~QAC#$sGUu!xbMNAlwk1uzsl$aI&nR ztrD_Atf6Rz^(O?5h=MVbu_Oi+tLi(d&=8)Yr|K^e;9Q(i4^r+s;mO%H4-K$u>dT{e z1PT>(v#E)na-!%DRLe>`-C|R-XNQ`L&3W(xl*%#&3&jGp zH=DLa018B;c1zj>w{|6xFPwyFw}G|ts?27aXQeq|+V|fmaxQ+h2B+7!wYhDg&9=tb z>^ID80#?{iwWlkqX?I{v<)br88#q!(RpW|>*Ovb}bsb2G2!KXJ_zIrFL~3ox4l*>D zHe3%ye4}rLpz;{n6Sk4lSChWD^Q-!EoO(Z!U9~H1iV<$a&QhG|#ois_Q*1gw2*kj%81@HfKX^#A>A#x*gImnN|m*4>B z?Koe*l{zB$W3$Mx51>m`=Z+>0BlLCc3@+WJq& ztBwh>PIt+*af?u;-Zp3CAo$l(6sB18JvE!OnJGPiJ)_Lvl16VrBUr_EnX4IfGxwoW zG0AOpm9~C<1cpoZesiUR%#y3*?Yoz*nW(aw)!j`nH|F5n&-JrXBhD^6000Mj3d47{ wpH&?0&lTr8g1*iEQMGTgQEcme$o^^^JAB8uAHunLcD}^PJ`dP8g>UEeZ|j$oUjP6A literal 0 HcmV?d00001 diff --git a/unittests/scans/sonarqube/findings_over_api_empty.json b/unittests/scans/sonarqube/findings_over_api_empty.json new file mode 100644 index 0000000000..07afd179d8 --- /dev/null +++ b/unittests/scans/sonarqube/findings_over_api_empty.json @@ -0,0 +1,14 @@ +{ + "total": 0, + "p": 1, + "ps": 100, + "paging": { + "pageIndex": 1, + "pageSize": 100, + "total": 0 + }, + "effortTotal": 0, + "issues": [], + "components": [], + "facets": [] + } \ No newline at end of file diff --git a/unittests/scans/sonarqube/findings_over_api_hotspots.json b/unittests/scans/sonarqube/findings_over_api_hotspots.json new file mode 100644 index 0000000000..bdf303e7f9 --- /dev/null +++ b/unittests/scans/sonarqube/findings_over_api_hotspots.json @@ -0,0 +1,127 @@ +{ + "paging": { + "pageIndex": 1, + "pageSize": 100, + "total": 4 + }, + "hotspots": [ + { + "key": "fwafewef", + "component": "nana-ofewfe:src/app/component.asdf", + "project": "nana-ofewfe", + "securityCategory": "xss", + "vulnerabilityProbability": "HIGH", + "status": "TO_REVIEW", + "line": 47, + "message": "Make sure disabling asdfbuilt-in sanitization is safe here.", + "author": "", + "creationDate": "2024-02-13T09:15:26+0000", + "updateDate": "2024-02-13T09:15:26+0000", + "textRange": { + "startLine": 47, + "endLine": 47, + "startOffset": 26, + "endOffset": 56 + }, + "flows": [], + "ruleKey": "typescript:7777", + "messageFormattings": [] + }, + { + "key": "cyxcvyxcvyxv", + "component": "keyfoot.htmlfjoes", + "project": "nana-ofewfe", + "securityCategory": "others", + "vulnerabilityProbability": "LOW", + "status": "TO_REVIEW", + "line": 5, + "message": "Make sure nasdfre.", + "author": "", + "creationDate": "2023-07-27T08:53:15+0000", + "updateDate": "2023-08-15T06:40:11+0000", + "textRange": { + "startLine": 5, + "endLine": 5, + "startOffset": 6, + "endOffset": 75 + }, + "flows": [], + "ruleKey": "Web:1222", + "messageFormattings": [] + }, + { + "key": "werrwerwerwer", + "component": "keyfoot.htmlfjoes", + "project": "nana-ofewfe", + "securityCategory": "others", + "vulnerabilityProbability": "LOW", + "status": "TO_REVIEW", + "line": 8, + "message": "Make sure no123123.", + "author": "", + "creationDate": "2023-07-27T08:53:15+0000", + "updateDate": "2023-08-15T06:40:11+0000", + "textRange": { + "startLine": 8, + "endLine": 8, + "startOffset": 6, + "endOffset": 77 + }, + "flows": [], + "ruleKey": "Web:9876", + "messageFormattings": [] + }, + { + "key": "jztjztjtzj", + "component": "nana-ofewfe:src/path/to//1231235/ccommp.html", + "project": "nana-ofewfe", + "securityCategory": "others", + "vulnerabilityProbability": "LOW", + "status": "TO_REVIEW", + "line": 3, + "message": "Make surgrgergrege.", + "author": "", + "creationDate": "2023-07-27T08:53:15+0000", + "updateDate": "2023-08-15T06:40:11+0000", + "textRange": { + "startLine": 3, + "endLine": 3, + "startOffset": 4, + "endOffset": 105 + }, + "flows": [], + "ruleKey": "Web:12345", + "messageFormattings": [] + } + ], + "components": [ + { + "key": "nana-ofewfe:src/path/to//1231235/ccommp.html", + "qualifier": "FIL", + "name": "ccommp.html", + "longName": "src/path/to//1231235/ccommp.html", + "path": "src/path/to//1231235/ccommp.html" + }, + { + "key": "nana-ofewfe", + "qualifier": "TRK", + "name": "nana-ofewfe", + "longName": "nana-ofewfe" + }, + { + "key": "keyfoot.htmlfjoes", + "qualifier": "FIL", + "name": "anonymous-footer.component.html", + "longName": "src/app/2389479284379021-footer.component.html", + "path": "src/app/2389479284379021-footer.component.html" + }, + { + "key": "nana-ofewfe:src/app/component.asdf", + "qualifier": "FIL", + "name": "component.asdf", + "longName": "src/app/component.asdf", + "path": "src/app/component.asdf" + } + ] +} + \ No newline at end of file diff --git a/unittests/tools/test_sonarqube_parser.py b/unittests/tools/test_sonarqube_parser.py index 04e048a633..3172407f82 100644 --- a/unittests/tools/test_sonarqube_parser.py +++ b/unittests/tools/test_sonarqube_parser.py @@ -547,3 +547,87 @@ def test_detailed_parse_json_file_with_multiple_vulnerabilities_has_multiple_fin # common verifications # (there is no aggregation to be done here) self.assertEqual(6, len(findings)) + + def test_parse_json_file_from_api_with_multiple_findings_json(self): + my_file_handle, _product, _engagement, test = self.init( + get_unit_tests_path() + "/scans/sonarqube/findings_over_api.json" + ) + parser = SonarQubeParser() + findings = parser.get_findings(my_file_handle, test) + self.assertEqual(5, len(findings)) + item = findings[0] + self.assertEqual(str, type(item.description)) + self.assertEqual("OWASP:UsingComponentWithKnownVulnerability_fjioefjwoefijo", item.title) + self.assertEqual("Medium", item.severity) + self.assertEqual("CVE-2024-2529", item.cve) + self.assertEqual("120", item.cwe) + self.assertEqual("6.4", item.cvssv3_score) + self.assertEqual("package", item.component_name) + self.assertEqual("1.1.2", item.component_version) + item = findings[1] + self.assertEqual("Web:TableWithoutCaptionCheck_asdfwfewfwefewf", item.title) + self.assertEqual("Low", item.severity) + self.assertIsNone(item.cve) + self.assertEqual(0, item.cwe) + self.assertIsNone(item.cvssv3_score) + item = findings[2] + self.assertEqual("typescript:S1533_fjoiewfjoweifjoihugu-", item.title) + self.assertEqual("Low", item.severity) + item = findings[3] + self.assertEqual("GHSA-frr2-c345-p7c2", item.cve) + item = findings[4] + self.assertEqual("CVE-2023-52428", item.cve) + self.assertEqual("nimbus-jose-jwt-9.24.4.jar", item.component_name) + self.assertIsNone(item.component_version) + + def test_parse_json_file_from_api_with_multiple_findings_hotspots_json(self): + my_file_handle, _product, _engagement, test = self.init( + get_unit_tests_path() + "/scans/sonarqube/findings_over_api_hotspots.json" + ) + parser = SonarQubeParser() + findings = parser.get_findings(my_file_handle, test) + self.assertEqual(4, len(findings)) + item = findings[0] + self.assertEqual(str, type(item.description)) + self.assertEqual("typescript:7777_fwafewef", item.title) + self.assertEqual("High", item.severity) + item = findings[1] + self.assertEqual("Web:1222_cyxcvyxcvyxv", item.title) + self.assertEqual("Low", item.severity) + item = findings[2] + self.assertEqual("Web:9876_werrwerwerwer", item.title) + self.assertEqual("Low", item.severity) + + def test_parse_json_file_from_api_with_empty_json(self): + my_file_handle, _product, _engagement, test = self.init( + get_unit_tests_path() + "/scans/sonarqube/findings_over_api_empty.json" + ) + parser = SonarQubeParser() + findings = parser.get_findings(my_file_handle, test) + self.assertEqual(0, len(findings)) + + def test_parse_json_file_from_api_with_emppty_zip(self): + my_file_handle, _product, _engagement, test = self.init( + get_unit_tests_path() + "/scans/sonarqube/empty_zip.zip" + ) + parser = SonarQubeParser() + findings = parser.get_findings(my_file_handle, test) + self.assertEqual(0, len(findings)) + + def test_parse_json_file_from_api_with_multiple_findings_zip(self): + my_file_handle, _product, _engagement, test = self.init( + get_unit_tests_path() + "/scans/sonarqube/findings_over_api.zip" + ) + parser = SonarQubeParser() + findings = parser.get_findings(my_file_handle, test) + self.assertEqual(6, len(findings)) + item = findings[0] + self.assertEqual(str, type(item.description)) + self.assertEqual("OWASP:UsingComponentWithKnownVulnerability_fjioefjwoefijo", item.title) + self.assertEqual("Medium", item.severity) + item = findings[3] + self.assertEqual("OWASP:UsingComponentWithKnownVulnerability_fjioefjwo1123efijo", item.title) + self.assertEqual("Low", item.severity) + item = findings[5] + self.assertEqual("typescript:S112533_fjoiewfjo1235gweifjoihugu-", item.title) + self.assertEqual("Medium", item.severity) From ba78a3dc4fd1fca728bedac07962cc0aa3c463be Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 Apr 2024 18:08:08 -0500 Subject: [PATCH 006/138] Update rabbitmq Docker tag from 3.13.0 to v3.13.1 (docker-compose.yml) (#9862) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index a56a39e751..2d00bbfccc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -149,7 +149,7 @@ services: volumes: - defectdojo_postgres:/var/lib/postgresql/data rabbitmq: - image: rabbitmq:3.13.0-alpine@sha256:b4abd8d41c68839068e8309067dd12c34c532d3effd81601f5f2a1587f5118d4 + image: rabbitmq:3.13.1-alpine@sha256:cd1b0e16575fd9885a03f2ae3b7d0fb4ee77b215a1127cf086397f7a55e8912b profiles: - mysql-rabbitmq - postgres-rabbitmq From a69b592afa135f1ac5884c2d05aebe1f66562b27 Mon Sep 17 00:00:00 2001 From: kiblik Date: Sat, 6 Apr 2024 02:38:32 +0200 Subject: [PATCH 007/138] Ruff: add pyupgrade (#9755) --- dojo/api_v2/mixins.py | 4 +- dojo/api_v2/permissions.py | 16 +- dojo/api_v2/serializers.py | 33 ++-- dojo/api_v2/views.py | 6 +- dojo/authorization/authorization.py | 6 +- dojo/celery.py | 2 +- dojo/components/sql_group_concat.py | 2 +- dojo/development_environment/views.py | 2 +- dojo/endpoint/utils.py | 46 ++--- dojo/endpoint/views.py | 13 +- dojo/engagement/views.py | 15 +- dojo/filters.py | 38 ++-- dojo/finding/helper.py | 2 +- dojo/finding/views.py | 76 +++----- dojo/finding_group/views.py | 2 +- dojo/forms.py | 176 +++++++++--------- dojo/group/views.py | 4 +- dojo/importers/importer/importer.py | 2 +- dojo/importers/reimporter/reimporter.py | 4 +- dojo/importers/utils.py | 2 +- dojo/jira_link/helper.py | 18 +- dojo/management/commands/dupecheck.py | 4 +- .../commands/import_github_languages.py | 4 +- dojo/management/commands/import_surveys.py | 4 +- dojo/metrics/views.py | 4 +- dojo/middleware.py | 4 +- dojo/models.py | 74 ++++---- dojo/notifications/helper.py | 16 +- dojo/okta.py | 2 +- dojo/product_type/views.py | 2 +- dojo/reports/widgets.py | 18 +- dojo/risk_acceptance/helper.py | 3 +- dojo/settings/settings.dist.py | 8 +- dojo/survey/views.py | 6 +- dojo/tasks.py | 12 +- dojo/templatetags/display_tags.py | 2 +- dojo/templatetags/navigation_tags.py | 2 +- dojo/test/views.py | 4 +- dojo/tools/acunetix/parse_acunetix360_json.py | 2 +- dojo/tools/acunetix/parse_acunetix_xml.py | 8 +- dojo/tools/acunetix/parser.py | 2 +- dojo/tools/anchore_engine/parser.py | 2 +- dojo/tools/anchore_enterprise/parser.py | 8 +- dojo/tools/anchore_grype/parser.py | 2 +- dojo/tools/anchorectl_policies/parser.py | 6 +- dojo/tools/anchorectl_vulns/parser.py | 2 +- dojo/tools/api_blackduck/api_client.py | 4 +- dojo/tools/api_blackduck/importer.py | 2 +- dojo/tools/api_blackduck/parser.py | 2 +- dojo/tools/api_bugcrowd/api_client.py | 24 +-- dojo/tools/api_bugcrowd/importer.py | 8 +- dojo/tools/api_bugcrowd/parser.py | 10 +- dojo/tools/api_cobalt/api_client.py | 18 +- dojo/tools/api_cobalt/importer.py | 2 +- dojo/tools/api_cobalt/parser.py | 2 +- dojo/tools/api_edgescan/api_client.py | 6 +- dojo/tools/api_edgescan/importer.py | 2 +- dojo/tools/api_edgescan/parser.py | 2 +- dojo/tools/api_sonarqube/importer.py | 2 +- dojo/tools/api_sonarqube/parser.py | 2 +- dojo/tools/api_sonarqube/updater.py | 12 +- .../api_sonarqube/updater_from_source.py | 10 +- dojo/tools/api_vulners/api_client.py | 4 +- dojo/tools/api_vulners/importer.py | 2 +- dojo/tools/api_vulners/parser.py | 2 +- dojo/tools/appspider/parser.py | 2 +- dojo/tools/aqua/parser.py | 14 +- dojo/tools/arachni/parser.py | 2 +- dojo/tools/asff/parser.py | 2 +- dojo/tools/auditjs/parser.py | 2 +- dojo/tools/aws_prowler/parser.py | 2 +- dojo/tools/aws_prowler_v3/parser.py | 2 +- dojo/tools/aws_scout2/parser.py | 30 ++- dojo/tools/awssecurityhub/compliance.py | 2 +- dojo/tools/awssecurityhub/guardduty.py | 2 +- dojo/tools/awssecurityhub/inspector.py | 2 +- dojo/tools/awssecurityhub/parser.py | 2 +- .../parser.py | 2 +- dojo/tools/bandit/parser.py | 2 +- dojo/tools/bearer_cli/parser.py | 2 +- dojo/tools/blackduck/importer.py | 4 +- dojo/tools/blackduck/parser.py | 36 ++-- .../blackduck_binary_analysis/importer.py | 2 +- .../tools/blackduck_binary_analysis/parser.py | 71 +++---- .../blackduck_component_risk/importer.py | 2 +- dojo/tools/blackduck_component_risk/parser.py | 2 +- dojo/tools/brakeman/parser.py | 2 +- dojo/tools/bugcrowd/parser.py | 2 +- dojo/tools/bundler_audit/parser.py | 2 +- dojo/tools/burp/parser.py | 2 +- dojo/tools/burp_api/parser.py | 2 +- dojo/tools/burp_dastardly/parser.py | 2 +- dojo/tools/burp_enterprise/parser.py | 2 +- dojo/tools/burp_graphql/parser.py | 2 +- dojo/tools/cargo_audit/parser.py | 2 +- dojo/tools/checkmarx/parser.py | 48 ++--- dojo/tools/checkmarx_one/parser.py | 2 +- dojo/tools/checkmarx_osa/parser.py | 4 +- dojo/tools/checkov/parser.py | 2 +- dojo/tools/chefinspect/parser.py | 2 +- dojo/tools/clair/clair_parser.py | 2 +- dojo/tools/clair/clairklar_parser.py | 2 +- dojo/tools/clair/parser.py | 2 +- dojo/tools/cloudsploit/parser.py | 2 +- dojo/tools/cobalt/parser.py | 2 +- dojo/tools/codechecker/parser.py | 10 +- dojo/tools/contrast/parser.py | 4 +- dojo/tools/coverity_api/parser.py | 2 +- dojo/tools/crashtest_security/parser.py | 6 +- dojo/tools/cred_scan/parser.py | 2 +- dojo/tools/crunch42/parser.py | 2 +- dojo/tools/cyclonedx/helpers.py | 2 +- dojo/tools/cyclonedx/json_parser.py | 6 +- dojo/tools/cyclonedx/parser.py | 2 +- dojo/tools/cyclonedx/xml_parser.py | 6 +- dojo/tools/dawnscanner/parser.py | 2 +- dojo/tools/dependency_check/parser.py | 20 +- dojo/tools/dependency_track/parser.py | 16 +- dojo/tools/detect_secrets/parser.py | 2 +- dojo/tools/dockerbench/parser.py | 4 +- dojo/tools/dockle/parser.py | 2 +- dojo/tools/drheader/parser.py | 2 +- dojo/tools/eslint/parser.py | 4 +- dojo/tools/fortify/fpr_parser.py | 2 +- dojo/tools/fortify/parser.py | 2 +- dojo/tools/fortify/xml_parser.py | 10 +- dojo/tools/gcloud_artifact_scan/parser.py | 2 +- dojo/tools/generic/parser.py | 4 +- dojo/tools/ggshield/parser.py | 2 +- dojo/tools/github_vulnerability/parser.py | 4 +- dojo/tools/gitlab_api_fuzzing/parser.py | 2 +- dojo/tools/gitlab_container_scan/parser.py | 2 +- dojo/tools/gitlab_dast/parser.py | 2 +- dojo/tools/gitlab_dep_scan/parser.py | 2 +- dojo/tools/gitlab_sast/parser.py | 2 +- .../gitlab_secret_detection_report/parser.py | 2 +- dojo/tools/gitleaks/parser.py | 2 +- dojo/tools/gosec/parser.py | 10 +- dojo/tools/h1/parser.py | 18 +- dojo/tools/hadolint/parser.py | 2 +- dojo/tools/harbor_vulnerability/parser.py | 2 +- dojo/tools/hcl_appscan/parser.py | 2 +- dojo/tools/horusec/parser.py | 2 +- dojo/tools/humble/parser.py | 2 +- dojo/tools/huskyci/parser.py | 2 +- dojo/tools/hydra/parser.py | 2 +- dojo/tools/ibm_app/parser.py | 2 +- dojo/tools/immuniweb/parser.py | 2 +- dojo/tools/intsights/parser.py | 2 +- .../jfrog_xray_api_summary_artifact/parser.py | 2 +- .../parser.py | 2 +- dojo/tools/jfrog_xray_unified/parser.py | 6 +- dojo/tools/jfrogxray/parser.py | 2 +- dojo/tools/kics/parser.py | 2 +- dojo/tools/kiuwan/parser.py | 2 +- dojo/tools/kubeaudit/parser.py | 2 +- dojo/tools/kubebench/parser.py | 2 +- dojo/tools/kubehunter/parser.py | 2 +- dojo/tools/kubescape/parser.py | 2 +- dojo/tools/mend/parser.py | 2 +- dojo/tools/meterian/parser.py | 2 +- dojo/tools/microfocus_webinspect/parser.py | 4 +- dojo/tools/mobsf/parser.py | 32 ++-- dojo/tools/mobsfscan/parser.py | 2 +- dojo/tools/mozilla_observatory/parser.py | 2 +- dojo/tools/ms_defender/parser.py | 2 +- dojo/tools/nancy/parser.py | 2 +- dojo/tools/netsparker/parser.py | 2 +- dojo/tools/neuvector/parser.py | 8 +- dojo/tools/neuvector_compliance/parser.py | 16 +- dojo/tools/nexpose/parser.py | 2 +- dojo/tools/nikto/json_parser.py | 2 +- dojo/tools/nikto/parser.py | 2 +- dojo/tools/nikto/xml_parser.py | 2 +- dojo/tools/nmap/parser.py | 11 +- dojo/tools/noseyparker/parser.py | 2 +- dojo/tools/npm_audit/parser.py | 2 +- dojo/tools/npm_audit_7_plus/parser.py | 15 +- dojo/tools/nsp/parser.py | 2 +- dojo/tools/nuclei/parser.py | 2 +- dojo/tools/openscap/parser.py | 22 +-- dojo/tools/openvas/csv_parser.py | 40 ++-- dojo/tools/openvas/parser.py | 2 +- dojo/tools/openvas/xml_parser.py | 2 +- dojo/tools/ort/parser.py | 2 +- dojo/tools/ossindex_devaudit/parser.py | 2 +- dojo/tools/osv_scanner/parser.py | 2 +- dojo/tools/outpost24/parser.py | 6 +- dojo/tools/parser_test.py | 2 +- dojo/tools/php_security_audit_v2/parser.py | 2 +- .../php_symfony_security_check/parser.py | 2 +- dojo/tools/pmd/parser.py | 4 +- dojo/tools/popeye/parser.py | 2 +- dojo/tools/pwn_sast/parser.py | 2 +- dojo/tools/qualys/parser.py | 6 +- dojo/tools/qualys_infrascan_webgui/parser.py | 2 +- dojo/tools/qualys_webapp/parser.py | 2 +- dojo/tools/redhatsatellite/parser.py | 2 +- dojo/tools/retirejs/parser.py | 2 +- dojo/tools/risk_recon/api.py | 12 +- dojo/tools/risk_recon/parser.py | 2 +- dojo/tools/rusty_hog/parser.py | 20 +- dojo/tools/sarif/parser.py | 6 +- dojo/tools/scantist/parser.py | 2 +- dojo/tools/scout_suite/parser.py | 15 +- dojo/tools/semgrep/parser.py | 8 +- dojo/tools/skf/parser.py | 12 +- dojo/tools/snyk/parser.py | 16 +- dojo/tools/snyk_code/parser.py | 16 +- dojo/tools/solar_appscreener/parser.py | 2 +- dojo/tools/sonarqube/parser.py | 2 +- .../tools/sonarqube/sonarqube_restapi_json.py | 2 +- dojo/tools/sonarqube/sonarqube_restapi_zip.py | 2 +- dojo/tools/sonarqube/soprasteria_helper.py | 20 +- dojo/tools/sonarqube/soprasteria_html.py | 2 +- dojo/tools/sonarqube/soprasteria_json.py | 2 +- dojo/tools/spotbugs/parser.py | 2 +- dojo/tools/ssh_audit/parser.py | 2 +- dojo/tools/ssl_labs/parser.py | 18 +- dojo/tools/sslscan/parser.py | 2 +- dojo/tools/sslyze/parser.py | 2 +- dojo/tools/sslyze/parser_json.py | 2 +- dojo/tools/sslyze/parser_xml.py | 2 +- dojo/tools/stackhawk/parser.py | 2 +- dojo/tools/sysdig_reports/parser.py | 2 +- dojo/tools/talisman/parser.py | 2 +- dojo/tools/tenable/csv_format.py | 2 +- dojo/tools/tenable/parser.py | 2 +- dojo/tools/tenable/xml_format.py | 2 +- dojo/tools/terrascan/parser.py | 2 +- dojo/tools/testssl/parser.py | 2 +- dojo/tools/tfsec/parser.py | 2 +- dojo/tools/threagile/parser.py | 2 +- dojo/tools/trufflehog/parser.py | 2 +- dojo/tools/trufflehog3/parser.py | 2 +- dojo/tools/trustwave/parser.py | 2 +- dojo/tools/trustwave_fusion_api/parser.py | 2 +- dojo/tools/twistlock/parser.py | 14 +- dojo/tools/vcg/parser.py | 8 +- dojo/tools/veracode/json_parser.py | 2 +- dojo/tools/veracode/parser.py | 2 +- dojo/tools/veracode/xml_parser.py | 12 +- dojo/tools/veracode_sca/parser.py | 10 +- dojo/tools/wapiti/parser.py | 2 +- dojo/tools/wazuh/parser.py | 2 +- dojo/tools/wfuzz/parser.py | 2 +- dojo/tools/whispers/parser.py | 2 +- dojo/tools/whitehat_sentinel/parser.py | 2 +- dojo/tools/wiz/parser.py | 2 +- dojo/tools/wpscan/parser.py | 2 +- dojo/tools/xanitizer/parser.py | 32 ++-- dojo/tools/yarn_audit/parser.py | 2 +- dojo/tools/zap/parser.py | 2 +- dojo/user/validators.py | 12 +- dojo/utils.py | 67 +++---- dojo/views.py | 4 +- dojo/wsgi.py | 4 +- pyproject.toml | 2 +- tests/announcement_banner_test.py | 2 +- tests/base_test_class.py | 2 +- tests/notifications_test.py | 18 +- tests/product_test.py | 4 +- tests/zap.py | 18 +- unittests/dojo_test_case.py | 4 +- unittests/test_adminsite.py | 4 +- unittests/test_bulk_risk_acceptance_api.py | 18 +- unittests/test_deduplication_logic.py | 10 +- unittests/test_endpoint_meta_import.py | 2 +- unittests/test_endpoint_model.py | 2 +- .../test_false_positive_history_logic.py | 14 +- unittests/test_import_reimport.py | 2 +- unittests/test_importers_importer.py | 4 +- unittests/test_jira_config_engagement.py | 2 +- unittests/test_jira_import_and_pushing_api.py | 2 +- unittests/test_parsers.py | 2 +- unittests/test_rest_framework.py | 8 +- unittests/test_utils.py | 2 +- unittests/tools/test_asff_parser.py | 8 +- .../tools/test_dependency_check_parser.py | 2 +- unittests/tools/test_generic_parser.py | 2 +- unittests/tools/test_tenable_parser.py | 2 +- unittests/tools/test_vcg_parser.py | 2 +- 282 files changed, 874 insertions(+), 1135 deletions(-) diff --git a/dojo/api_v2/mixins.py b/dojo/api_v2/mixins.py index 54d55a76d0..4e2791aec5 100644 --- a/dojo/api_v2/mixins.py +++ b/dojo/api_v2/mixins.py @@ -47,11 +47,11 @@ def flatten(elem): return self.get_paginated_response(serializer.data) -class QuestionSubClassFieldsMixin(object): +class QuestionSubClassFieldsMixin: def get_queryset(self): return Question.objects.select_subclasses() -class AnswerSubClassFieldsMixin(object): +class AnswerSubClassFieldsMixin: def get_queryset(self): return Answer.objects.select_subclasses() diff --git a/dojo/api_v2/permissions.py b/dojo/api_v2/permissions.py index 4c0e8c6e2e..b9c2ec433b 100644 --- a/dojo/api_v2/permissions.py +++ b/dojo/api_v2/permissions.py @@ -40,9 +40,7 @@ def check_post_permission(request, post_model, post_pk, post_permission): if request.method == "POST": if request.data.get(post_pk) is None: raise ParseError( - "Unable to check for permissions: Attribute '{}' is required".format( - post_pk - ) + f"Unable to check for permissions: Attribute '{post_pk}' is required" ) object = get_object_or_404(post_model, pk=request.data.get(post_pk)) return user_has_permission(request.user, object, post_permission) @@ -965,8 +963,7 @@ def raise_no_auto_create_import_validation_error( if product_name and not product: if product_type_name: raise serializers.ValidationError( - "Product '%s' doesn't exist in Product_Type '%s'" - % (product_name, product_type_name) + f"Product '{product_name}' doesn't exist in Product_Type '{product_type_name}'" ) else: raise serializers.ValidationError( @@ -975,21 +972,18 @@ def raise_no_auto_create_import_validation_error( if engagement_name and not engagement: raise serializers.ValidationError( - "Engagement '%s' doesn't exist in Product '%s'" - % (engagement_name, product_name) + f"Engagement '{engagement_name}' doesn't exist in Product '{product_name}'" ) # these are only set for reimport if test_title: raise serializers.ValidationError( - "Test '%s' with scan_type '%s' doesn't exist in Engagement '%s'" - % (test_title, scan_type, engagement_name) + f"Test '{test_title}' with scan_type '{scan_type}' doesn't exist in Engagement '{engagement_name}'" ) if scan_type: raise serializers.ValidationError( - "Test with scan_type '%s' doesn't exist in Engagement '%s'" - % (scan_type, engagement_name) + f"Test with scan_type '{scan_type}' doesn't exist in Engagement '{engagement_name}'" ) raise ValidationError(error_message) diff --git a/dojo/api_v2/serializers.py b/dojo/api_v2/serializers.py index 69a684d1cf..a39397b8de 100644 --- a/dojo/api_v2/serializers.py +++ b/dojo/api_v2/serializers.py @@ -245,7 +245,7 @@ def __init__(self, **kwargs): kwargs["style"] = {"base_template": "textarea.html"} kwargs["style"].update(style) - super(TagListSerializerField, self).__init__(**kwargs) + super().__init__(**kwargs) self.pretty_print = pretty_print @@ -300,14 +300,14 @@ class TaggitSerializer(serializers.Serializer): def create(self, validated_data): to_be_tagged, validated_data = self._pop_tags(validated_data) - tag_object = super(TaggitSerializer, self).create(validated_data) + tag_object = super().create(validated_data) return self._save_tags(tag_object, to_be_tagged) def update(self, instance, validated_data): to_be_tagged, validated_data = self._pop_tags(validated_data) - tag_object = super(TaggitSerializer, self).update( + tag_object = super().update( instance, validated_data ) @@ -389,7 +389,7 @@ def __init__(self, **kwargs): if isinstance(data, list): kwargs["many"] = True - super(RequestResponseSerializerField, self).__init__(**kwargs) + super().__init__(**kwargs) self.pretty_print = pretty_print @@ -1464,10 +1464,7 @@ def to_representation(self, data): new_files.append( { "id": file.id, - "file": "{site_url}/{file_access_url}".format( - site_url=settings.SITE_URL, - file_access_url=file.get_accessible_url(test, test.id), - ), + "file": f"{settings.SITE_URL}/{file.get_accessible_url(test, test.id)}", "title": file.title, } ) @@ -2306,13 +2303,11 @@ def validate(self, data): file = data.get("file") if not file and requires_file(scan_type): raise serializers.ValidationError( - "Uploading a Report File is required for {}".format(scan_type) + f"Uploading a Report File is required for {scan_type}" ) if file and is_scan_file_too_large(file): raise serializers.ValidationError( - "Report file is too large. Maximum supported size is {} MB".format( - settings.SCAN_FILE_MAX_SIZE - ) + f"Report file is too large. Maximum supported size is {settings.SCAN_FILE_MAX_SIZE} MB" ) tool_type = requires_tool_type(scan_type) if tool_type: @@ -2665,13 +2660,11 @@ def validate(self, data): file = data.get("file") if not file and requires_file(scan_type): raise serializers.ValidationError( - "Uploading a Report File is required for {}".format(scan_type) + f"Uploading a Report File is required for {scan_type}" ) if file and is_scan_file_too_large(file): raise serializers.ValidationError( - "Report file is too large. Maximum supported size is {} MB".format( - settings.SCAN_FILE_MAX_SIZE - ) + f"Report file is too large. Maximum supported size is {settings.SCAN_FILE_MAX_SIZE} MB" ) tool_type = requires_tool_type(scan_type) if tool_type: @@ -2712,9 +2705,7 @@ def validate(self, data): file = data.get("file") if file and is_scan_file_too_large(file): raise serializers.ValidationError( - "Report file is too large. Maximum supported size is {} MB".format( - settings.SCAN_FILE_MAX_SIZE - ) + f"Report file is too large. Maximum supported size is {settings.SCAN_FILE_MAX_SIZE} MB" ) return data @@ -2818,9 +2809,7 @@ def save(self): def validate(self, data): if is_scan_file_too_large(data["file"]): raise serializers.ValidationError( - "File is too large. Maximum supported size is {} MB".format( - settings.SCAN_FILE_MAX_SIZE - ) + f"File is too large. Maximum supported size is {settings.SCAN_FILE_MAX_SIZE} MB" ) return data diff --git a/dojo/api_v2/views.py b/dojo/api_v2/views.py index 2149a86a35..ff73d2f01f 100644 --- a/dojo/api_v2/views.py +++ b/dojo/api_v2/views.py @@ -1214,9 +1214,7 @@ def remove_tags(self, request, pk=None): if tag not in all_tags: return Response( { - "error": "'{}' is not a valid tag in list".format( - tag - ) + "error": f"'{tag}' is not a valid tag in list" }, status=status.HTTP_400_BAD_REQUEST, ) @@ -2877,7 +2875,7 @@ def report_generate(request, obj, options): include_executive_summary = False include_table_of_contents = False - report_info = "Generated By %s on %s" % ( + report_info = "Generated By {} on {}".format( user.get_full_name(), (timezone.now().strftime("%m/%d/%Y %I:%M%p %Z")), ) diff --git a/dojo/authorization/authorization.py b/dojo/authorization/authorization.py index 69f3884a4c..1cbef9ecd6 100644 --- a/dojo/authorization/authorization.py +++ b/dojo/authorization/authorization.py @@ -259,7 +259,7 @@ def user_has_global_permission_or_403(user, permission): def get_roles_for_permission(permission): if not Permissions.has_value(permission): raise PermissionDoesNotExistError( - "Permission {} does not exist".format(permission) + f"Permission {permission} does not exist" ) roles_for_permissions = set() roles = get_roles_with_permissions() @@ -274,7 +274,7 @@ def role_has_permission(role, permission): if role is None: return False if not Roles.has_value(role): - raise RoleDoesNotExistError("Role {} does not exist".format(role)) + raise RoleDoesNotExistError(f"Role {role} does not exist") roles = get_roles_with_permissions() permissions = roles.get(role) if not permissions: @@ -286,7 +286,7 @@ def role_has_global_permission(role, permission): if role is None: return False if not Roles.has_value(role): - raise RoleDoesNotExistError("Role {} does not exist".format(role)) + raise RoleDoesNotExistError(f"Role {role} does not exist") roles = get_global_roles_with_permissions() permissions = roles.get(role) if permissions and permission in permissions: diff --git a/dojo/celery.py b/dojo/celery.py index f2d73f0386..1fbf6e73fc 100644 --- a/dojo/celery.py +++ b/dojo/celery.py @@ -20,7 +20,7 @@ @app.task(bind=True) def debug_task(self): - print(('Request: {0!r}'.format(self.request))) + print(f'Request: {self.request!r}') @setup_logging.connect diff --git a/dojo/components/sql_group_concat.py b/dojo/components/sql_group_concat.py index 5aa8f10d64..ba23b24e38 100644 --- a/dojo/components/sql_group_concat.py +++ b/dojo/components/sql_group_concat.py @@ -9,7 +9,7 @@ def __init__( self, expression, separator, distinct=False, ordering=None, **extra ): self.separator = separator - super(Sql_GroupConcat, self).__init__( + super().__init__( expression, distinct="DISTINCT " if distinct else "", ordering=" ORDER BY %s" % ordering if ordering is not None else "", diff --git a/dojo/development_environment/views.py b/dojo/development_environment/views.py index d6d4c167b1..8de454f1a8 100644 --- a/dojo/development_environment/views.py +++ b/dojo/development_environment/views.py @@ -85,7 +85,7 @@ def edit_dev_env(request, deid): except RestrictedError as err: messages.add_message(request, messages.WARNING, - 'Environment cannot be deleted: {}'.format(err), + f'Environment cannot be deleted: {err}', extra_tags='alert-warning') return HttpResponseRedirect(reverse('dev_env')) diff --git a/dojo/endpoint/utils.py b/dojo/endpoint/utils.py index f52a46311c..4c404a3275 100644 --- a/dojo/endpoint/utils.py +++ b/dojo/endpoint/utils.py @@ -92,7 +92,7 @@ def clean_hosts_run(apps, change): def err_log(message, html_log, endpoint_html_log, endpoint): error_suffix = 'It is not possible to migrate it. Delete or edit this endpoint.' html_log.append({**endpoint_html_log, **{'message': message}}) - logger.error('Endpoint (id={}) {}. {}'.format(endpoint.pk, message, error_suffix)) + logger.error(f'Endpoint (id={endpoint.pk}) {message}. {error_suffix}') broken_endpoints.add(endpoint.pk) html_log = [] broken_endpoints = set() @@ -120,8 +120,8 @@ def err_log(message, html_log, endpoint_html_log, endpoint): if parts.protocol: if endpoint.protocol and (endpoint.protocol != parts.protocol): - message = 'has defined protocol ({}) and it is not the same as protocol in host ' \ - '({})'.format(endpoint.protocol, parts.protocol) + message = f'has defined protocol ({endpoint.protocol}) and it is not the same as protocol in host ' \ + f'({parts.protocol})' err_log(message, html_log, endpoint_html_log, endpoint) else: if change: @@ -135,26 +135,26 @@ def err_log(message, html_log, endpoint_html_log, endpoint): if change: endpoint.host = parts.host else: - message = '"{}" use invalid format of host'.format(endpoint.host) + message = f'"{endpoint.host}" use invalid format of host' err_log(message, html_log, endpoint_html_log, endpoint) if parts.port: try: if (endpoint.port is not None) and (int(endpoint.port) != parts.port): - message = 'has defined port number ({}) and it is not the same as port number in ' \ - 'host ({})'.format(endpoint.port, parts.port) + message = f'has defined port number ({endpoint.port}) and it is not the same as port number in ' \ + f'host ({parts.port})' err_log(message, html_log, endpoint_html_log, endpoint) else: if change: endpoint.port = parts.port except ValueError: - message = 'uses non-numeric port: {}'.format(endpoint.port) + message = f'uses non-numeric port: {endpoint.port}' err_log(message, html_log, endpoint_html_log, endpoint) if parts.path: if endpoint.path and (endpoint.path != parts.path): - message = 'has defined path ({}) and it is not the same as path in host ' \ - '({})'.format(endpoint.path, parts.path) + message = f'has defined path ({endpoint.path}) and it is not the same as path in host ' \ + f'({parts.path})' err_log(message, html_log, endpoint_html_log, endpoint) else: if change: @@ -162,8 +162,8 @@ def err_log(message, html_log, endpoint_html_log, endpoint): if parts.query: if endpoint.query and (endpoint.query != parts.query): - message = 'has defined query ({}) and it is not the same as query in host ' \ - '({})'.format(endpoint.query, parts.query) + message = f'has defined query ({endpoint.query}) and it is not the same as query in host ' \ + f'({parts.query})' err_log(message, html_log, endpoint_html_log, endpoint) else: if change: @@ -171,8 +171,8 @@ def err_log(message, html_log, endpoint_html_log, endpoint): if parts.fragment: if endpoint.fragment and (endpoint.fragment != parts.fragment): - message = 'has defined fragment ({}) and it is not the same as fragment in host ' \ - '({})'.format(endpoint.fragment, parts.fragment) + message = f'has defined fragment ({endpoint.fragment}) and it is not the same as fragment in host ' \ + f'({parts.fragment})' err_log(message, html_log, endpoint_html_log, endpoint) else: if change: @@ -182,7 +182,7 @@ def err_log(message, html_log, endpoint_html_log, endpoint): endpoint.save() except ValidationError: - message = '"{}" uses invalid format of host'.format(endpoint.host) + message = f'"{endpoint.host}" uses invalid format of host' err_log(message, html_log, endpoint_html_log, endpoint) try: @@ -197,8 +197,8 @@ def err_log(message, html_log, endpoint_html_log, endpoint): err_log('Missing product', html_log, endpoint_html_log, endpoint) if broken_endpoints: - logger.error('It is not possible to migrate database because there is/are {} broken endpoint(s). ' - 'Please check logs.'.format(len(broken_endpoints))) + logger.error(f'It is not possible to migrate database because there is/are {len(broken_endpoints)} broken endpoint(s). ' + 'Please check logs.') else: logger.info('There is not broken endpoint.') @@ -223,8 +223,8 @@ def err_log(message, html_log, endpoint_html_log, endpoint): to_be_deleted.update(ep_ids[1:]) if change: message = "Merging Endpoints {} into '{}'".format( - ["{} (id={})".format(str(x), x.pk) for x in ep[1:]], - "{} (id={})".format(str(ep[0]), ep[0].pk)) + [f"{str(x)} (id={x.pk})" for x in ep[1:]], + f"{str(ep[0])} (id={ep[0].pk})") html_log.append(message) logger.info(message) Endpoint_Status_model.objects\ @@ -240,18 +240,18 @@ def err_log(message, html_log, endpoint_html_log, endpoint): .filter(finding=eps['finding'])\ .order_by('-last_modified') message = "Endpoint Statuses {} will be replaced by '{}'".format( - ["last_modified: {} (id={})".format(x.last_modified, x.pk) for x in esm[1:]], - "last_modified: {} (id={})".format(esm[0].last_modified, esm[0].pk)) + [f"last_modified: {x.last_modified} (id={x.pk})" for x in esm[1:]], + f"last_modified: {esm[0].last_modified} (id={esm[0].pk})") html_log.append(message) logger.info(message) esm.exclude(id=esm[0].pk).delete() if to_be_deleted: if change: - message = "Removing endpoints: {}".format(list(to_be_deleted)) + message = f"Removing endpoints: {list(to_be_deleted)}" Endpoint_model.objects.filter(id__in=to_be_deleted).delete() else: - message = "Redundant endpoints: {}, migration is required.".format(list(to_be_deleted)) + message = f"Redundant endpoints: {list(to_be_deleted)}, migration is required." html_log.append(message) logger.info(message) @@ -283,7 +283,7 @@ def validate_endpoints_to_add(endpoints_to_add): except ValidationError as ves: for ve in ves: errors.append( - ValidationError("Invalid endpoint {}: {}".format(endpoint, ve)) + ValidationError(f"Invalid endpoint {endpoint}: {ve}") ) return endpoint_list, errors diff --git a/dojo/endpoint/views.py b/dojo/endpoint/views.py index d35a139098..dbe0956d10 100644 --- a/dojo/endpoint/views.py +++ b/dojo/endpoint/views.py @@ -216,7 +216,7 @@ def delete_endpoint(request, eid): create_notification(event='other', title='Deletion of %s' % endpoint, product=product, - description='The endpoint "%s" was deleted by %s' % (endpoint, request.user), + description=f'The endpoint "{endpoint}" was deleted by {request.user}', url=reverse('endpoint'), icon="exclamation-triangle") return HttpResponseRedirect(reverse('view_product', args=(product.id,))) @@ -372,12 +372,12 @@ def endpoint_bulk_update_all(request, pid=None): calculate_grade(prod) if skipped_endpoint_count > 0: - add_error_message_to_response('Skipped deletion of {} endpoints because you are not authorized.'.format(skipped_endpoint_count)) + add_error_message_to_response(f'Skipped deletion of {skipped_endpoint_count} endpoints because you are not authorized.') if deleted_endpoint_count > 0: messages.add_message(request, messages.SUCCESS, - 'Bulk delete of {} endpoints was successful.'.format(deleted_endpoint_count), + f'Bulk delete of {deleted_endpoint_count} endpoints was successful.', extra_tags='alert-success') else: if endpoints_to_update: @@ -392,7 +392,7 @@ def endpoint_bulk_update_all(request, pid=None): updated_endpoint_count = endpoints.count() if skipped_endpoint_count > 0: - add_error_message_to_response('Skipped mitigation of {} endpoints because you are not authorized.'.format(skipped_endpoint_count)) + add_error_message_to_response(f'Skipped mitigation of {skipped_endpoint_count} endpoints because you are not authorized.') eps_count = Endpoint_Status.objects.filter(endpoint__in=endpoints).update( mitigated=True, @@ -404,8 +404,7 @@ def endpoint_bulk_update_all(request, pid=None): if updated_endpoint_count > 0: messages.add_message(request, messages.SUCCESS, - 'Bulk mitigation of {} endpoints ({} endpoint statuses) was successful.'.format( - updated_endpoint_count, eps_count), + f'Bulk mitigation of {updated_endpoint_count} endpoints ({eps_count} endpoint statuses) was successful.', extra_tags='alert-success') else: messages.add_message(request, @@ -488,7 +487,7 @@ def import_endpoint_meta(request, pid): messages.add_message( request, messages.ERROR, - "Report file is too large. Maximum supported size is {} MB".format(settings.SCAN_FILE_MAX_SIZE), + f"Report file is too large. Maximum supported size is {settings.SCAN_FILE_MAX_SIZE} MB", extra_tags='alert-danger') create_endpoints = form.cleaned_data['create_endpoints'] diff --git a/dojo/engagement/views.py b/dojo/engagement/views.py index 230c18cc3a..45bb5009c8 100644 --- a/dojo/engagement/views.py +++ b/dojo/engagement/views.py @@ -310,7 +310,7 @@ def delete_engagement(request, eid): create_notification(event='other', title='Deletion of %s' % engagement.name, product=product, - description='The engagement "%s" was deleted by %s' % (engagement.name, request.user), + description=f'The engagement "{engagement.name}" was deleted by {request.user}', url=request.build_absolute_uri(reverse('view_engagements', args=(product.id, ))), recipients=[engagement.lead], icon="exclamation-triangle") @@ -352,7 +352,7 @@ def copy_engagement(request, eid): extra_tags='alert-success') create_notification(event='other', title='Copying of %s' % engagement.name, - description='The engagement "%s" was copied by %s' % (engagement.name, request.user), + description=f'The engagement "{engagement.name}" was copied by {request.user}', product=product, url=request.build_absolute_uri(reverse('view_engagement', args=(engagement_copy.id, ))), recipients=[engagement.lead], @@ -504,7 +504,7 @@ def post(self, request, eid, *args, **kwargs): form = TypedNoteForm(available_note_types=available_note_types) else: form = NoteForm() - title = "Engagement: %s on %s" % (eng.name, eng.product.name) + title = f"Engagement: {eng.name} on {eng.product.name}" messages.add_message(request, messages.SUCCESS, 'Note added successfully.', @@ -755,7 +755,7 @@ def post(self, request, eid=None, pid=None): if scan and is_scan_file_too_large(scan): messages.add_message(request, messages.ERROR, - "Report file is too large. Maximum supported size is {} MB".format(settings.SCAN_FILE_MAX_SIZE), + f"Report file is too large. Maximum supported size is {settings.SCAN_FILE_MAX_SIZE} MB", extra_tags='alert-danger') return HttpResponseRedirect(reverse('import_scan_results', args=(engagement,))) @@ -1288,11 +1288,10 @@ def engagement_ics(request, eid): uid = "dojo_eng_%d_%d" % (eng.id, eng.product.id) cal = get_cal_event( start_date, end_date, - "Engagement: %s (%s)" % (eng.name, eng.product.name), - "Set aside for engagement %s, on product %s. Additional detail can be found at %s" - % (eng.name, eng.product.name, + f"Engagement: {eng.name} ({eng.product.name})", + "Set aside for engagement {}, on product {}. Additional detail can be found at {}".format(eng.name, eng.product.name, request.build_absolute_uri( - (reverse("view_engagement", args=(eng.id, ))))), uid) + reverse("view_engagement", args=(eng.id, )))), uid) output = cal.serialize() response = HttpResponse(content=output) response['Content-Type'] = 'text/calendar' diff --git a/dojo/filters.py b/dojo/filters.py index 4f1f3c539a..f5726fb4a8 100644 --- a/dojo/filters.py +++ b/dojo/filters.py @@ -131,7 +131,7 @@ def under_review(self, qs, name): def __init__(self, *args, **kwargs): kwargs['choices'] = [ (key, value[0]) for key, value in six.iteritems(self.options)] - super(FindingStatusFilter, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def filter(self, qs, value): earliest_finding = get_earliest_finding(qs) @@ -179,7 +179,7 @@ def sla_violated(self, qs, name): def __init__(self, *args, **kwargs): kwargs['choices'] = [ (key, value[0]) for key, value in six.iteritems(self.options)] - super(FindingSLAFilter, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def filter(self, qs, value): try: @@ -214,7 +214,7 @@ def sla_violated(self, qs, name): def __init__(self, *args, **kwargs): kwargs['choices'] = [ (key, value[0]) for key, value in six.iteritems(self.options)] - super(ProductSLAFilter, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def filter(self, qs, value): try: @@ -246,7 +246,7 @@ def cwe_options(queryset): class DojoFilter(FilterSet): def __init__(self, *args, **kwargs): - super(DojoFilter, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) for field in ['tags', 'test__tags', 'test__engagement__tags', 'test__engagement__product__tags', 'not_tags', 'not_test__tags', 'not_test__engagement__tags', 'not_test__engagement__product__tags']: @@ -483,7 +483,7 @@ class DateRangeFilter(ChoiceFilter): def __init__(self, *args, **kwargs): kwargs['choices'] = [ (key, value[0]) for key, value in six.iteritems(self.options)] - super(DateRangeFilter, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def filter(self, qs, value): try: @@ -545,7 +545,7 @@ class DateRangeOmniFilter(ChoiceFilter): def __init__(self, *args, **kwargs): kwargs['choices'] = [ (key, value[0]) for key, value in six.iteritems(self.options)] - super(DateRangeOmniFilter, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def filter(self, qs, value): try: @@ -569,7 +569,7 @@ class ReportBooleanFilter(ChoiceFilter): def __init__(self, *args, **kwargs): kwargs['choices'] = [ (key, value[0]) for key, value in six.iteritems(self.options)] - super(ReportBooleanFilter, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def filter(self, qs, value): try: @@ -604,7 +604,7 @@ def was_accepted(self, qs, name): def __init__(self, *args, **kwargs): kwargs['choices'] = [ (key, value[0]) for key, value in six.iteritems(self.options)] - super(ReportRiskAcceptanceFilter, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def filter(self, qs, value): try: @@ -679,7 +679,7 @@ def past_year(self, qs, name): def __init__(self, *args, **kwargs): kwargs['choices'] = [ (key, value[0]) for key, value in six.iteritems(self.options)] - super(MetricsDateRangeFilter, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def filter(self, qs, value): if value == 8: @@ -729,7 +729,7 @@ class ComponentFilter(ProductComponentFilter): label="Product") def __init__(self, *args, **kwargs): - super(ComponentFilter, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.form.fields[ 'test__engagement__product__prod_type'].queryset = get_authorized_product_types(Permissions.Product_Type_View) self.form.fields[ @@ -792,7 +792,7 @@ class EngagementDirectFilter(DojoFilter): ) def __init__(self, *args, **kwargs): - super(EngagementDirectFilter, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.form.fields['product__prod_type'].queryset = get_authorized_product_types(Permissions.Product_Type_View) self.form.fields['lead'].queryset = get_authorized_users(Permissions.Product_Type_View) \ .filter(engagement__lead__isnull=False).distinct() @@ -852,7 +852,7 @@ class EngagementFilter(DojoFilter): ) def __init__(self, *args, **kwargs): - super(EngagementFilter, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.form.fields['prod_type'].queryset = get_authorized_product_types(Permissions.Product_Type_View) self.form.fields['engagement__lead'].queryset = get_authorized_users(Permissions.Product_Type_View) \ .filter(engagement__lead__isnull=False).distinct() @@ -910,7 +910,7 @@ class ProductEngagementFilter(DojoFilter): ) def __init__(self, *args, **kwargs): - super(ProductEngagementFilter, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.form.fields['lead'].queryset = get_authorized_users(Permissions.Product_Type_View) \ .filter(engagement__lead__isnull=False).distinct() @@ -1098,7 +1098,7 @@ def __init__(self, *args, **kwargs): if 'user' in kwargs: self.user = kwargs.pop('user') - super(ProductFilter, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.form.fields['prod_type'].queryset = get_authorized_product_types(Permissions.Product_Type_View) @@ -1715,7 +1715,7 @@ class Meta: not_tag = CharFilter(field_name='tags__name', lookup_expr='icontains', label='Not tag name contains', exclude=True) def __init__(self, *args, **kwargs): - super(TemplateFindingFilter, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.form.fields['cwe'].choices = cwe_options(self.queryset) @@ -1950,12 +1950,12 @@ def __init__(self, *args, **kwargs): self.user = None if 'user' in kwargs: self.user = kwargs.pop('user') - super(EndpointFilter, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.form.fields['product'].queryset = get_authorized_products(Permissions.Product_View) @property def qs(self): - parent = super(EndpointFilter, self).qs + parent = super().qs return get_authorized_endpoints(Permissions.Endpoint_View, parent) class Meta: @@ -2348,7 +2348,7 @@ class LogEntryFilter(DojoFilter): timestamp = DateRangeFilter() def __init__(self, *args, **kwargs): - super(LogEntryFilter, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.form.fields['actor'].queryset = get_authorized_users(Permissions.Product_View) class Meta: @@ -2467,7 +2467,7 @@ def choice_question(self, qs, name): def __init__(self, *args, **kwargs): kwargs['choices'] = [ (key, value[0]) for key, value in six.iteritems(self.options)] - super(QuestionTypeFilter, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def filter(self, qs, value): try: diff --git a/dojo/finding/helper.py b/dojo/finding/helper.py index 95421553f4..debb209b3f 100644 --- a/dojo/finding/helper.py +++ b/dojo/finding/helper.py @@ -236,7 +236,7 @@ def get_group_by_group_name(finding, finding_group_by_option): group_name = finding.component_name elif finding_group_by_option == 'component_name+component_version': if finding.component_name or finding.component_version: - group_name = '%s:%s' % ((finding.component_name if finding.component_name else 'None'), + group_name = '{}:{}'.format((finding.component_name if finding.component_name else 'None'), (finding.component_version if finding.component_version else 'None')) elif finding_group_by_option == 'file_path': if finding.file_path: diff --git a/dojo/finding/views.py b/dojo/finding/views.py index 08ce201491..0adae7ae64 100644 --- a/dojo/finding/views.py +++ b/dojo/finding/views.py @@ -1279,8 +1279,7 @@ def close_finding(request, fid): event="other", title="Closing of %s" % finding.title, finding=finding, - description='The finding "%s" was closed by %s' - % (finding.title, request.user), + description=f'The finding "{finding.title}" was closed by {request.user}', url=reverse("view_finding", args=(finding.id,)), ) return HttpResponseRedirect( @@ -1443,8 +1442,7 @@ def reopen_finding(request, fid): event="other", title="Reopening of %s" % finding.title, finding=finding, - description='The finding "%s" was reopened by %s' - % (finding.title, request.user), + description=f'The finding "{finding.title}" was reopened by {request.user}', url=reverse("view_finding", args=(finding.id,)), ) return HttpResponseRedirect(reverse("view_finding", args=(finding.id,))) @@ -1501,8 +1499,7 @@ def copy_finding(request, fid): create_notification( event="other", title="Copying of %s" % finding.title, - description='The finding "%s" was copied by %s to %s' - % (finding.title, request.user, test.title), + description=f'The finding "{finding.title}" was copied by {request.user} to {test.title}', product=product, url=request.build_absolute_uri( reverse("copy_finding", args=(finding_copy.id,)) @@ -2274,8 +2271,7 @@ def apply_cwe_mitigation(apply_to_findings, template, update=True): template.save() new_note = Notes() new_note.entry = ( - "CWE remediation text applied to finding for CWE: %s using template: %s." - % (template.cwe, template.title) + f"CWE remediation text applied to finding for CWE: {template.cwe} using template: {template.title}." ) new_note.author, _created = User.objects.get_or_create( username="System" @@ -2518,9 +2514,7 @@ def merge_finding_product(request, pid): for finding in findings_to_merge.exclude( pk=finding_to_merge_into.pk ): - notes_entry = "{}\n- {} ({}),".format( - notes_entry, finding.title, finding.id - ) + notes_entry = f"{notes_entry}\n- {finding.title} ({finding.id})," if finding.static_finding: static = finding.static_finding @@ -2528,23 +2522,17 @@ def merge_finding_product(request, pid): dynamic = finding.dynamic_finding if form.cleaned_data["append_description"]: - finding_descriptions = "{}\n{}".format( - finding_descriptions, finding.description - ) + finding_descriptions = f"{finding_descriptions}\n{finding.description}" # Workaround until file path is one to many if finding.file_path: - finding_descriptions = "{}\n**File Path:** {}\n".format( - finding_descriptions, finding.file_path - ) + finding_descriptions = f"{finding_descriptions}\n**File Path:** {finding.file_path}\n" # If checked merge the Reference if ( form.cleaned_data["append_reference"] and finding.references is not None ): - finding_references = "{}\n{}".format( - finding_references, finding.references - ) + finding_references = f"{finding_references}\n{finding.references}" # if checked merge the endpoints if form.cleaned_data["add_endpoints"]: @@ -2566,9 +2554,7 @@ def merge_finding_product(request, pid): # Add merge finding information to the note if set to inactive if form.cleaned_data["finding_action"] == "inactive": single_finding_notes_entry = ("Finding has been set to inactive " - "and merged with the finding: {}.").format( - finding_to_merge_into.title - ) + f"and merged with the finding: {finding_to_merge_into.title}.") note = Notes( entry=single_finding_notes_entry, author=request.user ) @@ -2581,9 +2567,7 @@ def merge_finding_product(request, pid): # Update the finding to merge into if finding_descriptions != "": - finding_to_merge_into.description = "{}\n\n{}".format( - finding_to_merge_into.description, finding_descriptions - ) + finding_to_merge_into.description = f"{finding_to_merge_into.description}\n\n{finding_descriptions}" if finding_to_merge_into.static_finding: static = finding.static_finding @@ -2592,9 +2576,7 @@ def merge_finding_product(request, pid): dynamic = finding.dynamic_finding if finding_references != "": - finding_to_merge_into.references = "{}\n{}".format( - finding_to_merge_into.references, finding_references - ) + finding_to_merge_into.references = f"{finding_to_merge_into.references}\n{finding_references}" finding_to_merge_into.static_finding = static finding_to_merge_into.dynamic_finding = dynamic @@ -2624,9 +2606,7 @@ def merge_finding_product(request, pid): findings_to_merge.delete() notes_entry = ("Finding consists of merged findings from the following " - "findings which have been {}: {}").format( - finding_action, notes_entry[:-1] - ) + f"findings which have been {finding_action}: {notes_entry[:-1]}") note = Notes(entry=notes_entry, author=request.user) note.save() finding_to_merge_into.notes.add(note) @@ -2716,18 +2696,14 @@ def finding_bulk_update_all(request, pid=None): if skipped_find_count > 0: add_error_message_to_response( - "Skipped deletion of {} findings because you are not authorized.".format( - skipped_find_count - ) + f"Skipped deletion of {skipped_find_count} findings because you are not authorized." ) if deleted_find_count > 0: messages.add_message( request, messages.SUCCESS, - "Bulk delete of {} findings was successful.".format( - deleted_find_count - ), + f"Bulk delete of {deleted_find_count} findings was successful.", extra_tags="alert-success", ) else: @@ -2748,9 +2724,7 @@ def finding_bulk_update_all(request, pid=None): if skipped_find_count > 0: add_error_message_to_response( - "Skipped update of {} findings because you are not authorized.".format( - skipped_find_count - ) + f"Skipped update of {skipped_find_count} findings because you are not authorized." ) finds = prefetch_for_findings(finds) @@ -2887,8 +2861,7 @@ def finding_bulk_update_all(request, pid=None): if added: add_success_message_to_response( - "Added %s findings to finding group %s" - % (added, finding_group.name) + f"Added {added} findings to finding group {finding_group.name}" ) return_url = reverse( "view_finding_group", args=(finding_group.id,) @@ -2896,9 +2869,8 @@ def finding_bulk_update_all(request, pid=None): if skipped: add_success_message_to_response( - ("Skipped %s findings when adding to finding group %s, " - "findings already part of another group") - % (skipped, finding_group.name) + f"Skipped {skipped} findings when adding to finding group {finding_group.name}, " + "findings already part of another group" ) # refresh findings from db @@ -2914,8 +2886,7 @@ def finding_bulk_update_all(request, pid=None): if removed: add_success_message_to_response( - "Removed %s findings from finding groups %s" - % ( + "Removed {} findings from finding groups {}".format( removed, ",".join( [ @@ -2958,9 +2929,8 @@ def finding_bulk_update_all(request, pid=None): if skipped: add_success_message_to_response( - ("Skipped %s findings when grouping by %s as these findings " - "were already in an existing group") - % (skipped, finding_group_by_option) + f"Skipped {skipped} findings when grouping by {finding_group_by_option} as these findings " + "were already in an existing group" ) # refresh findings from db @@ -3104,9 +3074,7 @@ def finding_bulk_update_all(request, pid=None): messages.add_message( request, messages.SUCCESS, - "Bulk update of {} findings was successful.".format( - updated_find_count - ), + f"Bulk update of {updated_find_count} findings was successful.", extra_tags="alert-success", ) else: diff --git a/dojo/finding_group/views.py b/dojo/finding_group/views.py index e6f92a71d2..054fb29bfe 100644 --- a/dojo/finding_group/views.py +++ b/dojo/finding_group/views.py @@ -122,7 +122,7 @@ def delete_finding_group(request, fgid): create_notification(event='other', title='Deletion of %s' % finding_group.name, product=product, - description='The finding group "%s" was deleted by %s' % (finding_group.name, request.user), + description=f'The finding group "{finding_group.name}" was deleted by {request.user}', url=request.build_absolute_uri(reverse('view_test', args=(finding_group.test.id,))), icon="exclamation-triangle") return HttpResponseRedirect(reverse('view_test', args=(finding_group.test.id,))) diff --git a/dojo/forms.py b/dojo/forms.py index 1d24ed429a..8bce183a95 100755 --- a/dojo/forms.py +++ b/dojo/forms.py @@ -75,7 +75,7 @@ class MultipleSelectWithPop(forms.SelectMultiple): def render(self, name, *args, **kwargs): - html = super(MultipleSelectWithPop, self).render(name, *args, **kwargs) + html = super().render(name, *args, **kwargs) popup_plus = '
' + html + '
' return mark_safe(popup_plus) @@ -154,7 +154,7 @@ def value_from_datadict(self, data, files, name): if y == m == "0": return None if y and m: - return '%s-%s-%s' % (y, m, 1) + return f'{y}-{m}-{1}' return data.get(name, None) @@ -179,7 +179,7 @@ class Meta: class Edit_Product_Type_MemberForm(forms.ModelForm): def __init__(self, *args, **kwargs): - super(Edit_Product_Type_MemberForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['product_type'].disabled = True self.fields['user'].queryset = Dojo_User.objects.order_by('first_name', 'last_name') self.fields['user'].disabled = True @@ -193,7 +193,7 @@ class Add_Product_Type_MemberForm(forms.ModelForm): users = forms.ModelMultipleChoiceField(queryset=Dojo_User.objects.none(), required=True, label='Users') def __init__(self, *args, **kwargs): - super(Add_Product_Type_MemberForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) current_members = Product_Type_Member.objects.filter(product_type=self.initial["product_type"]).values_list('user', flat=True) self.fields['users'].queryset = Dojo_User.objects.exclude( Q(is_superuser=True) @@ -209,7 +209,7 @@ class Add_Product_Type_Member_UserForm(forms.ModelForm): product_types = forms.ModelMultipleChoiceField(queryset=Product_Type.objects.none(), required=True, label='Product Types') def __init__(self, *args, **kwargs): - super(Add_Product_Type_Member_UserForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) current_members = Product_Type_Member.objects.filter(user=self.initial['user']).values_list('product_type', flat=True) self.fields['product_types'].queryset = get_authorized_product_types(Permissions.Product_Type_Member_Add_Owner) \ .exclude(id__in=current_members) @@ -222,7 +222,7 @@ class Meta: class Delete_Product_Type_MemberForm(Edit_Product_Type_MemberForm): def __init__(self, *args, **kwargs): - super(Delete_Product_Type_MemberForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['role'].disabled = True @@ -263,7 +263,7 @@ class ProductForm(forms.ModelForm): team_manager = forms.ModelChoiceField(queryset=Dojo_User.objects.exclude(is_active=False).order_by('first_name', 'last_name'), required=False) def __init__(self, *args, **kwargs): - super(ProductForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['prod_type'].queryset = get_authorized_product_types(Permissions.Product_Type_Add_Product) # if this product has findings being asynchronously updated, disable the sla config field @@ -294,7 +294,7 @@ class EditFindingGroupForm(forms.ModelForm): help_text='Leave empty and check push to jira to create a new JIRA issue for this finding group.') def __init__(self, *args, **kwargs): - super(EditFindingGroupForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) import dojo.jira_link.helper as jira_helper self.fields['push_to_jira'] = forms.BooleanField() @@ -325,7 +325,7 @@ class Meta: class Edit_Product_MemberForm(forms.ModelForm): def __init__(self, *args, **kwargs): - super(Edit_Product_MemberForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['product'].disabled = True self.fields['user'].queryset = Dojo_User.objects.order_by('first_name', 'last_name') self.fields['user'].disabled = True @@ -339,7 +339,7 @@ class Add_Product_MemberForm(forms.ModelForm): users = forms.ModelMultipleChoiceField(queryset=Dojo_User.objects.none(), required=True, label='Users') def __init__(self, *args, **kwargs): - super(Add_Product_MemberForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['product'].disabled = True current_members = Product_Member.objects.filter(product=self.initial["product"]).values_list('user', flat=True) self.fields['users'].queryset = Dojo_User.objects.exclude( @@ -355,7 +355,7 @@ class Add_Product_Member_UserForm(forms.ModelForm): products = forms.ModelMultipleChoiceField(queryset=Product.objects.none(), required=True, label='Products') def __init__(self, *args, **kwargs): - super(Add_Product_Member_UserForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) current_members = Product_Member.objects.filter(user=self.initial["user"]).values_list('product', flat=True) self.fields['products'].queryset = get_authorized_products(Permissions.Product_Member_Add_Owner) \ .exclude(id__in=current_members) @@ -368,7 +368,7 @@ class Meta: class Delete_Product_MemberForm(Edit_Product_MemberForm): def __init__(self, *args, **kwargs): - super(Delete_Product_MemberForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['role'].disabled = True @@ -385,14 +385,14 @@ class EditNoteTypeForm(NoteTypeForm): def __init__(self, *args, **kwargs): is_single = kwargs.pop('is_single') - super(EditNoteTypeForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if is_single is False: self.fields['is_single'].widget = forms.HiddenInput() class DisableOrEnableNoteTypeForm(NoteTypeForm): def __init__(self, *args, **kwargs): - super(DisableOrEnableNoteTypeForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['name'].disabled = True self.fields['description'].disabled = True self.fields['is_single'].disabled = True @@ -409,7 +409,7 @@ class DojoMetaDataForm(forms.ModelForm): required=True) def full_clean(self): - super(DojoMetaDataForm, self).full_clean() + super().full_clean() try: self.instance.validate_unique() except ValidationError: @@ -498,7 +498,7 @@ class ImportScanForm(forms.Form): create_finding_groups_for_all_findings = forms.BooleanField(help_text="If unchecked, finding groups will only be created when there is more than one grouped finding", required=False, initial=True) def __init__(self, *args, **kwargs): - super(ImportScanForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['active'].initial = self.active_verified_choices[0] self.fields['verified'].initial = self.active_verified_choices[0] @@ -515,7 +515,7 @@ def clean(self): scan_type = cleaned_data.get("scan_type") file = cleaned_data.get("file") if requires_file(scan_type) and not file: - raise forms.ValidationError('Uploading a Report File is required for {}'.format(scan_type)) + raise forms.ValidationError(f'Uploading a Report File is required for {scan_type}') tool_type = requires_tool_type(scan_type) if tool_type: api_scan_configuration = cleaned_data.get('api_scan_configuration') @@ -596,7 +596,7 @@ class ReImportScanForm(forms.Form): create_finding_groups_for_all_findings = forms.BooleanField(help_text="If unchecked, finding groups will only be created when there is more than one grouped finding", required=False, initial=True) def __init__(self, *args, test=None, **kwargs): - super(ReImportScanForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['active'].initial = self.active_verified_choices[0] self.fields['verified'].initial = self.active_verified_choices[0] self.scan_type = None @@ -653,7 +653,7 @@ class ImportEndpointMetaForm(forms.Form): help_text="Add data from file as Metadata. Metadata is used for displaying custom fields",) def __init__(self, *args, **kwargs): - super(ImportEndpointMetaForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) class DoneForm(forms.Form): @@ -696,7 +696,7 @@ class MergeFindings(forms.ModelForm): def __init__(self, *args, **kwargs): _ = kwargs.pop('finding') findings = kwargs.pop('findings') - super(MergeFindings, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['finding_to_merge_into'] = forms.ModelChoiceField( queryset=findings, initial=0, required="False", label="Finding to Merge Into", help_text="Findings selected below will be merged into this finding.") @@ -817,7 +817,7 @@ class CheckForm(forms.ModelForm): def __init__(self, *args, **kwargs): findings = kwargs.pop('findings') - super(CheckForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['session_issues'].queryset = findings self.fields['crypto_issues'].queryset = findings self.fields['config_issues'].queryset = findings @@ -868,7 +868,7 @@ def __init__(self, *args, **kwargs): if 'user' in kwargs: self.user = kwargs.pop('user') - super(EngForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if product: self.fields['preset'] = forms.ModelChoiceField(help_text="Settings and notes for performing this engagement.", required=False, queryset=Engagement_Presets.objects.filter(product=product)) @@ -892,7 +892,7 @@ def __init__(self, *args, **kwargs): del self.fields['status'] def is_valid(self): - valid = super(EngForm, self).is_valid() + valid = super().is_valid() # we're done now if not valid if not valid: @@ -943,7 +943,7 @@ def __init__(self, *args, **kwargs): if 'instance' in kwargs: obj = kwargs.get('instance') - super(TestForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if obj: product = get_product(obj) @@ -976,7 +976,7 @@ class CopyTestForm(forms.Form): def __init__(self, *args, **kwargs): authorized_lists = kwargs.pop('engagements', None) - super(CopyTestForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['engagement'].queryset = authorized_lists @@ -1024,7 +1024,7 @@ def __init__(self, *args, **kwargs): if 'product' in kwargs: product = kwargs.pop('product') - super(AddFindingForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if product: self.fields['endpoints'].queryset = Endpoint.objects.filter(product=product) @@ -1036,7 +1036,7 @@ def __init__(self, *args, **kwargs): self.endpoints_to_add_list = [] def clean(self): - cleaned_data = super(AddFindingForm, self).clean() + cleaned_data = super().clean() if ((cleaned_data['active'] or cleaned_data['verified']) and cleaned_data['duplicate']): raise forms.ValidationError('Duplicate findings cannot be' ' verified or active') @@ -1105,7 +1105,7 @@ def __init__(self, *args, **kwargs): if 'product' in kwargs: product = kwargs.pop('product') - super(AdHocFindingForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if product: self.fields['endpoints'].queryset = Endpoint.objects.filter(product=product) @@ -1117,7 +1117,7 @@ def __init__(self, *args, **kwargs): self.endpoints_to_add_list = [] def clean(self): - cleaned_data = super(AdHocFindingForm, self).clean() + cleaned_data = super().clean() if ((cleaned_data['active'] or cleaned_data['verified']) and cleaned_data['duplicate']): raise forms.ValidationError('Duplicate findings cannot be' ' verified or active') @@ -1173,7 +1173,7 @@ def __init__(self, *args, **kwargs): if 'product' in kwargs: product = kwargs.pop('product') - super(PromoteFindingForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if product: self.fields['endpoints'].queryset = Endpoint.objects.filter(product=product) @@ -1181,7 +1181,7 @@ def __init__(self, *args, **kwargs): self.endpoints_to_add_list = [] def clean(self): - cleaned_data = super(PromoteFindingForm, self).clean() + cleaned_data = super().clean() endpoints_to_add_list, errors = validate_endpoints_to_add(cleaned_data['endpoints_to_add']) if errors: @@ -1249,7 +1249,7 @@ def __init__(self, *args, **kwargs): self.can_edit_mitigated_data = kwargs.pop('can_edit_mitigated_data') if 'can_edit_mitigated_data' in kwargs \ else False - super(FindingForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['endpoints'].queryset = Endpoint.objects.filter(product=self.instance.test.engagement.product) self.fields['mitigated_by'].queryset = get_authorized_users(Permissions.Test_Edit) @@ -1295,7 +1295,7 @@ def __init__(self, *args, **kwargs): self.endpoints_to_add_list = [] def clean(self): - cleaned_data = super(FindingForm, self).clean() + cleaned_data = super().clean() if (cleaned_data['active'] or cleaned_data['verified']) and cleaned_data['duplicate']: raise forms.ValidationError('Duplicate findings cannot be' @@ -1316,7 +1316,7 @@ def clean(self): return cleaned_data def _post_clean(self): - super(FindingForm, self)._post_clean() + super()._post_clean() if self.can_edit_mitigated_data: opts = self.instance._meta @@ -1342,7 +1342,7 @@ class Meta: 'date', 'description', 'severity', 'reporter', 'test', 'is_mitigated') def clean(self): - cleaned_data = super(StubFindingForm, self).clean() + cleaned_data = super().clean() if 'title' in cleaned_data: if len(cleaned_data['title']) <= 0: raise forms.ValidationError("The title is required.") @@ -1370,14 +1370,14 @@ class ApplyFindingTemplateForm(forms.Form): tags = TagField(required=False, help_text="Add tags that help describe this finding template. Choose from the list or add new tags. Press Enter key to add.", initial=Finding.tags.tag_model.objects.all().order_by('name')) def __init__(self, template=None, *args, **kwargs): - super(ApplyFindingTemplateForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['tags'].autocomplete_tags = Finding.tags.tag_model.objects.all().order_by('name') self.template = template if template: self.template.vulnerability_ids = '\n'.join(template.vulnerability_ids) def clean(self): - cleaned_data = super(ApplyFindingTemplateForm, self).clean() + cleaned_data = super().clean() if 'title' in cleaned_data: if len(cleaned_data['title']) <= 0: @@ -1409,7 +1409,7 @@ class FindingTemplateForm(forms.ModelForm): field_order = ['title', 'cwe', 'vulnerability_ids', 'severity', 'cvssv3', 'description', 'mitigation', 'impact', 'references', 'tags', 'template_match', 'template_match_cwe', 'template_match_title', 'apply_to_findings'] def __init__(self, *args, **kwargs): - super(FindingTemplateForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['tags'].autocomplete_tags = Finding.tags.tag_model.objects.all().order_by('name') class Meta: @@ -1452,13 +1452,13 @@ class FindingBulkUpdateForm(forms.ModelForm): notes = forms.CharField(required=False, max_length=1024, widget=forms.TextInput(attrs={'class': 'form-control'})) def __init__(self, *args, **kwargs): - super(FindingBulkUpdateForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['severity'].required = False # we need to defer initialization to prevent multiple initializations if other forms are shown self.fields['tags'].widget.tag_options = tagulous.models.options.TagOptions(autocomplete_settings={'width': '200px', 'defer': True}) def clean(self): - cleaned_data = super(FindingBulkUpdateForm, self).clean() + cleaned_data = super().clean() if (cleaned_data['active'] or cleaned_data['verified']) and cleaned_data['duplicate']: raise forms.ValidationError('Duplicate findings cannot be' @@ -1482,7 +1482,7 @@ class Meta: def __init__(self, *args, **kwargs): self.product = None self.endpoint_instance = None - super(EditEndpointForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if 'instance' in kwargs: self.endpoint_instance = kwargs.pop('instance') self.product = self.endpoint_instance.product @@ -1492,7 +1492,7 @@ def __init__(self, *args, **kwargs): def clean(self): - cleaned_data = super(EditEndpointForm, self).clean() + cleaned_data = super().clean() protocol = cleaned_data['protocol'] userinfo = cleaned_data['userinfo'] @@ -1536,7 +1536,7 @@ def __init__(self, *args, **kwargs): product = None if 'product' in kwargs: product = kwargs.pop('product') - super(AddEndpointForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['product'] = forms.ModelChoiceField(queryset=get_authorized_products(Permissions.Endpoint_Add)) if product is not None: self.fields['product'].initial = product.id @@ -1562,7 +1562,7 @@ def save(self): def clean(self): - cleaned_data = super(AddEndpointForm, self).clean() + cleaned_data = super().clean() if 'endpoint' in cleaned_data and 'product' in cleaned_data: endpoint = cleaned_data['endpoint'] @@ -1606,10 +1606,10 @@ class TypedNoteForm(NoteForm): def __init__(self, *args, **kwargs): queryset = kwargs.pop('available_note_types') - super(TypedNoteForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['note_type'] = forms.ModelChoiceField(queryset=queryset, label='Note Type', required=True) - class Meta(): + class Meta: model = Notes fields = ['note_type', 'entry', 'private'] @@ -1639,7 +1639,7 @@ class CloseFindingForm(forms.ModelForm): def __init__(self, *args, **kwargs): queryset = kwargs.pop('missing_note_types') - super(CloseFindingForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if len(queryset) == 0: self.fields['note_type'].widget = forms.HiddenInput() else: @@ -1654,7 +1654,7 @@ def __init__(self, *args, **kwargs): self.fields['mitigated_by'].initial = self.instance.mitigated_by def _post_clean(self): - super(CloseFindingForm, self)._post_clean() + super()._post_clean() if self.can_edit_mitigated_data: opts = self.instance._meta @@ -1676,7 +1676,7 @@ def __init__(self, *args, **kwargs): if 'finding' in kwargs: finding = kwargs.pop('finding') - super(EditPlannedRemediationDateFindingForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['planned_remediation_date'].required = True self.fields['planned_remediation_date'].widget = forms.DateInput(attrs={'class': 'datepicker'}) @@ -1742,7 +1742,7 @@ class ReviewFindingForm(forms.Form): def __init__(self, *args, **kwargs): finding = kwargs.pop("finding", None) user = kwargs.pop("user", None) - super(ReviewFindingForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # Get the list of users if finding is not None: users = get_authorized_users_for_product_and_product_type(None, finding.test.engagement.product, Permissions.Finding_Edit) @@ -1776,7 +1776,7 @@ class WeeklyMetricsForm(forms.Form): dates = forms.ChoiceField() def __init__(self, *args, **kwargs): - super(WeeklyMetricsForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) wmf_options = [] for i in range(6): @@ -1842,7 +1842,7 @@ def __init__(self, *args, **kwargs): exclude_product_types = kwargs.get('exclude_product_types', False) if 'exclude_product_types' in kwargs: del kwargs['exclude_product_types'] - super(MetricsFilterForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if exclude_product_types: del self.fields['exclude_product_types'] @@ -1871,7 +1871,7 @@ class Add_Group_MemberForm(forms.ModelForm): users = forms.ModelMultipleChoiceField(queryset=Dojo_Group_Member.objects.none(), required=True, label='Users') def __init__(self, *args, **kwargs): - super(Add_Group_MemberForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['group'].disabled = True current_members = Dojo_Group_Member.objects.filter(group=self.initial['group']).values_list('user', flat=True) self.fields['users'].queryset = Dojo_User.objects.exclude( @@ -1888,7 +1888,7 @@ class Add_Group_Member_UserForm(forms.ModelForm): groups = forms.ModelMultipleChoiceField(queryset=Dojo_Group.objects.none(), required=True, label='Groups') def __init__(self, *args, **kwargs): - super(Add_Group_Member_UserForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['user'].disabled = True current_groups = Dojo_Group_Member.objects.filter(user=self.initial['user']).values_list('group', flat=True) self.fields['groups'].queryset = Dojo_Group.objects.exclude(id__in=current_groups) @@ -1901,7 +1901,7 @@ class Meta: class Edit_Group_MemberForm(forms.ModelForm): def __init__(self, *args, **kwargs): - super(Edit_Group_MemberForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['group'].disabled = True self.fields['user'].disabled = True self.fields['role'].queryset = get_group_member_roles() @@ -1913,7 +1913,7 @@ class Meta: class Delete_Group_MemberForm(Edit_Group_MemberForm): def __init__(self, *args, **kwargs): - super(Delete_Group_MemberForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['role'].disabled = True @@ -1921,7 +1921,7 @@ class Add_Product_GroupForm(forms.ModelForm): groups = forms.ModelMultipleChoiceField(queryset=Dojo_Group.objects.none(), required=True, label='Groups') def __init__(self, *args, **kwargs): - super(Add_Product_GroupForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['product'].disabled = True current_groups = Product_Group.objects.filter(product=self.initial["product"]).values_list('group', flat=True) authorized_groups = get_authorized_groups(Permissions.Group_View) @@ -1937,7 +1937,7 @@ class Add_Product_Group_GroupForm(forms.ModelForm): products = forms.ModelMultipleChoiceField(queryset=Product.objects.none(), required=True, label='Products') def __init__(self, *args, **kwargs): - super(Add_Product_Group_GroupForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) current_members = Product_Group.objects.filter(group=self.initial["group"]).values_list('product', flat=True) self.fields['products'].queryset = get_authorized_products(Permissions.Product_Member_Add_Owner) \ .exclude(id__in=current_members) @@ -1951,7 +1951,7 @@ class Meta: class Edit_Product_Group_Form(forms.ModelForm): def __init__(self, *args, **kwargs): - super(Edit_Product_Group_Form, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['product'].disabled = True self.fields['group'].disabled = True @@ -1962,7 +1962,7 @@ class Meta: class Delete_Product_GroupForm(Edit_Product_Group_Form): def __init__(self, *args, **kwargs): - super(Delete_Product_GroupForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['role'].disabled = True @@ -1970,7 +1970,7 @@ class Add_Product_Type_GroupForm(forms.ModelForm): groups = forms.ModelMultipleChoiceField(queryset=Dojo_Group.objects.none(), required=True, label='Groups') def __init__(self, *args, **kwargs): - super(Add_Product_Type_GroupForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) current_groups = Product_Type_Group.objects.filter(product_type=self.initial["product_type"]).values_list('group', flat=True) authorized_groups = get_authorized_groups(Permissions.Group_View) authorized_groups = authorized_groups.exclude(id__in=current_groups) @@ -1986,7 +1986,7 @@ class Add_Product_Type_Group_GroupForm(forms.ModelForm): product_types = forms.ModelMultipleChoiceField(queryset=Product_Type.objects.none(), required=True, label='Product Types') def __init__(self, *args, **kwargs): - super(Add_Product_Type_Group_GroupForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) current_members = Product_Type_Group.objects.filter(group=self.initial['group']).values_list('product_type', flat=True) self.fields['product_types'].queryset = get_authorized_product_types(Permissions.Product_Type_Member_Add_Owner) \ .exclude(id__in=current_members) @@ -2000,7 +2000,7 @@ class Meta: class Edit_Product_Type_Group_Form(forms.ModelForm): def __init__(self, *args, **kwargs): - super(Edit_Product_Type_Group_Form, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['product_type'].disabled = True self.fields['group'].disabled = True @@ -2011,13 +2011,13 @@ class Meta: class Delete_Product_Type_GroupForm(Edit_Product_Type_Group_Form): def __init__(self, *args, **kwargs): - super(Delete_Product_Type_GroupForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['role'].disabled = True class DojoUserForm(forms.ModelForm): def __init__(self, *args, **kwargs): - super(DojoUserForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if not get_current_user().is_superuser and not get_system_setting('enable_user_profile_editable'): for field in self.fields: self.fields[field].disabled = True @@ -2045,7 +2045,7 @@ def __init__(self, *args, **kwargs): self.user = None if 'user' in kwargs: self.user = kwargs.pop('user') - super(ChangePasswordForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['new_password'].help_text = get_password_requirements_string() def clean(self): @@ -2214,7 +2214,7 @@ class CopyFindingForm(forms.Form): def __init__(self, *args, **kwargs): authorized_lists = kwargs.pop('tests', None) - super(CopyFindingForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['test'].queryset = authorized_lists @@ -2329,7 +2329,7 @@ class JIRAForm(BaseJiraForm): help_text='Choose the folder containing the Django templates used to render the JIRA issue description. These are stored in dojo/templates/issue-trackers. Leave empty to use the default jira_full templates.') def __init__(self, *args, **kwargs): - super(JIRAForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if self.instance: self.fields['password'].required = False @@ -2380,7 +2380,7 @@ class Meta: class Product_API_Scan_ConfigurationForm(forms.ModelForm): def __init__(self, *args, **kwargs): - super(Product_API_Scan_ConfigurationForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) tool_configuration = forms.ModelChoiceField( label='Tool Configuration', @@ -2453,7 +2453,7 @@ class Meta: exclude = ['product', 'tags'] def __init__(self, *args, **kwargs): - super(DeleteAppAnalysisForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['name'].disabled = True self.fields['user'].disabled = True self.fields['confidence'].disabled = True @@ -2489,7 +2489,7 @@ def clean(self): class SLAConfigForm(forms.ModelForm): def __init__(self, *args, **kwargs): - super(SLAConfigForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # if this sla config has findings being asynchronously updated, disable the days by severity fields if self.instance.async_updating: @@ -2574,7 +2574,7 @@ class Meta: exclude = ['product'] def __init__(self, *args, **kwargs): - super(ObjectSettingsForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def clean(self): form_data = self.cleaned_data @@ -2625,7 +2625,7 @@ class SystemSettingsForm(forms.ModelForm): jira_webhook_secret = forms.CharField(required=False) def __init__(self, *args, **kwargs): - super(SystemSettingsForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['default_group_role'].queryset = get_group_member_roles() def clean(self): @@ -2667,7 +2667,7 @@ class Meta: class ProductNotificationsForm(forms.ModelForm): def __init__(self, *args, **kwargs): - super(ProductNotificationsForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if not self.instance.id: self.initial['engagement_added'] = '' self.initial['close_engagement'] = '' @@ -2837,7 +2837,7 @@ def clean(self): class GITHUBFindingForm(forms.Form): def __init__(self, *args, **kwargs): self.enabled = kwargs.pop('enabled') - super(GITHUBFindingForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['push_to_github'] = forms.BooleanField() self.fields['push_to_github'].required = False self.fields['push_to_github'].help_text = "Checking this will overwrite content of your Github issue, or create one." @@ -2857,7 +2857,7 @@ def __init__(self, *args, **kwargs): if self.instance is None and self.jira_project is None: raise ValueError('either and finding instance or jira_project is needed') - super(JIRAFindingForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['push_to_jira'] = forms.BooleanField() self.fields['push_to_jira'].required = False if is_finding_groups_enabled(): @@ -2892,7 +2892,7 @@ def __init__(self, *args, **kwargs): def clean(self): logger.debug('jform clean') - super(JIRAFindingForm, self).clean() + super().clean() jira_issue_key_new = self.cleaned_data.get('jira_issue') finding = self.instance jira_project = self.jira_project @@ -2968,7 +2968,7 @@ class JIRAImportScanForm(forms.Form): def __init__(self, *args, **kwargs): self.push_all = kwargs.pop('push_all', False) - super(JIRAImportScanForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if self.push_all: # This will show the checkbox as checked and greyed out, this way the user is aware # that issues will be pushed to JIRA, given their product-level settings. @@ -2987,7 +2987,7 @@ class JIRAEngagementForm(forms.Form): def __init__(self, *args, **kwargs): self.instance = kwargs.pop('instance', None) - super(JIRAEngagementForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if self.instance: if self.instance.has_jira_issue: @@ -3026,7 +3026,7 @@ class Meta: class AnnouncementRemoveForm(AnnouncementCreateForm): def __init__(self, *args, **kwargs): - super(AnnouncementRemoveForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['dismissable'].disabled = True self.fields['message'].disabled = True self.fields['style'].disabled = True @@ -3069,12 +3069,12 @@ def __init__(self, *args, **kwargs): raise ValueError('Need a question to render') del kwargs['question'] - super(QuestionForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) class TextQuestionForm(QuestionForm): def __init__(self, *args, **kwargs): - super(TextQuestionForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # work out initial data @@ -3119,7 +3119,7 @@ def save(self): class ChoiceQuestionForm(QuestionForm): def __init__(self, *args, **kwargs): - super(ChoiceQuestionForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) choices = [(c.id, c.label) for c in self.question.choices.all()] @@ -3326,7 +3326,7 @@ def __init__(self, attrs=None): forms.TextInput(attrs={'data-type': 'choice'}), forms.TextInput(attrs={'data-type': 'choice'}), forms.TextInput(attrs={'data-type': 'choice'})] - super(MultiWidgetBasic, self).__init__(widgets, attrs) + super().__init__(widgets, attrs) def decompress(self, value): if value: @@ -3348,7 +3348,7 @@ def __init__(self, *args, **kwargs): forms.fields.CharField(required=False), forms.fields.CharField(required=False), forms.fields.CharField(required=False)] - super(MultiExampleField, self).__init__(list_fields, *args, **kwargs) + super().__init__(list_fields, *args, **kwargs) def compress(self, values): return pickle.dumps(values) @@ -3405,7 +3405,7 @@ def __init__(self, *args, **kwargs): assignee = None if 'assignee' in kwargs: assignee = kwargs.pop('asignees') - super(AssignUserForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if assignee is None: self.fields['assignee'] = forms.ModelChoiceField(queryset=get_authorized_users(Permissions.Engagement_View), empty_label='Not Assigned', required=False) else: @@ -3424,7 +3424,7 @@ class AddEngagementForm(forms.Form): help_text='Select which product to attach Engagement') def __init__(self, *args, **kwargs): - super(AddEngagementForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['product'].queryset = get_authorized_products(Permissions.Engagement_Add) @@ -3433,7 +3433,7 @@ class ConfigurationPermissionsForm(forms.Form): def __init__(self, *args, **kwargs): self.user = kwargs.pop('user', None) self.group = kwargs.pop('group', None) - super(ConfigurationPermissionsForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.permission_fields = get_configuration_permissions_fields() diff --git a/dojo/group/views.py b/dojo/group/views.py index 8cdf17b31c..d454a8d977 100644 --- a/dojo/group/views.py +++ b/dojo/group/views.py @@ -419,7 +419,7 @@ def edit_group_member(request, mid): if owners < 1: messages.add_message(request, messages.WARNING, - 'There must be at least one owner for group {}.'.format(member.group.name), + f'There must be at least one owner for group {member.group.name}.', extra_tags='alert-warning') if is_title_in_breadcrumbs('View User'): return HttpResponseRedirect(reverse('view_user', args=(member.user.id, ))) @@ -461,7 +461,7 @@ def delete_group_member(request, mid): if owners <= 1: messages.add_message(request, messages.WARNING, - 'There must be at least one owner for group {}.'.format(member.group.name), + f'There must be at least one owner for group {member.group.name}.', extra_tags='alert-warning') if is_title_in_breadcrumbs('View User'): return HttpResponseRedirect(reverse('view_user', args=(member.user.id, ))) diff --git a/dojo/importers/importer/importer.py b/dojo/importers/importer/importer.py index 337df8d047..1be23a01e8 100644 --- a/dojo/importers/importer/importer.py +++ b/dojo/importers/importer/importer.py @@ -23,7 +23,7 @@ deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") -class DojoDefaultImporter(object): +class DojoDefaultImporter: def create_test(self, scan_type, test_type_name, engagement, lead, environment, tags=None, scan_date=None, version=None, branch_tag=None, build_id=None, commit_hash=None, now=timezone.now(), diff --git a/dojo/importers/reimporter/reimporter.py b/dojo/importers/reimporter/reimporter.py index 1515b6ba41..0128d0daaa 100644 --- a/dojo/importers/reimporter/reimporter.py +++ b/dojo/importers/reimporter/reimporter.py @@ -22,7 +22,7 @@ deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") -class DojoDefaultReImporter(object): +class DojoDefaultReImporter: @dojo_async_task @app.task(ignore_result=False) def process_parsed_findings( @@ -106,7 +106,7 @@ def process_parsed_findings( except ValidationError as err: logger.warning( "DefectDojo is storing broken endpoint because cleaning wasn't successful: " - "{}".format(err) + f"{err}" ) item.hash_code = item.compute_hash_code() diff --git a/dojo/importers/utils.py b/dojo/importers/utils.py index 0b98caf551..5788b5fcf4 100644 --- a/dojo/importers/utils.py +++ b/dojo/importers/utils.py @@ -142,7 +142,7 @@ def add_endpoints_to_unsaved_finding(finding, test, endpoints, **kwargs): endpoint.clean() except ValidationError as e: logger.warning("DefectDojo is storing broken endpoint because cleaning wasn't successful: " - "{}".format(e)) + f"{e}") ep = None try: ep, _created = endpoint_get_or_create( diff --git a/dojo/jira_link/helper.py b/dojo/jira_link/helper.py index 090c75c897..eb2b1c3adf 100644 --- a/dojo/jira_link/helper.py +++ b/dojo/jira_link/helper.py @@ -722,7 +722,7 @@ def failure_to_add_message(message: str, exception: Exception, object: Any) -> b return False if not is_jira_configured_and_enabled(obj): - message = 'Object %s cannot be pushed to JIRA as there is no JIRA configuration for %s.' % (obj.id, to_str_typed(obj)) + message = f'Object {obj.id} cannot be pushed to JIRA as there is no JIRA configuration for {to_str_typed(obj)}.' return failure_to_add_message(message, None, obj) jira_project = get_jira_project(obj) @@ -884,7 +884,7 @@ def failure_to_update_message(message: str, exception: Exception, obj: Any) -> b jira_instance = get_jira_instance(obj) if not is_jira_configured_and_enabled(obj): - message = 'Object %s cannot be pushed to JIRA as there is no JIRA configuration for %s.' % (obj.id, to_str_typed(obj)) + message = f'Object {obj.id} cannot be pushed to JIRA as there is no JIRA configuration for {to_str_typed(obj)}.' return failure_to_update_message(message, None, obj) j_issue = obj.jira_issue @@ -985,7 +985,7 @@ def get_jira_issue_from_jira(find): j_issue = find.jira_issue if not jira_project: logger.error("Unable to retrieve latest status change from JIRA %s for finding %s as there is no JIRA_Project configured for this finding.", j_issue.jira_key, format(find.id)) - log_jira_alert("Unable to retrieve latest status change from JIRA %s for finding %s as there is no JIRA_Project configured for this finding." % (j_issue.jira_key, find), find) + log_jira_alert(f"Unable to retrieve latest status change from JIRA {j_issue.jira_key} for finding {find} as there is no JIRA_Project configured for this finding.", find) return False meta = None @@ -1203,7 +1203,7 @@ def close_epic(eng, push_to_jira, **kwargs): auth=HTTPBasicAuth(jira_instance.username, jira_instance.password), json=json_data) if r.status_code != 204: - logger.warning("JIRA close epic failed with error: {}".format(r.text)) + logger.warning(f"JIRA close epic failed with error: {r.text}") return False return True except JIRAError as e: @@ -1349,7 +1349,7 @@ def add_comment(obj, note, force_push=False, **kwargs): j_issue = obj.jira_issue jira.add_comment( j_issue.jira_id, - '(%s): %s' % (note.author.get_full_name() if note.author.get_full_name() else note.author.username, note.entry)) + f'({note.author.get_full_name() if note.author.get_full_name() else note.author.username}): {note.entry}') return True except JIRAError as e: log_jira_generic_alert('Jira Add Comment Error', str(e)) @@ -1580,7 +1580,7 @@ def process_resolution_from_jira(finding, resolution_id, resolution_name, assign if resolved: if jira_instance and resolution_name in jira_instance.accepted_resolutions: if not finding.risk_accepted: - logger.debug("Marking related finding of {} as accepted. Creating risk acceptance.".format(jira_issue.jira_key)) + logger.debug(f"Marking related finding of {jira_issue.jira_key} as accepted. Creating risk acceptance.") finding.active = False finding.mitigated = None finding.is_mitigated = False @@ -1594,7 +1594,7 @@ def process_resolution_from_jira(finding, resolution_id, resolution_name, assign status_changed = True elif jira_instance and resolution_name in jira_instance.false_positive_resolutions: if not finding.false_p: - logger.debug("Marking related finding of {} as false-positive".format(jira_issue.jira_key)) + logger.debug(f"Marking related finding of {jira_issue.jira_key} as false-positive") finding.active = False finding.verified = False finding.mitigated = None @@ -1605,7 +1605,7 @@ def process_resolution_from_jira(finding, resolution_id, resolution_name, assign else: # Mitigated by default as before if not finding.is_mitigated: - logger.debug("Marking related finding of {} as mitigated (default)".format(jira_issue.jira_key)) + logger.debug(f"Marking related finding of {jira_issue.jira_key} as mitigated (default)") finding.active = False finding.mitigated = jira_now finding.is_mitigated = True @@ -1617,7 +1617,7 @@ def process_resolution_from_jira(finding, resolution_id, resolution_name, assign else: if not finding.active: # Reopen / Open Jira issue - logger.debug("Re-opening related finding of {}".format(jira_issue.jira_key)) + logger.debug(f"Re-opening related finding of {jira_issue.jira_key}") finding.active = True finding.mitigated = None finding.is_mitigated = False diff --git a/dojo/management/commands/dupecheck.py b/dojo/management/commands/dupecheck.py index ab7432fdec..92567173c9 100644 --- a/dojo/management/commands/dupecheck.py +++ b/dojo/management/commands/dupecheck.py @@ -17,13 +17,13 @@ def count_the_duplicates(self, model, column): print(" Table:" + str(model) + " Column: " + column) print("===================================") duplicates = model.objects.values(column).annotate(Count('id')).order_by().filter(id__count__gt=1) - kwargs = {'{0}__{1}'.format(column, 'in'): [item[column] for item in duplicates]} + kwargs = {'{}__{}'.format(column, 'in'): [item[column] for item in duplicates]} duplicates = model.objects.filter(**kwargs) if not duplicates: print("No duplicates found") for dupe in duplicates: - print('{0}, Duplicate value: {1}, Object: {2}'.format(dupe.id, getattr(dupe, column), dupe)) + print(f'{dupe.id}, Duplicate value: {getattr(dupe, column)}, Object: {dupe}') def handle(self, *args, **options): self.count_the_duplicates(Product, 'name') diff --git a/dojo/management/commands/import_github_languages.py b/dojo/management/commands/import_github_languages.py index b92ff7921f..bed838e9f6 100644 --- a/dojo/management/commands/import_github_languages.py +++ b/dojo/management/commands/import_github_languages.py @@ -33,7 +33,7 @@ def handle(self, *args, **options): try: language_type, created = Language_Type.objects.get_or_create(language=name) except Language_Type.MultipleObjectsReturned: - logger.warning('Language_Type {} exists multiple times'.format(name)) + logger.warning(f'Language_Type {name} exists multiple times') continue if created: @@ -42,4 +42,4 @@ def handle(self, *args, **options): language_type.color = element.get('color', 0) language_type.save() - logger.info('Finished importing languages from GitHub, added {} Language_Types'.format(new_language_types)) + logger.info(f'Finished importing languages from GitHub, added {new_language_types} Language_Types') diff --git a/dojo/management/commands/import_surveys.py b/dojo/management/commands/import_surveys.py index 75c2824726..5fc230fbb4 100644 --- a/dojo/management/commands/import_surveys.py +++ b/dojo/management/commands/import_surveys.py @@ -28,7 +28,7 @@ def handle(self, *args, **options): # Find the current id in the surveys file path = os.path.dirname(os.path.abspath(__file__)) path = path[:-19] + 'fixtures/initial_surveys.json' - contents = open(path, "rt").readlines() + contents = open(path).readlines() for line in contents: if '"polymorphic_ctype": ' in line: matchedLine = line @@ -37,7 +37,7 @@ def handle(self, *args, **options): old_id = ''.join(c for c in matchedLine if c.isdigit()) new_line = matchedLine.replace(old_id, str(ctype_id)) # Replace the all lines in the file - with open(path, "wt") as fout: + with open(path, "w") as fout: for line in contents: fout.write(line.replace(matchedLine, new_line)) # Delete the temp question diff --git a/dojo/metrics/views.py b/dojo/metrics/views.py index 03872c33ed..c7bef42c76 100644 --- a/dojo/metrics/views.py +++ b/dojo/metrics/views.py @@ -1033,7 +1033,7 @@ def view_engineer(request, eid): severity='Low' ).count() prod = Product.objects.get(id=product) - all_findings_link = "%s" % ( + all_findings_link = "{}".format( reverse('product_open_findings', args=(prod.id,)), escape(prod.name)) update.append([all_findings_link, z_count, o_count, t_count, h_count, z_count + o_count + t_count + h_count]) @@ -1066,7 +1066,7 @@ def view_engineer(request, eid): mitigated__isnull=True, severity='Low').count() prod = Product.objects.get(id=product) - all_findings_link = "%s" % ( + all_findings_link = "{}".format( reverse('product_open_findings', args=(prod.id,)), escape(prod.name)) total_update.append([all_findings_link, z_count, o_count, t_count, h_count, z_count + o_count + t_count + h_count]) diff --git a/dojo/middleware.py b/dojo/middleware.py index 733c66f4cd..4e54fe9e81 100644 --- a/dojo/middleware.py +++ b/dojo/middleware.py @@ -63,7 +63,7 @@ def __call__(self, request): return self.get_response(request) -class DojoSytemSettingsMiddleware(object): +class DojoSytemSettingsMiddleware: _thread_local = local() def __init__(self, get_response): @@ -106,7 +106,7 @@ class System_Settings_Manager(models.Manager): def get_from_db(self, *args, **kwargs): # logger.debug('refreshing system_settings from db') try: - from_db = super(System_Settings_Manager, self).get(*args, **kwargs) + from_db = super().get(*args, **kwargs) except: from dojo.models import System_Settings # this mimics the existing code that was in filters.py and utils.py. diff --git a/dojo/models.py b/dojo/models.py index a59af55ee9..53d9637e01 100755 --- a/dojo/models.py +++ b/dojo/models.py @@ -142,7 +142,7 @@ def __init__(self, directory=None, keep_basename=False, keep_ext=True): def __call__(self, model_instance, filename): base, ext = os.path.splitext(filename) - filename = "%s_%s" % (base, uuid4()) if self.keep_basename else str(uuid4()) + filename = f"{base}_{uuid4()}" if self.keep_basename else str(uuid4()) if self.keep_ext: filename += ext if self.directory is None: @@ -219,9 +219,7 @@ def generate_full_name(user): """ Returns the first_name plus the last_name, with a space in between. """ - full_name = '%s %s (%s)' % (user.first_name, - user.last_name, - user.username) + full_name = f'{user.first_name} {user.last_name} ({user.username})' return full_name.strip() @@ -690,12 +688,12 @@ def copy(self): copy.pk = None copy.id = None # Add unique modifier to file name - copy.title = '{} - clone-{}'.format(self.title, str(uuid4())[:8]) + copy.title = f'{self.title} - clone-{str(uuid4())[:8]}' # Create new unique file name current_url = self.file.url _, current_full_filename = current_url.rsplit('/', 1) _, extension = current_full_filename.split('.', 1) - new_file = ContentFile(self.file.read(), name='{}.{}'.format(uuid4(), extension)) + new_file = ContentFile(self.file.read(), name=f'{uuid4()}.{extension}') copy.file = new_file copy.save() @@ -709,11 +707,7 @@ def get_accessible_url(self, obj, obj_id): elif isinstance(obj, Finding): obj_type = 'Finding' - return 'access_file/{file_id}/{obj_id}/{obj_type}'.format( - file_id=self.id, - obj_id=obj_id, - obj_type=obj_type - ) + return f'access_file/{self.id}/{obj_id}/{obj_type}' class Product_Type(models.Model): @@ -857,7 +851,7 @@ def clean(self): raise ValidationError('Metadata entries may not have more than one relation, either a product, an endpoint either or a finding') def __str__(self): - return "%s: %s" % (self.name, self.value) + return f"{self.name}: {self.value}" class Meta: unique_together = (('product', 'name'), @@ -899,7 +893,7 @@ def save(self, *args, **kwargs): self.medium = initial_sla_config.medium self.low = initial_sla_config.low - super(SLA_Configuration, self).save(*args, **kwargs) + super().save(*args, **kwargs) # if the initial sla config exists and async finding update is not running if initial_sla_config is not None and not self.async_updating: @@ -917,7 +911,7 @@ def save(self, *args, **kwargs): if len(severities): # set the async updating flag to true for this sla config self.async_updating = True - super(SLA_Configuration, self).save(*args, **kwargs) + super().save(*args, **kwargs) # set the async updating flag to true for all products using this sla config products = Product.objects.filter(sla_configuration=self) for product in products: @@ -1060,7 +1054,7 @@ def save(self, *args, **kwargs): if initial_sla_config and self.async_updating: self.sla_configuration = initial_sla_config - super(Product, self).save(*args, **kwargs) + super().save(*args, **kwargs) # if the initial sla config exists and async finding update is not running if initial_sla_config is not None and not self.async_updating: @@ -1070,7 +1064,7 @@ def save(self, *args, **kwargs): if new_sla_config and (initial_sla_config != new_sla_config): # set the async updating flag to true for this product self.async_updating = True - super(Product, self).save(*args, **kwargs) + super().save(*args, **kwargs) # set the async updating flag to true for the sla config assigned to this product sla_config = getattr(self, 'sla_configuration', None) if sla_config: @@ -1552,7 +1546,7 @@ def age(self): return days if days > 0 else 0 def __str__(self): - return "'{}' on '{}'".format(str(self.finding), str(self.endpoint)) + return f"'{str(self.finding)}' on '{str(self.endpoint)}'" def copy(self, finding=None): copy = self @@ -1617,13 +1611,13 @@ def clean(self): db_type = connection.vendor if self.protocol or self.protocol == '': if not re.match(r'^[A-Za-z][A-Za-z0-9\.\-\+]+$', self.protocol): # https://tools.ietf.org/html/rfc3986#section-3.1 - errors.append(ValidationError('Protocol "{}" has invalid format'.format(self.protocol))) + errors.append(ValidationError(f'Protocol "{self.protocol}" has invalid format')) if self.protocol == '': self.protocol = None if self.userinfo or self.userinfo == '': if not re.match(r'^[A-Za-z0-9\.\-_~%\!\$&\'\(\)\*\+,;=:]+$', self.userinfo): # https://tools.ietf.org/html/rfc3986#section-3.2.1 - errors.append(ValidationError('Userinfo "{}" has invalid format'.format(self.userinfo))) + errors.append(ValidationError(f'Userinfo "{self.userinfo}" has invalid format')) if self.userinfo == '': self.userinfo = None @@ -1632,7 +1626,7 @@ def clean(self): try: validate_ipv46_address(self.host) except ValidationError: - errors.append(ValidationError('Host "{}" has invalid format'.format(self.host))) + errors.append(ValidationError(f'Host "{self.host}" has invalid format')) else: errors.append(ValidationError('Host must not be empty')) @@ -1640,10 +1634,10 @@ def clean(self): try: int_port = int(self.port) if not (0 <= int_port < 65536): - errors.append(ValidationError('Port "{}" has invalid format - out of range'.format(self.port))) + errors.append(ValidationError(f'Port "{self.port}" has invalid format - out of range')) self.port = int_port except ValueError: - errors.append(ValidationError('Port "{}" has invalid format - it is not a number'.format(self.port))) + errors.append(ValidationError(f'Port "{self.port}" has invalid format - it is not a number')) if self.path or self.path == '': while len(self.path) > 0 and self.path[0] == "/": # Endpoint store "root-less" path @@ -1654,7 +1648,7 @@ def clean(self): action_string = 'Postgres does not accept NULL character. Attempting to replace with %00...' for remove_str in null_char_list: self.path = self.path.replace(remove_str, '%00') - errors.append(ValidationError('Path "{}" has invalid format - It contains the NULL character. The following action was taken: {}'.format(old_value, action_string))) + errors.append(ValidationError(f'Path "{old_value}" has invalid format - It contains the NULL character. The following action was taken: {action_string}')) if self.path == '': self.path = None @@ -1667,7 +1661,7 @@ def clean(self): action_string = 'Postgres does not accept NULL character. Attempting to replace with %00...' for remove_str in null_char_list: self.query = self.query.replace(remove_str, '%00') - errors.append(ValidationError('Query "{}" has invalid format - It contains the NULL character. The following action was taken: {}'.format(old_value, action_string))) + errors.append(ValidationError(f'Query "{old_value}" has invalid format - It contains the NULL character. The following action was taken: {action_string}')) if self.query == '': self.query = None @@ -1680,7 +1674,7 @@ def clean(self): action_string = 'Postgres does not accept NULL character. Attempting to replace with %00...' for remove_str in null_char_list: self.fragment = self.fragment.replace(remove_str, '%00') - errors.append(ValidationError('Fragment "{}" has invalid format - It contains the NULL character. The following action was taken: {}'.format(old_value, action_string))) + errors.append(ValidationError(f'Fragment "{old_value}" has invalid format - It contains the NULL character. The following action was taken: {action_string}')) if self.fragment == '': self.fragment = None @@ -1699,11 +1693,11 @@ def __str__(self): path=tuple(self.path.split('/')) if self.path else (), query=tuple( ( - qe.split(u"=", 1) - if u"=" in qe + qe.split("=", 1) + if "=" in qe else (qe, None) ) - for qe in self.query.split(u"&") + for qe in self.query.split("&") ) if self.query else (), # inspired by https://github.com/python-hyper/hyperlink/blob/b8c9152cd826bbe8e6cc125648f3738235019705/src/hyperlink/_url.py#L1427 fragment=self.fragment or '' ) @@ -1722,19 +1716,19 @@ def __str__(self): except: url = '' if self.protocol: - url += '{}://'.format(self.protocol) + url += f'{self.protocol}://' if self.userinfo: - url += '{}@'.format(self.userinfo) + url += f'{self.userinfo}@' if self.host: url += self.host if self.port: - url += ':{}'.format(self.port) + url += f':{self.port}' if self.path: url += '{}{}'.format('/' if self.path[0] != '/' else '', self.path) if self.query: - url += '?{}'.format(self.query) + url += f'?{self.query}' if self.fragment: - url += '#{}'.format(self.fragment) + url += f'#{self.fragment}' return url def __hash__(self): @@ -1905,7 +1899,7 @@ def from_uri(uri): from urllib.parse import urlparse url = hyperlink.parse(url="//" + urlparse(uri).netloc) except hyperlink.URLParseError as e: - raise ValidationError('Invalid URL format: {}'.format(e)) + raise ValidationError(f'Invalid URL format: {e}') query_parts = [] # inspired by https://github.com/python-hyper/hyperlink/blob/b8c9152cd826bbe8e6cc125648f3738235019705/src/hyperlink/_url.py#L1768 for k, v in url.query: @@ -1913,7 +1907,7 @@ def from_uri(uri): query_parts.append(k) else: query_parts.append(f"{k}={v}") - query_string = u"&".join(query_parts) + query_string = "&".join(query_parts) protocol = url.scheme if url.scheme != '' else None userinfo = ':'.join(url.userinfo) if url.userinfo not in [(), ('',)] else None @@ -2019,7 +2013,7 @@ def test_type_name(self) -> str: def __str__(self): if self.title: - return "%s (%s)" % (self.title, self.test_type) + return f"{self.title} ({self.test_type})" return str(self.test_type) def get_breadcrumbs(self): @@ -2561,7 +2555,7 @@ class Meta: ] def __init__(self, *args, **kwargs): - super(Finding, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.unsaved_endpoints = [] self.unsaved_request = None @@ -3053,7 +3047,7 @@ def save(self, dedupe_option=True, rules_option=True, product_grading_option=Tru self.set_sla_expiration_date() logger.debug("Saving finding of id " + str(self.id) + " dedupe_option:" + str(dedupe_option) + " (self.pk is %s)", "None" if self.pk is None else "not None") - super(Finding, self).save(*args, **kwargs) + super().save(*args, **kwargs) self.found_by.add(self.test.test_type) @@ -3087,7 +3081,7 @@ def get_breadcrumbs(self): return bc def get_valid_request_response_pairs(self): - empty_value = base64.b64encode("".encode()) + empty_value = base64.b64encode(b"") # Get a list of all req/resp pairs all_req_resps = self.burprawrequestresponse_set.all() # Filter away those that do not have any contents @@ -3711,7 +3705,7 @@ class FileAccessToken(models.Model): def save(self, *args, **kwargs): if not self.token: self.token = uuid4() - return super(FileAccessToken, self).save(*args, **kwargs) + return super().save(*args, **kwargs) ANNOUNCEMENT_STYLE_CHOICES = ( diff --git a/dojo/notifications/helper.py b/dojo/notifications/helper.py index 4cfa65bdda..1ee9a9be20 100644 --- a/dojo/notifications/helper.py +++ b/dojo/notifications/helper.py @@ -93,7 +93,7 @@ def create_notification(event=None, **kwargs): queryset=Notifications.objects.filter(Q(product_id=product) | Q(product__isnull=True)), to_attr="applicable_notifications" )).annotate(applicable_notifications_count=Count('notifications__id', filter=Q(notifications__product_id=product) | Q(notifications__product__isnull=True)))\ - .filter((Q(applicable_notifications_count__gt=0) | Q(is_superuser=True))) + .filter(Q(applicable_notifications_count__gt=0) | Q(is_superuser=True)) # only send to authorized users or admin/superusers logger.debug('Filtering users for the product %s', product) @@ -126,11 +126,11 @@ def create_notification(event=None, **kwargs): def create_description(event, *args, **kwargs): if "description" not in kwargs.keys(): if event == 'product_added': - kwargs["description"] = _('Product %(title)s has been created successfully.' % {'title': kwargs['title']}) + kwargs["description"] = _('Product {title} has been created successfully.'.format(title=kwargs['title'])) elif event == 'product_type_added': - kwargs["description"] = _('Product Type %(title)s has been created successfully.' % {'title': kwargs['title']}) + kwargs["description"] = _('Product Type {title} has been created successfully.'.format(title=kwargs['title'])) else: - kwargs["description"] = _('Event %(event)s has occurred.' % {'event': str(event)}) + kwargs["description"] = _('Event {event} has occurred.'.format(event=str(event))) return kwargs["description"] @@ -227,7 +227,7 @@ def _post_slack_message(channel): # only send notification if we managed to find the slack_user_id if slack_user_id: - channel = '@{}'.format(slack_user_id) + channel = f'@{slack_user_id}' _post_slack_message(channel) else: logger.info("The user %s does not have a email address informed for Slack in profile.", user) @@ -235,7 +235,7 @@ def _post_slack_message(channel): # System scope slack notifications, and not personal would still see this go through if get_system_setting('slack_channel') is not None: channel = get_system_setting('slack_channel') - logger.info("Sending system notification to system channel {}.".format(channel)) + logger.info(f"Sending system notification to system channel {channel}.") _post_slack_message(channel) else: logger.debug('slack_channel not configured: skipping system notification') @@ -354,10 +354,10 @@ def get_slack_user_id(user_email): if user_email == user["user"]["profile"]["email"]: if "id" in user["user"]: user_id = user["user"]["id"] - logger.debug("Slack user ID is {}".format(user_id)) + logger.debug(f"Slack user ID is {user_id}") slack_user_is_found = True else: - logger.warning("A user with email {} could not be found in this Slack workspace.".format(user_email)) + logger.warning(f"A user with email {user_email} could not be found in this Slack workspace.") if not slack_user_is_found: logger.warning("The Slack user was not found.") diff --git a/dojo/okta.py b/dojo/okta.py index 27ea21084d..856f6004e8 100644 --- a/dojo/okta.py +++ b/dojo/okta.py @@ -12,7 +12,7 @@ from social_core.backends.open_id_connect import OpenIdConnectAuth -class OktaMixin(object): +class OktaMixin: def api_url(self): return append_slash(self.setting('API_URL')) diff --git a/dojo/product_type/views.py b/dojo/product_type/views.py index 84bb14c108..fbc4aae063 100644 --- a/dojo/product_type/views.py +++ b/dojo/product_type/views.py @@ -139,7 +139,7 @@ def delete_product_type(request, ptid): create_notification(event='other', title='Deletion of %s' % product_type.name, no_users=True, - description='The product type "%s" was deleted by %s' % (product_type.name, request.user), + description=f'The product type "{product_type.name}" was deleted by {request.user}', url=request.build_absolute_uri(reverse('product_type')), icon="exclamation-triangle") return HttpResponseRedirect(reverse('product_type')) diff --git a/dojo/reports/widgets.py b/dojo/reports/widgets.py index 36831c4ad0..09eb164620 100644 --- a/dojo/reports/widgets.py +++ b/dojo/reports/widgets.py @@ -57,7 +57,7 @@ def __init__(self, attrs=None): default_attrs = {'style': 'width:100%;min-height:400px'} if attrs: default_attrs.update(attrs) - super(Div, self).__init__(default_attrs) + super().__init__(default_attrs) def render(self, name, value, attrs=None, renderer=None): if value is None: @@ -109,7 +109,7 @@ class Meta: # base Widget class others will inherit from -class Widget(object): +class Widget: def __init__(self, *args, **kwargs): self.title = 'Base Widget' self.form = None @@ -130,7 +130,7 @@ def get_option_form(self): class PageBreak(Widget): def __init__(self, *args, **kwargs): - super(PageBreak, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.title = 'Page Break' self.form = None self.multiple = "true" @@ -151,7 +151,7 @@ def get_option_form(self): class ReportOptions(Widget): def __init__(self, *args, **kwargs): - super(ReportOptions, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.title = 'Report Options' self.form = CustomReportOptionsForm() self.extra_help = "Choose additional report options. These will apply to the overall report." @@ -172,7 +172,7 @@ def get_option_form(self): class CoverPage(Widget): def __init__(self, *args, **kwargs): - super(CoverPage, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.title = 'Cover Page' self.form = CoverPageForm() self.help_text = "The cover page includes a page break after its content." @@ -197,7 +197,7 @@ def get_option_form(self): class TableOfContents(Widget): def __init__(self, *args, **kwargs): - super(TableOfContents, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.title = 'Table Of Contents' self.form = TableOfContentsForm() self.help_text = "The table of contents includes a page break after its content." @@ -220,7 +220,7 @@ def get_option_form(self): class WYSIWYGContent(Widget): def __init__(self, *args, **kwargs): - super(WYSIWYGContent, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.title = 'WYSIWYG Content' self.form = WYSIWYGContentForm() self.multiple = 'true' @@ -267,7 +267,7 @@ def __init__(self, *args, **kwargs): else: self.finding_images = False - super(FindingList, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.title = 'Finding List' if hasattr(self.findings, 'form'): @@ -342,7 +342,7 @@ def __init__(self, *args, **kwargs): else: self.finding_images = False - super(EndpointList, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.title = 'Endpoint List' self.form = self.endpoints.form diff --git a/dojo/risk_acceptance/helper.py b/dojo/risk_acceptance/helper.py index 8034ce713c..7fcaa796c9 100644 --- a/dojo/risk_acceptance/helper.py +++ b/dojo/risk_acceptance/helper.py @@ -208,8 +208,7 @@ def accepted_message_creator(risk_acceptance, heads_up_days=0): def unaccepted_message_creator(risk_acceptance, heads_up_days=0): if risk_acceptance: - return 'finding was unaccepted/deleted from risk acceptance [(%s)|%s]' % \ - (escape_for_jira(risk_acceptance.name), + return 'finding was unaccepted/deleted from risk acceptance [({})|{}]'.format(escape_for_jira(risk_acceptance.name), get_full_url(reverse('view_risk_acceptance', args=(risk_acceptance.engagement.id, risk_acceptance.id)))) else: return 'Finding is no longer risk accepted' diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index 2126ad82d9..add788caaa 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -1261,10 +1261,10 @@ def saml2_attrib_map_format(dict): env_hashcode_fields_per_scanner = json.loads(env('DD_HASHCODE_FIELDS_PER_SCANNER')) for key, value in env_hashcode_fields_per_scanner.items(): if key in HASHCODE_FIELDS_PER_SCANNER: - logger.info("Replacing {} with value {} (previously set to {}) from env var DD_HASHCODE_FIELDS_PER_SCANNER".format(key, value, HASHCODE_FIELDS_PER_SCANNER[key])) + logger.info(f"Replacing {key} with value {value} (previously set to {HASHCODE_FIELDS_PER_SCANNER[key]}) from env var DD_HASHCODE_FIELDS_PER_SCANNER") HASHCODE_FIELDS_PER_SCANNER[key] = value if key not in HASHCODE_FIELDS_PER_SCANNER: - logger.info("Adding {} with value {} from env var DD_HASHCODE_FIELDS_PER_SCANNER".format(key, value)) + logger.info(f"Adding {key} with value {value} from env var DD_HASHCODE_FIELDS_PER_SCANNER") HASHCODE_FIELDS_PER_SCANNER[key] = value @@ -1477,10 +1477,10 @@ def saml2_attrib_map_format(dict): env_dedup_algorithm_per_parser = json.loads(env('DD_DEDUPLICATION_ALGORITHM_PER_PARSER')) for key, value in env_dedup_algorithm_per_parser.items(): if key in DEDUPLICATION_ALGORITHM_PER_PARSER: - logger.info("Replacing {} with value {} (previously set to {}) from env var DD_DEDUPLICATION_ALGORITHM_PER_PARSER".format(key, value, DEDUPLICATION_ALGORITHM_PER_PARSER[key])) + logger.info(f"Replacing {key} with value {value} (previously set to {DEDUPLICATION_ALGORITHM_PER_PARSER[key]}) from env var DD_DEDUPLICATION_ALGORITHM_PER_PARSER") DEDUPLICATION_ALGORITHM_PER_PARSER[key] = value if key not in DEDUPLICATION_ALGORITHM_PER_PARSER: - logger.info("Adding {} with value {} from env var DD_DEDUPLICATION_ALGORITHM_PER_PARSER".format(key, value)) + logger.info(f"Adding {key} with value {value} from env var DD_DEDUPLICATION_ALGORITHM_PER_PARSER") DEDUPLICATION_ALGORITHM_PER_PARSER[key] = value DUPE_DELETE_MAX_PER_RUN = env('DD_DUPE_DELETE_MAX_PER_RUN') diff --git a/dojo/survey/views.py b/dojo/survey/views.py index 02fc9f74d5..02191342a8 100644 --- a/dojo/survey/views.py +++ b/dojo/survey/views.py @@ -484,8 +484,7 @@ def create_question(request): error = True if '_popup' in request.GET and not error: - resp = '' \ - % (escape(created_question._get_pk_val()), escape(created_question.text)) + resp = f'' resp += '' return HttpResponse(resp) @@ -577,8 +576,7 @@ def add_choices(request): if '_popup' in request.GET: resp = '' if created: - resp = '' \ - % (escape(choice._get_pk_val()), escape(choice.label)) + resp = f'' resp += '' return HttpResponse(resp) add_breadcrumb(title="Add Choice", top_level=False, request=request) diff --git a/dojo/tasks.py b/dojo/tasks.py index 50d48049a8..25d258f9ee 100644 --- a/dojo/tasks.py +++ b/dojo/tasks.py @@ -43,7 +43,7 @@ def add_alerts(self, runinterval): for eng in stale_engagements: create_notification(event='stale_engagement', title='Stale Engagement: %s' % eng.name, - description='The engagement "%s" is stale. Target end was %s.' % (eng.name, eng.target_end.strftime("%b. %d, %Y")), + description='The engagement "{}" is stale. Target end was {}.'.format(eng.name, eng.target_end.strftime("%b. %d, %Y")), url=reverse('view_engagement', args=(eng.id,)), recipients=[eng.lead]) @@ -57,7 +57,7 @@ def add_alerts(self, runinterval): for eng in unclosed_engagements: create_notification(event='auto_close_engagement', title=eng.name, - description='The engagement "%s" has auto-closed. Target end was %s.' % (eng.name, eng.target_end.strftime("%b. %d, %Y")), + description='The engagement "{}" has auto-closed. Target end was {}.'.format(eng.name, eng.target_end.strftime("%b. %d, %Y")), url=reverse('view_engagement', args=(eng.id,)), recipients=[eng.lead]) @@ -139,8 +139,8 @@ def async_dupe_delete(*args, **kwargs): originals_with_too_many_duplicates = Finding.objects.filter(id__in=originals_with_too_many_duplicates_ids).order_by('id') # prefetch to make it faster - originals_with_too_many_duplicates = originals_with_too_many_duplicates.prefetch_related((Prefetch("original_finding", - queryset=Finding.objects.filter(duplicate=True).order_by('date')))) + originals_with_too_many_duplicates = originals_with_too_many_duplicates.prefetch_related(Prefetch("original_finding", + queryset=Finding.objects.filter(duplicate=True).order_by('date'))) total_deleted_count = 0 for original in originals_with_too_many_duplicates: @@ -148,7 +148,7 @@ def async_dupe_delete(*args, **kwargs): dupe_count = len(duplicate_list) - dupe_max for finding in duplicate_list: - deduplicationLogger.debug('deleting finding {}:{} ({}))'.format(finding.id, finding.title, finding.hash_code)) + deduplicationLogger.debug(f'deleting finding {finding.id}:{finding.title} ({finding.hash_code}))') finding.delete() total_deleted_count += 1 dupe_count -= 1 @@ -177,7 +177,7 @@ def async_sla_compute_and_notify_task(*args, **kwargs): sla_compute_and_notify(*args, **kwargs) except Exception as e: logger.exception(e) - logger.error("An unexpected error was thrown calling the SLA code: {}".format(e)) + logger.error(f"An unexpected error was thrown calling the SLA code: {e}") @app.task diff --git a/dojo/templatetags/display_tags.py b/dojo/templatetags/display_tags.py index f49fba54bc..221daf0413 100644 --- a/dojo/templatetags/display_tags.py +++ b/dojo/templatetags/display_tags.py @@ -135,7 +135,7 @@ def dojo_version(): version = __version__ if settings.FOOTER_VERSION: version = settings.FOOTER_VERSION - return "v. {}".format(version) + return f"v. {version}" @register.simple_tag diff --git a/dojo/templatetags/navigation_tags.py b/dojo/templatetags/navigation_tags.py index a6d53f0082..e446dd842d 100644 --- a/dojo/templatetags/navigation_tags.py +++ b/dojo/templatetags/navigation_tags.py @@ -69,7 +69,7 @@ def dojo_sort(request, display='Name', value='title', default=None): return safe(link) -class PaginationNav(object): +class PaginationNav: def __init__(self, page_number=None, display=None, is_current=False): self.page_number = page_number self.is_current = is_current diff --git a/dojo/test/views.py b/dojo/test/views.py index ca3d60e16f..0ddd446404 100644 --- a/dojo/test/views.py +++ b/dojo/test/views.py @@ -346,7 +346,7 @@ def copy_test(request, tid): extra_tags='alert-success') create_notification(event='other', title='Copying of %s' % test.title, - description='The test "%s" was copied by %s to %s' % (test.title, request.user, engagement.name), + description=f'The test "{test.title}" was copied by {request.user} to {engagement.name}', product=product, url=request.build_absolute_uri(reverse('view_test', args=(test_copy.id,))), recipients=[test.engagement.lead], @@ -412,7 +412,7 @@ def test_ics(request, tid): _("Set aside for test %(test_type_name)s, on product %(product_name)s. Additional detail can be found at %(detail_url)s") % { 'test_type_name': test.test_type.name, 'product_name': test.engagement.product.name, - 'detail_url': request.build_absolute_uri((reverse("view_test", args=(test.id,)))) + 'detail_url': request.build_absolute_uri(reverse("view_test", args=(test.id,))) }, uid) output = cal.serialize() diff --git a/dojo/tools/acunetix/parse_acunetix360_json.py b/dojo/tools/acunetix/parse_acunetix360_json.py index f9fff0b109..0f8c01c581 100644 --- a/dojo/tools/acunetix/parse_acunetix360_json.py +++ b/dojo/tools/acunetix/parse_acunetix360_json.py @@ -5,7 +5,7 @@ from dojo.models import Endpoint, Finding -class AcunetixJSONParser(object): +class AcunetixJSONParser: """This parser is written for Acunetix JSON Findings.""" def get_findings(self, filename, test): dupes = dict() diff --git a/dojo/tools/acunetix/parse_acunetix_xml.py b/dojo/tools/acunetix/parse_acunetix_xml.py index 12ca4100a0..529da45e99 100644 --- a/dojo/tools/acunetix/parse_acunetix_xml.py +++ b/dojo/tools/acunetix/parse_acunetix_xml.py @@ -9,7 +9,7 @@ logger = logging.getLogger(__name__) -class AcunetixXMLParser(object): +class AcunetixXMLParser: """This parser is written for Acunetix XML reports""" def get_findings(self, filename, test): dupes = dict() @@ -54,7 +54,7 @@ def get_findings(self, filename, test): for reference in item.findall("References/Reference"): url = reference.findtext("URL") db = reference.findtext("Database") or url - references.append(" * [{}]({})".format(db, url)) + references.append(f" * [{db}]({url})") if len(references) > 0: finding.references = "\n".join(references) if item.findtext("CVSS3/Descriptor"): @@ -128,9 +128,7 @@ def get_findings(self, filename, test): find.unsaved_req_resp.extend(finding.unsaved_req_resp) find.nb_occurences += finding.nb_occurences logger.debug( - "Duplicate finding : {defectdojo_title}".format( - defectdojo_title=finding.title - ) + f"Duplicate finding : {finding.title}" ) else: dupes[dupe_key] = finding diff --git a/dojo/tools/acunetix/parser.py b/dojo/tools/acunetix/parser.py index 9d0ee77123..272f295acf 100644 --- a/dojo/tools/acunetix/parser.py +++ b/dojo/tools/acunetix/parser.py @@ -2,7 +2,7 @@ from dojo.tools.acunetix.parse_acunetix_xml import AcunetixXMLParser -class AcunetixParser(object): +class AcunetixParser: """Parser for Acunetix XML files and Acunetix 360 JSON files.""" def get_scan_types(self): diff --git a/dojo/tools/anchore_engine/parser.py b/dojo/tools/anchore_engine/parser.py index 3b9e0bc546..f734b4a489 100644 --- a/dojo/tools/anchore_engine/parser.py +++ b/dojo/tools/anchore_engine/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class AnchoreEngineParser(object): +class AnchoreEngineParser: def get_scan_types(self): return ["Anchore Engine Scan"] diff --git a/dojo/tools/anchore_enterprise/parser.py b/dojo/tools/anchore_enterprise/parser.py index 899e600a51..82dad174d7 100644 --- a/dojo/tools/anchore_enterprise/parser.py +++ b/dojo/tools/anchore_enterprise/parser.py @@ -69,9 +69,7 @@ def get_findings(self, filename, test): test=test, description=description, severity=severity, - references="Policy ID: {}\nTrigger ID: {}".format( - policyid, triggerid - ), + references=f"Policy ID: {policyid}\nTrigger ID: {triggerid}", file_path=search_filepath(description), component_name=repo, component_version=tag, @@ -86,9 +84,7 @@ def get_findings(self, filename, test): items.append(find) except (KeyError, IndexError) as err: raise ValueError( - "Invalid format: {} key not found".format( - err - ) + f"Invalid format: {err} key not found" ) except AttributeError as err: # import empty policies without error (e.g. policies or images diff --git a/dojo/tools/anchore_grype/parser.py b/dojo/tools/anchore_grype/parser.py index 9854bf34d5..ad04aaf3b7 100644 --- a/dojo/tools/anchore_grype/parser.py +++ b/dojo/tools/anchore_grype/parser.py @@ -5,7 +5,7 @@ from dojo.models import Finding -class AnchoreGrypeParser(object): +class AnchoreGrypeParser: """Anchore Grype JSON report format generated with `-o json` option. command: `grype defectdojo/defectdojo-django:1.13.1 -o json > many_vulns.json` diff --git a/dojo/tools/anchorectl_policies/parser.py b/dojo/tools/anchorectl_policies/parser.py index 1df2fa94f9..3de3f5d0c1 100644 --- a/dojo/tools/anchorectl_policies/parser.py +++ b/dojo/tools/anchorectl_policies/parser.py @@ -54,9 +54,7 @@ def get_findings(self, filename, test): test=test, description=description, severity=severity, - references="Policy ID: {}\nTrigger ID: {}".format( - policy_id, trigger_id - ), + references=f"Policy ID: {policy_id}\nTrigger ID: {trigger_id}", file_path=search_filepath(description), component_name=repo, component_version=tag, @@ -69,7 +67,7 @@ def get_findings(self, filename, test): items.append(find) except (KeyError, IndexError) as err: raise ValueError( - "Invalid format: {} key not found".format(err) + f"Invalid format: {err} key not found" ) except AttributeError as err: # import empty policies without error (e.g. policies or images diff --git a/dojo/tools/anchorectl_vulns/parser.py b/dojo/tools/anchorectl_vulns/parser.py index 77c350b56b..652ac821af 100644 --- a/dojo/tools/anchorectl_vulns/parser.py +++ b/dojo/tools/anchorectl_vulns/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class AnchoreCTLVulnsParser(object): +class AnchoreCTLVulnsParser: def get_scan_types(self): return ["AnchoreCTL Vuln Report"] diff --git a/dojo/tools/api_blackduck/api_client.py b/dojo/tools/api_blackduck/api_client.py index fb8058bc8b..a2895dc5be 100644 --- a/dojo/tools/api_blackduck/api_client.py +++ b/dojo/tools/api_blackduck/api_client.py @@ -17,9 +17,7 @@ def __init__(self, tool_config): ) else: raise ValueError( - "Authentication type {} not supported".format( - tool_config.authentication_type - ) + f"Authentication type {tool_config.authentication_type} not supported" ) # TODO diff --git a/dojo/tools/api_blackduck/importer.py b/dojo/tools/api_blackduck/importer.py index cf7a143bb9..af0917a0e5 100644 --- a/dojo/tools/api_blackduck/importer.py +++ b/dojo/tools/api_blackduck/importer.py @@ -4,7 +4,7 @@ from .api_client import BlackduckAPI -class BlackduckApiImporter(object): +class BlackduckApiImporter: """ Import from BlackDuck API """ diff --git a/dojo/tools/api_blackduck/parser.py b/dojo/tools/api_blackduck/parser.py index be76f28c6e..0be6680787 100644 --- a/dojo/tools/api_blackduck/parser.py +++ b/dojo/tools/api_blackduck/parser.py @@ -7,7 +7,7 @@ SCAN_TYPE_ID = "BlackDuck API" -class ApiBlackduckParser(object): +class ApiBlackduckParser: """ Import from Synopsys BlackDuck API /findings """ diff --git a/dojo/tools/api_bugcrowd/api_client.py b/dojo/tools/api_bugcrowd/api_client.py index ddb73f0b0a..f1207bd77a 100644 --- a/dojo/tools/api_bugcrowd/api_client.py +++ b/dojo/tools/api_bugcrowd/api_client.py @@ -19,14 +19,12 @@ def __init__(self, tool_config): if tool_config.authentication_type == "API": self.api_token = tool_config.api_key self.session.headers.update( - {"Authorization": "Token {}".format(self.api_token)} + {"Authorization": f"Token {self.api_token}"} ) self.session.headers.update(self.default_headers) else: raise Exception( - "bugcrowd Authentication type {} not supported".format( - tool_config.authentication_type - ) + f"bugcrowd Authentication type {tool_config.authentication_type} not supported" ) def get_findings(self, program, target): @@ -53,9 +51,7 @@ def get_findings(self, program, target): else: params_encoded = urlencode(params_default) - next = "{}/submissions?{}".format( - self.bugcrowd_api_url, params_encoded - ) + next = f"{self.bugcrowd_api_url}/submissions?{params_encoded}" while next != "": response = self.session.get(url=next) response.raise_for_status() @@ -79,13 +75,13 @@ def get_findings(self, program, target): def test_connection(self): # Request programs response_programs = self.session.get( - url="{}/programs".format(self.bugcrowd_api_url) + url=f"{self.bugcrowd_api_url}/programs" ) response_programs.raise_for_status() # Request submissions to validate the org token response_subs = self.session.get( - url="{}/submissions".format(self.bugcrowd_api_url) + url=f"{self.bugcrowd_api_url}/submissions" ) response_subs.raise_for_status() if response_programs.ok and response_subs.ok: @@ -99,7 +95,7 @@ def test_connection(self): ) # Request targets to validate the org token response_targets = self.session.get( - url="{}/targets".format(self.bugcrowd_api_url) + url=f"{self.bugcrowd_api_url}/targets" ) response_targets.raise_for_status() if response_targets.ok: @@ -119,16 +115,12 @@ def test_connection(self): else: raise Exception( "Bugcrowd API test not successful, no targets were defined in Bugcrowd which is used for " - "filtering, check your configuration, HTTP response was: {}".format( - response_targets.text - ) + f"filtering, check your configuration, HTTP response was: {response_targets.text}" ) else: raise Exception( "Bugcrowd API test not successful, could not retrieve the programs or submissions, check your " - "configuration, HTTP response for programs was: {}, HTTP response for submissions was: {}".format( - response_programs.text, response_subs.text - ) + f"configuration, HTTP response for programs was: {response_programs.text}, HTTP response for submissions was: {response_subs.text}" ) def test_product_connection(self, api_scan_configuration): diff --git a/dojo/tools/api_bugcrowd/importer.py b/dojo/tools/api_bugcrowd/importer.py index 3e41b6be20..56b7ca1a22 100644 --- a/dojo/tools/api_bugcrowd/importer.py +++ b/dojo/tools/api_bugcrowd/importer.py @@ -6,7 +6,7 @@ logger = logging.getLogger(__name__) -class BugcrowdApiImporter(object): +class BugcrowdApiImporter: """ Import from Bugcrowd API """ @@ -14,9 +14,7 @@ class BugcrowdApiImporter(object): def get_findings(self, test): client, config = self.prepare_client(test) logger.debug( - "Fetching submissions program {} and target {}".format( - str(config.service_key_1), str(config.service_key_2) - ) + f"Fetching submissions program {str(config.service_key_1)} and target {str(config.service_key_2)}" ) submissions_paged = client.get_findings( @@ -29,7 +27,7 @@ def get_findings(self, test): for page in submissions_paged: submissions += page counter += 1 - logger.debug("{} Bugcrowd submissions pages fetched".format(counter)) + logger.debug(f"{counter} Bugcrowd submissions pages fetched") return submissions, config diff --git a/dojo/tools/api_bugcrowd/parser.py b/dojo/tools/api_bugcrowd/parser.py index 17cc04f84d..df119ed576 100644 --- a/dojo/tools/api_bugcrowd/parser.py +++ b/dojo/tools/api_bugcrowd/parser.py @@ -16,7 +16,7 @@ logger = logging.getLogger(__name__) -class ApiBugcrowdParser(object): +class ApiBugcrowdParser: """ Import from Bugcrowd API /submissions """ @@ -158,15 +158,11 @@ def get_findings(self, file, test): finding.unsaved_endpoints = [bug_endpoint] except Exception as e: logger.error( - "{} bug url from bugcrowd failed to parse to endpoint, error= {}".format( - str(bug_endpoint), e - ) + f"{str(bug_endpoint)} bug url from bugcrowd failed to parse to endpoint, error= {e}" ) except ValidationError: logger.error( - "Broken Bugcrowd endpoint {} was skipped.".format( - bug_endpoint.host - ) + f"Broken Bugcrowd endpoint {bug_endpoint.host} was skipped." ) findings.append(finding) diff --git a/dojo/tools/api_cobalt/api_client.py b/dojo/tools/api_cobalt/api_client.py index f51cef1dbe..e18ed6f01f 100644 --- a/dojo/tools/api_cobalt/api_client.py +++ b/dojo/tools/api_cobalt/api_client.py @@ -15,9 +15,7 @@ def __init__(self, tool_config): self.org_token = tool_config.extras else: raise Exception( - "Cobalt.io Authentication type {} not supported".format( - tool_config.authentication_type - ) + f"Cobalt.io Authentication type {tool_config.authentication_type} not supported" ) def get_asset(self, asset_id): @@ -32,12 +30,12 @@ def get_asset(self, asset_id): if asset["resource"]["id"] == asset_id: return asset - raise Exception("Asset {} not found in organisation".format(asset_id)) + raise Exception(f"Asset {asset_id} not found in organisation") def get_assets(self): """Returns all org assets""" response = self.session.get( - url="{}/assets?limit=1000".format(self.cobalt_api_url), + url=f"{self.cobalt_api_url}/assets?limit=1000", headers=self.get_headers(), ) @@ -57,9 +55,7 @@ def get_findings(self, asset_id): :return: """ response = self.session.get( - url="{}/findings?limit=1000&asset={}".format( - self.cobalt_api_url, asset_id - ), + url=f"{self.cobalt_api_url}/findings?limit=1000&asset={asset_id}", headers=self.get_headers(), ) @@ -75,13 +71,13 @@ def get_findings(self, asset_id): def test_connection(self): # Request orgs for the org name response_orgs = self.session.get( - url="{}/orgs".format(self.cobalt_api_url), + url=f"{self.cobalt_api_url}/orgs", headers=self.get_headers(), ) # Request assets to validate the org token response_assets = self.session.get( - url="{}/assets".format(self.cobalt_api_url), + url=f"{self.cobalt_api_url}/assets", headers=self.get_headers(), ) @@ -111,7 +107,7 @@ def test_product_connection(self, api_scan_configuration): def get_headers(self): headers = { "accept": "application/vnd.cobalt.v1+json", - "Authorization": "Bearer {}".format(self.api_token), + "Authorization": f"Bearer {self.api_token}", "User-Agent": "DefectDojo", } diff --git a/dojo/tools/api_cobalt/importer.py b/dojo/tools/api_cobalt/importer.py index 93ba6a06e0..9f3a291f4a 100644 --- a/dojo/tools/api_cobalt/importer.py +++ b/dojo/tools/api_cobalt/importer.py @@ -6,7 +6,7 @@ logger = logging.getLogger(__name__) -class CobaltApiImporter(object): +class CobaltApiImporter: """ Import from Cobalt.io API """ diff --git a/dojo/tools/api_cobalt/parser.py b/dojo/tools/api_cobalt/parser.py index 0e77b0d279..6be1a4e855 100644 --- a/dojo/tools/api_cobalt/parser.py +++ b/dojo/tools/api_cobalt/parser.py @@ -8,7 +8,7 @@ SCAN_COBALTIO_API = "Cobalt.io API Import" -class ApiCobaltParser(object): +class ApiCobaltParser: """ Import from Cobalt.io API /findings """ diff --git a/dojo/tools/api_edgescan/api_client.py b/dojo/tools/api_edgescan/api_client.py index 8e2f11ad09..a49c7686eb 100644 --- a/dojo/tools/api_edgescan/api_client.py +++ b/dojo/tools/api_edgescan/api_client.py @@ -3,7 +3,7 @@ from json.decoder import JSONDecodeError -class EdgescanAPI(object): +class EdgescanAPI: """ A simple client for the Edgescan API """ @@ -17,9 +17,7 @@ def __init__(self, tool_config): self.options = self.get_extra_options(tool_config) else: raise Exception( - "Edgescan Authentication type {} not supported".format( - tool_config.authentication_type - ) + f"Edgescan Authentication type {tool_config.authentication_type} not supported" ) @staticmethod diff --git a/dojo/tools/api_edgescan/importer.py b/dojo/tools/api_edgescan/importer.py index dc97edf82a..5857b188ab 100644 --- a/dojo/tools/api_edgescan/importer.py +++ b/dojo/tools/api_edgescan/importer.py @@ -3,7 +3,7 @@ from .api_client import EdgescanAPI -class EdgescanImporter(object): +class EdgescanImporter: """ Import from Edgescan API """ diff --git a/dojo/tools/api_edgescan/parser.py b/dojo/tools/api_edgescan/parser.py index 3e186e6d6b..8442c7cc66 100644 --- a/dojo/tools/api_edgescan/parser.py +++ b/dojo/tools/api_edgescan/parser.py @@ -8,7 +8,7 @@ SCANTYPE_EDGESCAN = "Edgescan Scan" -class ApiEdgescanParser(object): +class ApiEdgescanParser: """ Import from Edgescan API or JSON file """ diff --git a/dojo/tools/api_sonarqube/importer.py b/dojo/tools/api_sonarqube/importer.py index 31a5c62e77..6d4d1577f5 100644 --- a/dojo/tools/api_sonarqube/importer.py +++ b/dojo/tools/api_sonarqube/importer.py @@ -14,7 +14,7 @@ logger = logging.getLogger(__name__) -class SonarQubeApiImporter(object): +class SonarQubeApiImporter: """ This class imports from SonarQube (SQ) all open/confirmed SQ issues related to the project related to the test as findings. diff --git a/dojo/tools/api_sonarqube/parser.py b/dojo/tools/api_sonarqube/parser.py index f4e7162d31..8a57a8d80b 100644 --- a/dojo/tools/api_sonarqube/parser.py +++ b/dojo/tools/api_sonarqube/parser.py @@ -4,7 +4,7 @@ SCAN_SONARQUBE_API = "SonarQube API Import" -class ApiSonarQubeParser(object): +class ApiSonarQubeParser: def get_scan_types(self): return [SCAN_SONARQUBE_API] diff --git a/dojo/tools/api_sonarqube/updater.py b/dojo/tools/api_sonarqube/updater.py index b481568773..4cbf28dc3e 100644 --- a/dojo/tools/api_sonarqube/updater.py +++ b/dojo/tools/api_sonarqube/updater.py @@ -7,7 +7,7 @@ logger = logging.getLogger(__name__) -class SonarQubeApiUpdater(object): +class SonarQubeApiUpdater: """ This class updates in SonarQube, a SonarQube issue previously imported as a DefectDojo Findings. This class maps the finding status to a SQ issue status and later on it transitions the issue @@ -119,9 +119,7 @@ def update_sonarqube_finding(self, finding): return logger.debug( - "Checking if finding '{}' needs to be updated in SonarQube".format( - finding - ) + f"Checking if finding '{finding}' needs to be updated in SonarQube" ) client, _ = SonarQubeApiImporter.prepare_client(finding.test) @@ -142,9 +140,7 @@ def update_sonarqube_finding(self, finding): current_status = issue.get("status") logger.debug( - "--> SQ Current status: {}. Current target status: {}".format( - current_status, target_status - ) + f"--> SQ Current status: {current_status}. Current target status: {target_status}" ) transitions = self.get_sonarqube_required_transitions_for( @@ -152,7 +148,7 @@ def update_sonarqube_finding(self, finding): ) if transitions: logger.info( - "Updating finding '{}' in SonarQube".format(finding) + f"Updating finding '{finding}' in SonarQube" ) for transition in transitions: diff --git a/dojo/tools/api_sonarqube/updater_from_source.py b/dojo/tools/api_sonarqube/updater_from_source.py index 137c55dbd7..ee8fdb33d6 100644 --- a/dojo/tools/api_sonarqube/updater_from_source.py +++ b/dojo/tools/api_sonarqube/updater_from_source.py @@ -9,7 +9,7 @@ logger = logging.getLogger(__name__) -class SonarQubeApiUpdaterFromSource(object): +class SonarQubeApiUpdaterFromSource: """ The responsibility of this class is to update the Finding status if current SonarQube issue status doesn't match. @@ -40,9 +40,7 @@ def update(self, finding): current_status = issue.get("resolution") or issue.get("status") current_finding_status = self.get_sonarqube_status_for(finding) logger.debug( - "--> SQ Current status: {}. Finding status: {}".format( - current_status, current_finding_status - ) + f"--> SQ Current status: {current_status}. Finding status: {current_finding_status}" ) if ( @@ -50,9 +48,7 @@ def update(self, finding): and current_finding_status != current_status ): logger.info( - "Original SonarQube issue '{}' has changed. Updating DefectDojo finding '{}'...".format( - sonarqube_issue, finding - ) + f"Original SonarQube issue '{sonarqube_issue}' has changed. Updating DefectDojo finding '{finding}'..." ) self.update_finding_status(finding, current_status) diff --git a/dojo/tools/api_vulners/api_client.py b/dojo/tools/api_vulners/api_client.py index c12996abbc..9441fada34 100644 --- a/dojo/tools/api_vulners/api_client.py +++ b/dojo/tools/api_vulners/api_client.py @@ -16,9 +16,7 @@ def __init__(self, tool_config): self.vulners_api_url = tool_config.url else: raise Exception( - "Vulners.com Authentication type {} not supported".format( - tool_config.authentication_type - ) + f"Vulners.com Authentication type {tool_config.authentication_type} not supported" ) def get_client(self): diff --git a/dojo/tools/api_vulners/importer.py b/dojo/tools/api_vulners/importer.py index fef0d40c66..0017122f97 100644 --- a/dojo/tools/api_vulners/importer.py +++ b/dojo/tools/api_vulners/importer.py @@ -6,7 +6,7 @@ logger = logging.getLogger(__name__) -class VulnersImporter(object): +class VulnersImporter: """ Import from Vulners API """ diff --git a/dojo/tools/api_vulners/parser.py b/dojo/tools/api_vulners/parser.py index deba3c5762..50674e5130 100644 --- a/dojo/tools/api_vulners/parser.py +++ b/dojo/tools/api_vulners/parser.py @@ -17,7 +17,7 @@ } -class ApiVulnersParser(object): +class ApiVulnersParser: """Parser that can load data from Vulners Scanner API""" def get_scan_types(self): diff --git a/dojo/tools/appspider/parser.py b/dojo/tools/appspider/parser.py index 4d3e5eccc7..6b76df3718 100644 --- a/dojo/tools/appspider/parser.py +++ b/dojo/tools/appspider/parser.py @@ -4,7 +4,7 @@ from dojo.models import Endpoint, Finding -class AppSpiderParser(object): +class AppSpiderParser: """Parser for Rapid7 AppSpider reports""" def get_scan_types(self): diff --git a/dojo/tools/aqua/parser.py b/dojo/tools/aqua/parser.py index d29d6128a6..d6ea61edc9 100644 --- a/dojo/tools/aqua/parser.py +++ b/dojo/tools/aqua/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class AquaParser(object): +class AquaParser: def get_scan_types(self): return ["Aqua Scan"] @@ -61,7 +61,7 @@ def get_item(resource, vuln, test): score = vuln.get("aqua_severity") severity = aqua_severity_of(score) used_for_classification = ( - "Aqua security score ({}) used for classification.\n".format(score) + f"Aqua security score ({score}) used for classification.\n" ) severity_justification = vuln.get("aqua_severity_classification") if "nvd_score_v3" in vuln: @@ -70,17 +70,17 @@ def get_item(resource, vuln, test): if "aqua_score" in vuln: score = vuln.get("aqua_score") used_for_classification = ( - "Aqua score ({}) used for classification.\n".format(score) + f"Aqua score ({score}) used for classification.\n" ) elif "vendor_score" in vuln: score = vuln.get("vendor_score") used_for_classification = ( - "Vendor score ({}) used for classification.\n".format(score) + f"Vendor score ({score}) used for classification.\n" ) elif "nvd_score_v3" in vuln: score = vuln.get("nvd_score_v3") used_for_classification = ( - "NVD score v3 ({}) used for classification.\n".format(score) + f"NVD score v3 ({score}) used for classification.\n" ) severity_justification += "\nNVD v3 vectors: {}".format( vuln.get("nvd_vectors_v3") @@ -90,13 +90,13 @@ def get_item(resource, vuln, test): elif "nvd_score" in vuln: score = vuln.get("nvd_score") used_for_classification = ( - "NVD score v2 ({}) used for classification.\n".format(score) + f"NVD score v2 ({score}) used for classification.\n" ) severity_justification += "\nNVD v2 vectors: {}".format( vuln.get("nvd_vectors") ) severity = severity_of(score) - severity_justification += "\n{}".format(used_for_classification) + severity_justification += f"\n{used_for_classification}" finding = Finding( title=vulnerability_id diff --git a/dojo/tools/arachni/parser.py b/dojo/tools/arachni/parser.py index 22e67fe1b8..334b671b01 100755 --- a/dojo/tools/arachni/parser.py +++ b/dojo/tools/arachni/parser.py @@ -7,7 +7,7 @@ from dojo.models import Endpoint, Finding -class ArachniParser(object): +class ArachniParser: """Arachni Web Scanner (http://arachni-scanner.com/wiki) Reports are generated with arachni_reporter tool: diff --git a/dojo/tools/asff/parser.py b/dojo/tools/asff/parser.py index c5831d025b..1f4d96f567 100644 --- a/dojo/tools/asff/parser.py +++ b/dojo/tools/asff/parser.py @@ -13,7 +13,7 @@ } -class AsffParser(object): +class AsffParser: def get_scan_types(self): return ["AWS Security Finding Format (ASFF) Scan"] diff --git a/dojo/tools/auditjs/parser.py b/dojo/tools/auditjs/parser.py index 69031dc16b..6249f1b045 100644 --- a/dojo/tools/auditjs/parser.py +++ b/dojo/tools/auditjs/parser.py @@ -6,7 +6,7 @@ import cvss.parser -class AuditJSParser(object): +class AuditJSParser: """Parser for AuditJS Scan tool""" def get_scan_types(self): diff --git a/dojo/tools/aws_prowler/parser.py b/dojo/tools/aws_prowler/parser.py index b732003930..9659262fb8 100644 --- a/dojo/tools/aws_prowler/parser.py +++ b/dojo/tools/aws_prowler/parser.py @@ -10,7 +10,7 @@ from dojo.models import Finding -class AWSProwlerParser(object): +class AWSProwlerParser: def get_scan_types(self): return ["AWS Prowler Scan"] diff --git a/dojo/tools/aws_prowler_v3/parser.py b/dojo/tools/aws_prowler_v3/parser.py index c36c87ad9b..e0e6910fd7 100644 --- a/dojo/tools/aws_prowler_v3/parser.py +++ b/dojo/tools/aws_prowler_v3/parser.py @@ -7,7 +7,7 @@ from dojo.models import Finding -class AWSProwlerV3Parser(object): +class AWSProwlerV3Parser: SCAN_TYPE = ["AWS Prowler V3"] def get_scan_types(self): diff --git a/dojo/tools/aws_scout2/parser.py b/dojo/tools/aws_scout2/parser.py index 55b6d31afa..8fd45eba17 100644 --- a/dojo/tools/aws_scout2/parser.py +++ b/dojo/tools/aws_scout2/parser.py @@ -6,7 +6,7 @@ from html2text import html2text -class AWSScout2Parser(object): +class AWSScout2Parser: # FIXME bad very bad item_data = "" pdepth = 0 @@ -31,20 +31,17 @@ def get_findings(self, filename, test): test_description = "" aws_account_id = data["aws_account_id"] - test_description = "%s **AWS Account:** %s\n" % ( - test_description, - aws_account_id, - ) + test_description = f"{test_description} **AWS Account:** {aws_account_id}\n" last_run = data["last_run"] - test_description = "%s **Ruleset:** %s\n" % ( + test_description = "{} **Ruleset:** {}\n".format( test_description, last_run["ruleset_name"], ) - test_description = "%s **Ruleset Description:** %s\n" % ( + test_description = "{} **Ruleset Description:** {}\n".format( test_description, last_run["ruleset_about"], ) - test_description = "%s **Command:** %s\n" % ( + test_description = "{} **Command:** {}\n".format( test_description, last_run["cmd"], ) @@ -52,27 +49,24 @@ def get_findings(self, filename, test): # Summary for AWS Services test_description = "%s\n**AWS Services** \n\n" % (test_description) for service, items in list(last_run["summary"].items()): - test_description = "%s\n**%s** \n" % ( - test_description, - service.upper(), - ) - test_description = "%s\n* **Checked Items:** %s\n" % ( + test_description = f"{test_description}\n**{service.upper()}** \n" + test_description = "{}\n* **Checked Items:** {}\n".format( test_description, items["checked_items"], ) - test_description = "%s* **Flagged Items:** %s\n" % ( + test_description = "{}* **Flagged Items:** {}\n".format( test_description, items["flagged_items"], ) - test_description = "%s* **Max Level:** %s\n" % ( + test_description = "{}* **Max Level:** {}\n".format( test_description, items["max_level"], ) - test_description = "%s* **Resource Count:** %s\n" % ( + test_description = "{}* **Resource Count:** {}\n".format( test_description, items["resources_count"], ) - test_description = "%s* **Rules Count:** %s\n\n" % ( + test_description = "{}* **Rules Count:** {}\n\n".format( test_description, items["rules_count"], ) @@ -178,7 +172,7 @@ def tabs(n): self.item_data = ( self.item_data + self.formatview(depth) - + "**%s:** %s\n\n" % (key.title(), src) + + f"**{key.title()}:** {src}\n\n" ) else: self.item_data = ( diff --git a/dojo/tools/awssecurityhub/compliance.py b/dojo/tools/awssecurityhub/compliance.py index 3898442d69..914a196b80 100644 --- a/dojo/tools/awssecurityhub/compliance.py +++ b/dojo/tools/awssecurityhub/compliance.py @@ -2,7 +2,7 @@ from dojo.models import Finding -class Compliance(object): +class Compliance: def get_item(self, finding: dict, test): finding_id = finding.get("Id", "") title = finding.get("Title", "") diff --git a/dojo/tools/awssecurityhub/guardduty.py b/dojo/tools/awssecurityhub/guardduty.py index 3b22498ddc..7a663dcf1d 100644 --- a/dojo/tools/awssecurityhub/guardduty.py +++ b/dojo/tools/awssecurityhub/guardduty.py @@ -2,7 +2,7 @@ from dojo.models import Finding, Endpoint -class GuardDuty(object): +class GuardDuty: def get_item(self, finding: dict, test): finding_id = finding.get("Id", "") title = finding.get("Title", "") diff --git a/dojo/tools/awssecurityhub/inspector.py b/dojo/tools/awssecurityhub/inspector.py index 2c4c79db4e..ce0b7701ad 100644 --- a/dojo/tools/awssecurityhub/inspector.py +++ b/dojo/tools/awssecurityhub/inspector.py @@ -2,7 +2,7 @@ from dojo.models import Finding, Endpoint -class Inspector(object): +class Inspector: def get_item(self, finding: dict, test): finding_id = finding.get("Id", "") title = finding.get("Title", "") diff --git a/dojo/tools/awssecurityhub/parser.py b/dojo/tools/awssecurityhub/parser.py index 7380ece695..d7110c6daf 100644 --- a/dojo/tools/awssecurityhub/parser.py +++ b/dojo/tools/awssecurityhub/parser.py @@ -4,7 +4,7 @@ from dojo.tools.awssecurityhub.compliance import Compliance -class AwsSecurityHubParser(object): +class AwsSecurityHubParser: def get_scan_types(self): return ["AWS Security Hub Scan"] diff --git a/dojo/tools/azure_security_center_recommendations/parser.py b/dojo/tools/azure_security_center_recommendations/parser.py index 9d90519fb2..e2e9faf5eb 100644 --- a/dojo/tools/azure_security_center_recommendations/parser.py +++ b/dojo/tools/azure_security_center_recommendations/parser.py @@ -5,7 +5,7 @@ from dojo.models import Finding -class AzureSecurityCenterRecommendationsParser(object): +class AzureSecurityCenterRecommendationsParser: def get_scan_types(self): return ["Azure Security Center Recommendations Scan"] diff --git a/dojo/tools/bandit/parser.py b/dojo/tools/bandit/parser.py index 18b03967ad..e1f8327756 100644 --- a/dojo/tools/bandit/parser.py +++ b/dojo/tools/bandit/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class BanditParser(object): +class BanditParser: def get_scan_types(self): return ["Bandit Scan"] diff --git a/dojo/tools/bearer_cli/parser.py b/dojo/tools/bearer_cli/parser.py index 9c0126c3a6..856b752c28 100644 --- a/dojo/tools/bearer_cli/parser.py +++ b/dojo/tools/bearer_cli/parser.py @@ -2,7 +2,7 @@ from dojo.models import Finding -class BearerParser(object): +class BearerParser: """ Bearer CLI tool is a SAST scanner for multiple languages """ diff --git a/dojo/tools/blackduck/importer.py b/dojo/tools/blackduck/importer.py index 6cf5eb95d9..8ab2c0d89d 100644 --- a/dojo/tools/blackduck/importer.py +++ b/dojo/tools/blackduck/importer.py @@ -33,7 +33,7 @@ def _process_csvfile(self, report): No file information then. """ security_issues = dict() - with open(str(report), "r") as f: + with open(str(report)) as f: security_issues = self.__partition_by_key(f) project_ids = set(security_issues.keys()) @@ -80,7 +80,7 @@ def _process_project_findings( path = file_entry_dict.get("Path") archive_context = file_entry_dict.get("Archive context") if archive_context: - full_path = "{}{}".format(archive_context, path[1:]) + full_path = f"{archive_context}{path[1:]}" else: full_path = path diff --git a/dojo/tools/blackduck/parser.py b/dojo/tools/blackduck/parser.py index 804bb1bf5a..94c35e9881 100644 --- a/dojo/tools/blackduck/parser.py +++ b/dojo/tools/blackduck/parser.py @@ -4,7 +4,7 @@ from .importer import BlackduckImporter -class BlackduckParser(object): +class BlackduckParser: """ Can import as exported from Blackduck: - from a zip file containing a security.csv and files.csv @@ -45,16 +45,14 @@ def ingest_findings(self, normalized_findings, test): references = self.format_reference(i) dupe_key = hashlib.md5( - "{} | {}".format(title, i.vuln_source).encode("utf-8") + f"{title} | {i.vuln_source}".encode() ).hexdigest() if dupe_key in dupes: finding = dupes[dupe_key] if finding.description: finding.description += ( - "Vulnerability ID: {}\n {}\n".format( - vulnerability_id, i.vuln_source - ) + f"Vulnerability ID: {vulnerability_id}\n {i.vuln_source}\n" ) dupes[dupe_key] = finding else: @@ -87,31 +85,27 @@ def format_title(self, i): else: component_title = i.component_origin_id - return "{} - {}".format(i.vuln_id, component_title) + return f"{i.vuln_id} - {component_title}" def format_description(self, i): - description = "Published on: {}\n\n".format(str(i.published_date)) - description += "Updated on: {}\n\n".format(str(i.updated_date)) - description += "Base score: {}\n\n".format(str(i.base_score)) - description += "Exploitability: {}\n\n".format(str(i.exploitability)) - description += "Description: {}\n".format(i.description) + description = f"Published on: {str(i.published_date)}\n\n" + description += f"Updated on: {str(i.updated_date)}\n\n" + description += f"Base score: {str(i.base_score)}\n\n" + description += f"Exploitability: {str(i.exploitability)}\n\n" + description += f"Description: {i.description}\n" return description def format_mitigation(self, i): - mitigation = "Remediation status: {}\n".format(i.remediation_status) - mitigation += "Remediation target date: {}\n".format( - i.remediation_target_date - ) - mitigation += "Remediation actual date: {}\n".format( - i.remediation_actual_date - ) - mitigation += "Remediation comment: {}\n".format(i.remediation_comment) + mitigation = f"Remediation status: {i.remediation_status}\n" + mitigation += f"Remediation target date: {i.remediation_target_date}\n" + mitigation += f"Remediation actual date: {i.remediation_actual_date}\n" + mitigation += f"Remediation comment: {i.remediation_comment}\n" return mitigation def format_reference(self, i): - reference = "Source: {}\n".format(i.vuln_source) - reference += "URL: {}\n".format(i.url) + reference = f"Source: {i.vuln_source}\n" + reference += f"URL: {i.url}\n" return reference diff --git a/dojo/tools/blackduck_binary_analysis/importer.py b/dojo/tools/blackduck_binary_analysis/importer.py index fcbe4d49a8..3060838d7e 100644 --- a/dojo/tools/blackduck_binary_analysis/importer.py +++ b/dojo/tools/blackduck_binary_analysis/importer.py @@ -27,7 +27,7 @@ def _process_csvfile(self, report, orig_report_name): If passed a CSV file, process. """ vulnerabilities = dict() - with open(str(report), "r") as f: + with open(str(report)) as f: vulnerabilities = self.__partition_by_key(f) sha1_hash_keys = set(vulnerabilities.keys()) diff --git a/dojo/tools/blackduck_binary_analysis/parser.py b/dojo/tools/blackduck_binary_analysis/parser.py index 5504931256..baab6cd935 100644 --- a/dojo/tools/blackduck_binary_analysis/parser.py +++ b/dojo/tools/blackduck_binary_analysis/parser.py @@ -5,7 +5,7 @@ from cvss import CVSS2, CVSS3 -class BlackduckBinaryAnalysisParser(object): +class BlackduckBinaryAnalysisParser: """ Report type(s) from Blackduck Binary Analysis compatible with DefectDojo: - Single CSV file containing vulnerable components @@ -66,7 +66,7 @@ def ingest_findings(self, sorted_findings, test): references = self.format_references(i) unique_finding_key = hashlib.sha256( - "{}".format(file_path + object_sha1 + title).encode("utf-8") + f"{file_path + object_sha1 + title}".encode() ).hexdigest() if unique_finding_key in findings: @@ -105,11 +105,7 @@ def ingest_findings(self, sorted_findings, test): return findings.values() def format_title(self, i): - title = "{}: {} {} Vulnerable".format( - i.object_name, - i.component, - i.version, - ) + title = f"{i.object_name}: {i.component} {i.version} Vulnerable" if i.cve is not None: title += f" to {i.cve}" @@ -117,47 +113,30 @@ def format_title(self, i): return title def format_description(self, i): - description = "CSV Result: {}\n".format(str(i.report_name)) - description += "Vulnerable Component: {}\n".format(str(i.component)) - description += "Vulnerable Component Version in Use: {}\n".format(str(i.version)) - description += "Vulnerable Component Latest Version: {}\n".format( - str(i.latest_version) - ) - description += "Matching Type: {}\n".format(str(i.matching_type)) - description += "Object Name: {}\n".format( - str(i.object_name) - ) - description += "Object Extraction Path: {}\n".format( - str(i.object_full_path) - ) - description += "Object Compilation Date: {}\n".format( - str(i.object_compilation_date) - ) - description += "Object SHA1: {}\n".format(str(i.object_sha1)) - description += "CVE: {}\n".format(str(i.cve)) - description += "CVE Publication Date: {}\n".format( - str(i.cve_publication_date) - ) - description += "Distribution Package: {}\n".format( - str(i.distribution_package) - ) - description += "Missing Exploit Mitigations: {}\n".format( - str(i.missing_exploit_mitigations) - ) - description += "BDSA: {}\n".format(str(i.bdsa)) - description += "Summary:\n{}\n".format(str(i.summary)) - description += "Note Type:\n{}\n".format(str(i.note_type)) - description += "Note Reason:\n{}\n".format(str(i.note_reason)) - description += "Triage Vectors:\n{}\n".format(str(i.triage_vectors)) - description += "Unresolving Triage Vectors:\n{}\n".format(str(i.triage_vectors)) + description = f"CSV Result: {str(i.report_name)}\n" + description += f"Vulnerable Component: {str(i.component)}\n" + description += f"Vulnerable Component Version in Use: {str(i.version)}\n" + description += f"Vulnerable Component Latest Version: {str(i.latest_version)}\n" + description += f"Matching Type: {str(i.matching_type)}\n" + description += f"Object Name: {str(i.object_name)}\n" + description += f"Object Extraction Path: {str(i.object_full_path)}\n" + description += f"Object Compilation Date: {str(i.object_compilation_date)}\n" + description += f"Object SHA1: {str(i.object_sha1)}\n" + description += f"CVE: {str(i.cve)}\n" + description += f"CVE Publication Date: {str(i.cve_publication_date)}\n" + description += f"Distribution Package: {str(i.distribution_package)}\n" + description += f"Missing Exploit Mitigations: {str(i.missing_exploit_mitigations)}\n" + description += f"BDSA: {str(i.bdsa)}\n" + description += f"Summary:\n{str(i.summary)}\n" + description += f"Note Type:\n{str(i.note_type)}\n" + description += f"Note Reason:\n{str(i.note_reason)}\n" + description += f"Triage Vectors:\n{str(i.triage_vectors)}\n" + description += f"Unresolving Triage Vectors:\n{str(i.triage_vectors)}\n" return description def format_mitigation(self, i): - mitigation = "Upgrade {} to latest version: {}.\n".format( - str(i.component), - str(i.latest_version) - ) + mitigation = f"Upgrade {str(i.component)} to latest version: {str(i.latest_version)}.\n" return mitigation @@ -171,7 +150,7 @@ def format_impact(self, i): return impact def format_references(self, i): - references = "BDSA: {}\n".format(str(i.bdsa)) - references += "NIST CVE Details: {}\n".format(str(i.vulnerability_url)) + references = f"BDSA: {str(i.bdsa)}\n" + references += f"NIST CVE Details: {str(i.vulnerability_url)}\n" return references diff --git a/dojo/tools/blackduck_component_risk/importer.py b/dojo/tools/blackduck_component_risk/importer.py index c1c26d8dc4..da1f8c53cc 100644 --- a/dojo/tools/blackduck_component_risk/importer.py +++ b/dojo/tools/blackduck_component_risk/importer.py @@ -7,7 +7,7 @@ logger = logging.getLogger(__name__) -class BlackduckCRImporter(object): +class BlackduckCRImporter: """ Importer for blackduck. V3 is different in that it creates a Finding in defect dojo for each vulnerable component version used in a project, for each license that is diff --git a/dojo/tools/blackduck_component_risk/parser.py b/dojo/tools/blackduck_component_risk/parser.py index 644d525bcd..7f6916962b 100644 --- a/dojo/tools/blackduck_component_risk/parser.py +++ b/dojo/tools/blackduck_component_risk/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class BlackduckComponentRiskParser(object): +class BlackduckComponentRiskParser: """ Can import as exported from Blackduck: - from a zip file containing a security.csv, sources.csv and components.csv diff --git a/dojo/tools/brakeman/parser.py b/dojo/tools/brakeman/parser.py index 77e32603f1..50d130a13f 100644 --- a/dojo/tools/brakeman/parser.py +++ b/dojo/tools/brakeman/parser.py @@ -7,7 +7,7 @@ from dojo.models import Finding -class BrakemanParser(object): +class BrakemanParser: def get_scan_types(self): return ["Brakeman Scan"] diff --git a/dojo/tools/bugcrowd/parser.py b/dojo/tools/bugcrowd/parser.py index 941b55fd69..1414e711a1 100644 --- a/dojo/tools/bugcrowd/parser.py +++ b/dojo/tools/bugcrowd/parser.py @@ -6,7 +6,7 @@ from dojo.models import Endpoint, Finding -class BugCrowdParser(object): +class BugCrowdParser: def get_scan_types(self): return ["BugCrowd Scan"] diff --git a/dojo/tools/bundler_audit/parser.py b/dojo/tools/bundler_audit/parser.py index 8d567af2ec..a098e6e3e6 100644 --- a/dojo/tools/bundler_audit/parser.py +++ b/dojo/tools/bundler_audit/parser.py @@ -6,7 +6,7 @@ from dojo.models import Finding -class BundlerAuditParser(object): +class BundlerAuditParser: def get_scan_types(self): return ["Bundler-Audit Scan"] diff --git a/dojo/tools/burp/parser.py b/dojo/tools/burp/parser.py index bd59959867..82b24118d7 100755 --- a/dojo/tools/burp/parser.py +++ b/dojo/tools/burp/parser.py @@ -8,7 +8,7 @@ logger = logging.getLogger(__name__) -class BurpParser(object): +class BurpParser: """ The objective of this class is to parse an xml file generated by the burp tool. diff --git a/dojo/tools/burp_api/parser.py b/dojo/tools/burp_api/parser.py index 7d62f9b637..01f30faffb 100644 --- a/dojo/tools/burp_api/parser.py +++ b/dojo/tools/burp_api/parser.py @@ -15,7 +15,7 @@ """ -class BurpApiParser(object): +class BurpApiParser: """Parser that can load data from Burp API""" def get_scan_types(self): diff --git a/dojo/tools/burp_dastardly/parser.py b/dojo/tools/burp_dastardly/parser.py index e546c83978..70ee436a81 100755 --- a/dojo/tools/burp_dastardly/parser.py +++ b/dojo/tools/burp_dastardly/parser.py @@ -5,7 +5,7 @@ logger = logging.getLogger(__name__) -class BurpDastardlyParser(object): +class BurpDastardlyParser: def get_scan_types(self): return ["Burp Dastardly Scan"] diff --git a/dojo/tools/burp_enterprise/parser.py b/dojo/tools/burp_enterprise/parser.py index b80e0c54b7..b54603ea99 100644 --- a/dojo/tools/burp_enterprise/parser.py +++ b/dojo/tools/burp_enterprise/parser.py @@ -8,7 +8,7 @@ logger = logging.getLogger(__name__) -class BurpEnterpriseParser(object): +class BurpEnterpriseParser: def get_scan_types(self): return ["Burp Enterprise Scan"] diff --git a/dojo/tools/burp_graphql/parser.py b/dojo/tools/burp_graphql/parser.py index 90d91c640c..34ebfbdbdf 100644 --- a/dojo/tools/burp_graphql/parser.py +++ b/dojo/tools/burp_graphql/parser.py @@ -9,7 +9,7 @@ logger = logging.getLogger(__name__) -class BurpGraphQLParser(object): +class BurpGraphQLParser: def get_scan_types(self): return ["Burp GraphQL API"] diff --git a/dojo/tools/cargo_audit/parser.py b/dojo/tools/cargo_audit/parser.py index fddf3be36a..ccff968cc6 100644 --- a/dojo/tools/cargo_audit/parser.py +++ b/dojo/tools/cargo_audit/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class CargoAuditParser(object): +class CargoAuditParser: """ A class that can be used to parse the cargo audit JSON report file """ diff --git a/dojo/tools/checkmarx/parser.py b/dojo/tools/checkmarx/parser.py index 1c2a7220ce..3f67f97a51 100755 --- a/dojo/tools/checkmarx/parser.py +++ b/dojo/tools/checkmarx/parser.py @@ -11,7 +11,7 @@ logger = logging.getLogger(__name__) -class CheckmarxParser(object): +class CheckmarxParser: def get_scan_types(self): return ["Checkmarx Scan", "Checkmarx Scan detailed"] @@ -68,23 +68,17 @@ def _get_findings_xml(self, filename, test): for result in query.findall("Result"): if categories is not None: - findingdetail = "{}**Category:** {}\n".format( - findingdetail, categories - ) + findingdetail = f"{findingdetail}**Category:** {categories}\n" if language is not None: - findingdetail = "{}**Language:** {}\n".format( - findingdetail, language - ) + findingdetail = f"{findingdetail}**Language:** {language}\n" if language not in language_list: language_list[language] = 1 else: language_list[language] = language_list[language] + 1 if group is not None: - findingdetail = "{}**Group:** {}\n".format( - findingdetail, group - ) + findingdetail = f"{findingdetail}**Group:** {group}\n" if result.get("Status") is not None: findingdetail = "{}**Status:** {}\n".format( @@ -94,9 +88,7 @@ def _get_findings_xml(self, filename, test): deeplink = "[{}]({})".format( result.get("DeepLink"), result.get("DeepLink") ) - findingdetail = "{}**Finding Link:** {}\n".format( - findingdetail, deeplink - ) + findingdetail = f"{findingdetail}**Finding Link:** {deeplink}\n" if self.mode == "detailed": self._process_result_detailed( @@ -154,7 +146,7 @@ def _process_result_file_name_aggregated( title = titleStart false_p = result.get("FalsePositive") sev = result.get("Severity") - aggregateKeys = "{}{}{}".format(cwe, sev, sinkFilename) + aggregateKeys = f"{cwe}{sev}{sinkFilename}" state = result.get("state") active = self.isActive(state) verified = self.isVerified(state) @@ -190,16 +182,8 @@ def _process_result_file_name_aggregated( find = dupes[aggregateKeys] find.nb_occurences = find.nb_occurences + 1 if find.nb_occurences == 2: - find.description = "### 1. {}\n{}".format( - find.title, find.description - ) - find.description = "{}\n\n-----\n### {}. {}\n{}\n{}".format( - find.description, - find.nb_occurences, - title, - findingdetail, - description, - ) + find.description = f"### 1. {find.title}\n{find.description}" + find.description = f"{find.description}\n\n-----\n### {find.nb_occurences}. {title}\n{findingdetail}\n{description}" if queryId not in vuln_ids_from_tool[aggregateKeys]: vuln_ids_from_tool[aggregateKeys].append(queryId) # If at least one of the findings in the aggregate is exploitable, @@ -236,12 +220,8 @@ def get_description_file_name_aggregated(self, query, result): sinkFilename, sinkLineNumber, sinkObject = self.get_pathnode_elements( pathnode ) - description = "Source file: {} (line {})\nSource object: {}".format( - sourceFilename, sourceLineNumber, sourceObject - ) - description = "{}\nSink file: {} (line {})\nSink object: {}".format( - description, sinkFilename, sinkLineNumber, sinkObject - ) + description = f"Source file: {sourceFilename} (line {sourceLineNumber})\nSource object: {sourceObject}" + description = f"{description}\nSink file: {sinkFilename} (line {sinkLineNumber})\nSink object: {sinkObject}" return description, pathnode def _process_result_detailed( @@ -273,7 +253,7 @@ def _process_result_detailed( similarityId = str(path.get("SimilarityId")) path_id = str(path.get("PathId")) pathId = similarityId + path_id - findingdetail = "{}-----\n".format(findingdetail) + findingdetail = f"{findingdetail}-----\n" # Loop over function calls / assignments in the data flow graph for pathnode in path.findall("PathNode"): findingdetail = self.get_description_detailed( @@ -294,9 +274,7 @@ def _process_result_detailed( ) = self.get_pathnode_elements(pathnode) # pathId is the unique id from tool which means that there is # basically no aggregation except real duplicates - aggregateKeys = "{}{}{}{}{}".format( - categories, cwe, name, sinkFilename, pathId - ) + aggregateKeys = f"{categories}{cwe}{name}{sinkFilename}{pathId}" if title and sinkFilename: title = "{} ({})".format(title, sinkFilename.split("/")[-1]) @@ -355,7 +333,7 @@ def get_description_detailed(self, pathnode, findingdetail): codefragment.find("Code").text.strip(), ) - findingdetail = "{}-----\n".format(findingdetail) + findingdetail = f"{findingdetail}-----\n" return findingdetail # Get name, cwe and categories from the global query tag (1 query = 1 type diff --git a/dojo/tools/checkmarx_one/parser.py b/dojo/tools/checkmarx_one/parser.py index 699ac64e42..8769a2220f 100644 --- a/dojo/tools/checkmarx_one/parser.py +++ b/dojo/tools/checkmarx_one/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class CheckmarxOneParser(object): +class CheckmarxOneParser: def get_scan_types(self): return ["Checkmarx One Scan"] diff --git a/dojo/tools/checkmarx_osa/parser.py b/dojo/tools/checkmarx_osa/parser.py index 30ae18e0f4..c61ce2f868 100644 --- a/dojo/tools/checkmarx_osa/parser.py +++ b/dojo/tools/checkmarx_osa/parser.py @@ -6,7 +6,7 @@ logger = logging.getLogger(__name__) -class CheckmarxOsaParser(object): +class CheckmarxOsaParser: def get_scan_types(self): return ["Checkmarx OSA"] @@ -51,7 +51,7 @@ def get_findings(self, filehandle, test): status = item["state"]["name"] vulnerability_id = item.get("cveName", "NC") finding_item = Finding( - title="{0} {1} | {2}".format( + title="{} {} | {}".format( library["name"], library["version"], vulnerability_id ), severity=item["severity"]["name"], diff --git a/dojo/tools/checkov/parser.py b/dojo/tools/checkov/parser.py index c98e94537f..ad4878d389 100644 --- a/dojo/tools/checkov/parser.py +++ b/dojo/tools/checkov/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class CheckovParser(object): +class CheckovParser: def get_scan_types(self): return ["Checkov Scan"] diff --git a/dojo/tools/chefinspect/parser.py b/dojo/tools/chefinspect/parser.py index adf85eb5ea..30feaa586e 100644 --- a/dojo/tools/chefinspect/parser.py +++ b/dojo/tools/chefinspect/parser.py @@ -2,7 +2,7 @@ from dojo.models import Finding -class ChefInspectParser(object): +class ChefInspectParser: def get_scan_types(self): return ["Chef Inspect Log"] diff --git a/dojo/tools/clair/clair_parser.py b/dojo/tools/clair/clair_parser.py index 55fc94ad39..381a1b97ed 100644 --- a/dojo/tools/clair/clair_parser.py +++ b/dojo/tools/clair/clair_parser.py @@ -3,7 +3,7 @@ logger = logging.getLogger(__name__) -class ClairScan(object): +class ClairScan: def get_items_clair(self, tree, test): items = {} for node in tree: diff --git a/dojo/tools/clair/clairklar_parser.py b/dojo/tools/clair/clairklar_parser.py index 5a24dbb05f..263c18872f 100644 --- a/dojo/tools/clair/clairklar_parser.py +++ b/dojo/tools/clair/clairklar_parser.py @@ -3,7 +3,7 @@ logger = logging.getLogger(__name__) -class ClairKlarScan(object): +class ClairKlarScan: def get_items_klar(self, tree, test): items = list() clair_severities = [ diff --git a/dojo/tools/clair/parser.py b/dojo/tools/clair/parser.py index b0701de287..269bbcf5a0 100644 --- a/dojo/tools/clair/parser.py +++ b/dojo/tools/clair/parser.py @@ -3,7 +3,7 @@ from dojo.tools.clair.clairklar_parser import ClairKlarScan -class ClairParser(object): +class ClairParser: def get_scan_types(self): return ["Clair Scan"] diff --git a/dojo/tools/cloudsploit/parser.py b/dojo/tools/cloudsploit/parser.py index 38e518fc6e..b7b7d346e1 100644 --- a/dojo/tools/cloudsploit/parser.py +++ b/dojo/tools/cloudsploit/parser.py @@ -8,7 +8,7 @@ # from urllib.parse import urlparse -class CloudsploitParser(object): +class CloudsploitParser: """ AquaSecurity CloudSploit https://github.com/aquasecurity/cloudsploit """ diff --git a/dojo/tools/cobalt/parser.py b/dojo/tools/cobalt/parser.py index 172982dd67..11592d2ab9 100644 --- a/dojo/tools/cobalt/parser.py +++ b/dojo/tools/cobalt/parser.py @@ -7,7 +7,7 @@ __author__ = "dr3dd589" -class CobaltParser(object): +class CobaltParser: def get_scan_types(self): return ["Cobalt.io Scan"] diff --git a/dojo/tools/codechecker/parser.py b/dojo/tools/codechecker/parser.py index 4866145c02..f73302e7da 100644 --- a/dojo/tools/codechecker/parser.py +++ b/dojo/tools/codechecker/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class CodeCheckerParser(object): +class CodeCheckerParser: def get_scan_types(self): return ["Codechecker Report native"] @@ -48,7 +48,7 @@ def get_item(vuln): if "type" in vuln: vuln_type = vuln.get("type", "None") if vuln_type != "None": - description += "Type: {}\n".format(vuln_type) + description += f"Type: {vuln_type}\n" if "message" in vuln: description += "{}\n".format(vuln["message"]) @@ -57,15 +57,13 @@ def get_item(vuln): file_path = location["path"] if "path" in location else None if file_path: - description += "File path: {}\n".format(file_path) + description += f"File path: {file_path}\n" line = vuln["line"] if "line" in vuln else None column = vuln["column"] if "column" in vuln else None if line is not None and column is not None: - description += "Location in file: line {}, column {}\n".format( - line, column - ) + description += f"Location in file: line {line}, column {column}\n" sast_source_line = line diff --git a/dojo/tools/contrast/parser.py b/dojo/tools/contrast/parser.py index f689b392da..e535260658 100644 --- a/dojo/tools/contrast/parser.py +++ b/dojo/tools/contrast/parser.py @@ -7,7 +7,7 @@ from dojo.models import Endpoint, Finding -class ContrastParser(object): +class ContrastParser: """Contrast Scanner CSV Report""" def get_scan_types(self): @@ -80,7 +80,7 @@ def get_findings(self, filename, test): ) dupe_key = hashlib.sha256( - f"{finding.vuln_id_from_tool}".encode("utf-8") + f"{finding.vuln_id_from_tool}".encode() ).digest() if dupe_key in dupes: diff --git a/dojo/tools/coverity_api/parser.py b/dojo/tools/coverity_api/parser.py index e25f819a8d..38c361e882 100644 --- a/dojo/tools/coverity_api/parser.py +++ b/dojo/tools/coverity_api/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class CoverityApiParser(object): +class CoverityApiParser: """Parser that can load data from Synopsys Coverity API""" def get_scan_types(self): diff --git a/dojo/tools/crashtest_security/parser.py b/dojo/tools/crashtest_security/parser.py index 0ac2b37c0b..efe086ed4f 100755 --- a/dojo/tools/crashtest_security/parser.py +++ b/dojo/tools/crashtest_security/parser.py @@ -8,7 +8,7 @@ from dojo.models import Finding -class CrashtestSecurityJsonParser(object): +class CrashtestSecurityJsonParser: """ The objective of this class is to parse a json file generated by the crashtest security suite. @@ -141,7 +141,7 @@ def get_severity(self, cvss_base_score): return "Critical" -class CrashtestSecurityXmlParser(object): +class CrashtestSecurityXmlParser: """ The objective of this class is to parse an xml file generated by the crashtest security suite. @@ -224,7 +224,7 @@ def get_items(self, tree, test): return items -class CrashtestSecurityParser(object): +class CrashtestSecurityParser: """SSLYze support JSON and XML""" def get_scan_types(self): diff --git a/dojo/tools/cred_scan/parser.py b/dojo/tools/cred_scan/parser.py index 2a2e616f44..9a8ab21e5d 100644 --- a/dojo/tools/cred_scan/parser.py +++ b/dojo/tools/cred_scan/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class CredScanParser(object): +class CredScanParser: """ Credential Scanner (aka CredScan) is a tool developed and maintained by Microsoft to identify credential leaks such as those in source code and diff --git a/dojo/tools/crunch42/parser.py b/dojo/tools/crunch42/parser.py index e1a841e29a..fade8ddb42 100644 --- a/dojo/tools/crunch42/parser.py +++ b/dojo/tools/crunch42/parser.py @@ -2,7 +2,7 @@ from dojo.models import Finding -class Crunch42Parser(object): +class Crunch42Parser: def get_scan_types(self): return ["Crunch42 Scan"] diff --git a/dojo/tools/cyclonedx/helpers.py b/dojo/tools/cyclonedx/helpers.py index ed64843c7d..98a76bfe10 100644 --- a/dojo/tools/cyclonedx/helpers.py +++ b/dojo/tools/cyclonedx/helpers.py @@ -3,7 +3,7 @@ LOGGER = logging.getLogger(__name__) -class Cyclonedxhelper(object): +class Cyclonedxhelper: def _get_cvssv3(self, raw_vector): if raw_vector is None or "" == raw_vector: return None diff --git a/dojo/tools/cyclonedx/json_parser.py b/dojo/tools/cyclonedx/json_parser.py index 1c4b0490b4..9ee31275fc 100644 --- a/dojo/tools/cyclonedx/json_parser.py +++ b/dojo/tools/cyclonedx/json_parser.py @@ -6,7 +6,7 @@ LOGGER = logging.getLogger(__name__) -class CycloneDXJSONParser(object): +class CycloneDXJSONParser: def _get_findings_json(self, file, test): """Load a CycloneDX file in JSON format""" data = json.load(file) @@ -126,9 +126,7 @@ def _get_findings_json(self, file, test): if detail: finding.mitigation = ( finding.mitigation - + "\n**This vulnerability is mitigated and/or suppressed:** {}\n".format( - detail - ) + + f"\n**This vulnerability is mitigated and/or suppressed:** {detail}\n" ) findings.append(finding) return findings diff --git a/dojo/tools/cyclonedx/parser.py b/dojo/tools/cyclonedx/parser.py index dfb01b8a38..8fe80a5113 100644 --- a/dojo/tools/cyclonedx/parser.py +++ b/dojo/tools/cyclonedx/parser.py @@ -2,7 +2,7 @@ from dojo.tools.cyclonedx.xml_parser import CycloneDXXMLParser -class CycloneDXParser(object): +class CycloneDXParser: """CycloneDX is a lightweight software bill of materials (SBOM) standard designed for use in application security contexts and supply chain component analysis. https://www.cyclonedx.org/ diff --git a/dojo/tools/cyclonedx/xml_parser.py b/dojo/tools/cyclonedx/xml_parser.py index 5e0bda3985..517dbc5478 100644 --- a/dojo/tools/cyclonedx/xml_parser.py +++ b/dojo/tools/cyclonedx/xml_parser.py @@ -7,7 +7,7 @@ LOGGER = logging.getLogger(__name__) -class CycloneDXXMLParser(object): +class CycloneDXXMLParser: def _get_findings_xml(self, file, test): nscan = ElementTree.parse(file) root = nscan.getroot() @@ -294,9 +294,7 @@ def _manage_vulnerability_xml( if detail: finding.mitigation = ( finding.mitigation - + "\n**This vulnerability is mitigated and/or suppressed:** {}\n".format( - detail - ) + + f"\n**This vulnerability is mitigated and/or suppressed:** {detail}\n" ) findings.append(finding) return findings diff --git a/dojo/tools/dawnscanner/parser.py b/dojo/tools/dawnscanner/parser.py index e191d2da06..98b91d36ad 100644 --- a/dojo/tools/dawnscanner/parser.py +++ b/dojo/tools/dawnscanner/parser.py @@ -5,7 +5,7 @@ from dojo.models import Finding -class DawnScannerParser(object): +class DawnScannerParser: CVE_REGEX = re.compile(r"CVE-\d{4}-\d{4,7}") def get_scan_types(self): diff --git a/dojo/tools/dependency_check/parser.py b/dojo/tools/dependency_check/parser.py index 89b634d13c..01ff28e2fd 100644 --- a/dojo/tools/dependency_check/parser.py +++ b/dojo/tools/dependency_check/parser.py @@ -13,7 +13,7 @@ logger = logging.getLogger(__name__) -class DependencyCheckParser(object): +class DependencyCheckParser: SEVERITY_MAPPING = { "info": "Info", "low": "Low", @@ -232,9 +232,7 @@ def get_finding_from_vulnerability( if component_name is None: logger.warning( - "component_name was None for File: {}, using dependency file name instead.".format( - dependency_filename - ) + f"component_name was None for File: {dependency_filename}, using dependency file name instead." ) component_name = dependency_filename @@ -296,18 +294,14 @@ def get_finding_from_vulnerability( if related_dependency is not None: tags.append("related") - if vulnerability.tag == "{}suppressedVulnerability".format(namespace): + if vulnerability.tag == f"{namespace}suppressedVulnerability": if notes is None: notes = "Document on why we are suppressing this vulnerability is missing!" tags.append("no_suppression_document") - mitigation = "**This vulnerability is mitigated and/or suppressed:** {}\n".format( - notes - ) + mitigation = f"**This vulnerability is mitigated and/or suppressed:** {notes}\n" mitigation = ( mitigation - + "Update {}:{} to at least the version recommended in the description".format( - component_name, component_version - ) + + f"Update {component_name}:{component_version} to at least the version recommended in the description" ) mitigated = datetime.utcnow() is_Mitigated = True @@ -315,9 +309,7 @@ def get_finding_from_vulnerability( tags.append("suppressed") else: - mitigation = "Update {}:{} to at least the version recommended in the description".format( - component_name, component_version - ) + mitigation = f"Update {component_name}:{component_version} to at least the version recommended in the description" description += "\n**Filepath:** " + str(dependency_filepath) active = True diff --git a/dojo/tools/dependency_track/parser.py b/dojo/tools/dependency_track/parser.py index 965e3e3236..c4e3dad351 100644 --- a/dojo/tools/dependency_track/parser.py +++ b/dojo/tools/dependency_track/parser.py @@ -6,7 +6,7 @@ logger = logging.getLogger(__name__) -class DependencyTrackParser(object): +class DependencyTrackParser: """ A class that can be used to parse the JSON Finding Packaging Format (FPF) export from OWASP Dependency Track. @@ -138,8 +138,7 @@ def _convert_dependency_track_finding_to_dojo_finding(self, dependency_track_fin else: version_description = '' - title = "{component_name}:{version_description} affected by: {vuln_id} ({source})"\ - .format(vuln_id=vuln_id, source=source, version_description=version_description, component_name=component_name) + title = f"{component_name}:{version_description} affected by: {vuln_id} ({source})" # We should collect all the vulnerability ids, the FPF format can add additional IDs as aliases # we add these aliases in the vulnerability_id list making sure duplicate findings get correctly deduplicated @@ -168,17 +167,16 @@ def _convert_dependency_track_finding_to_dojo_finding(self, dependency_track_fin # Build the description of the Dojo finding # We already know (from above) that the version information is not always present if component_version is not None: - component_description = "Version {component_version} of the {component_name} component".format(component_version=component_version, component_name=component_name) + component_description = f"Version {component_version} of the {component_name} component" else: - component_description = "The {component_name} component".format(component_name=component_name) + component_description = f"The {component_name} component" vulnerability_description = "You are using a component with a known vulnerability. " \ - "{component_description} is affected by the vulnerability with an id of {vuln_id} as " \ - "identified by {source}." \ - .format(component_description=component_description, vuln_id=vuln_id, source=source) + f"{component_description} is affected by the vulnerability with an id of {vuln_id} as " \ + f"identified by {source}." # Append purl info if it is present if 'purl' in dependency_track_finding['component'] and dependency_track_finding['component']['purl'] is not None: component_purl = dependency_track_finding['component']['purl'] - vulnerability_description = vulnerability_description + "\nThe purl of the affected component is: {purl}.".format(purl=component_purl) + vulnerability_description = vulnerability_description + f"\nThe purl of the affected component is: {component_purl}." # there is no file_path in the report, but defect dojo needs it otherwise it skips deduplication: # see https://github.com/DefectDojo/django-DefectDojo/issues/3647 # might be no longer needed in the future, and is not needed if people use the default diff --git a/dojo/tools/detect_secrets/parser.py b/dojo/tools/detect_secrets/parser.py index 0da274ba9f..3e450a02a1 100644 --- a/dojo/tools/detect_secrets/parser.py +++ b/dojo/tools/detect_secrets/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class DetectSecretsParser(object): +class DetectSecretsParser: """ A class that can be used to parse the detect-secrets JSON report file """ diff --git a/dojo/tools/dockerbench/parser.py b/dojo/tools/dockerbench/parser.py index 870c3bc31b..a00db912d2 100644 --- a/dojo/tools/dockerbench/parser.py +++ b/dojo/tools/dockerbench/parser.py @@ -4,7 +4,7 @@ from datetime import datetime -class DockerBenchParser(object): +class DockerBenchParser: def get_scan_types(self): return ["docker-bench-security Scan"] @@ -90,7 +90,7 @@ def get_item(vuln, test, test_start, test_end, description): description += unique_id_from_tool if reason: description += "\n" - description += "desc: {}\n".format(reason) + description += f"desc: {reason}\n" if vuln.get("details"): description += "\n" description += vuln["details"] diff --git a/dojo/tools/dockle/parser.py b/dojo/tools/dockle/parser.py index 5c07472bed..e2d0be9256 100644 --- a/dojo/tools/dockle/parser.py +++ b/dojo/tools/dockle/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class DockleParser(object): +class DockleParser: """ A class that can be used to parse the Dockle JSON report files """ diff --git a/dojo/tools/drheader/parser.py b/dojo/tools/drheader/parser.py index eeeed1e5e1..158da541bd 100644 --- a/dojo/tools/drheader/parser.py +++ b/dojo/tools/drheader/parser.py @@ -3,7 +3,7 @@ from dojo.models import Endpoint, Finding -class DrHeaderParser(object): +class DrHeaderParser: def get_scan_types(self): return ["DrHeader JSON Importer"] diff --git a/dojo/tools/eslint/parser.py b/dojo/tools/eslint/parser.py index c3e2167b8c..df8628f533 100644 --- a/dojo/tools/eslint/parser.py +++ b/dojo/tools/eslint/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class ESLintParser(object): +class ESLintParser: def get_scan_types(self): return ["ESLint Scan"] @@ -37,7 +37,7 @@ def get_findings(self, filename, test): for message in item["messages"]: if message["message"] is None: - title = str("Finding Not defined") + title = "Finding Not defined" else: title = str(message["message"]) diff --git a/dojo/tools/fortify/fpr_parser.py b/dojo/tools/fortify/fpr_parser.py index de745d236d..8110a23cb9 100644 --- a/dojo/tools/fortify/fpr_parser.py +++ b/dojo/tools/fortify/fpr_parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class FortifyFPRParser(object): +class FortifyFPRParser: def parse_fpr(self, filename, test): if str(filename.__class__) == "": input_zip = zipfile.ZipFile(filename.name, 'r') diff --git a/dojo/tools/fortify/parser.py b/dojo/tools/fortify/parser.py index 7ef6a07f85..3eef4071d5 100644 --- a/dojo/tools/fortify/parser.py +++ b/dojo/tools/fortify/parser.py @@ -2,7 +2,7 @@ from dojo.tools.fortify.fpr_parser import FortifyFPRParser -class FortifyParser(object): +class FortifyParser: def get_scan_types(self): return ["Fortify Scan"] diff --git a/dojo/tools/fortify/xml_parser.py b/dojo/tools/fortify/xml_parser.py index 80b54f9f85..a6f1d11d4a 100644 --- a/dojo/tools/fortify/xml_parser.py +++ b/dojo/tools/fortify/xml_parser.py @@ -2,7 +2,7 @@ from dojo.models import Finding -class FortifyXMLParser(object): +class FortifyXMLParser: def parse_xml(self, filename, test): fortify_scan = ElementTree.parse(filename) root = fortify_scan.getroot() @@ -120,7 +120,7 @@ def format_description(self, issue, meta_info) -> str: ) ) if explanation: - desc += "##Explanation:\n {}".format(explanation) + desc += f"##Explanation:\n {explanation}" return desc def format_title(self, category, filename, line_no): @@ -131,7 +131,7 @@ def format_title(self, category, filename, line_no): :param line_no: Line number of offending line :return: str """ - return "{} - {}: {}".format(category, filename, line_no) + return f"{category} - {filename}: {line_no}" def format_mitigation(self, issue, meta_info) -> str: """ @@ -144,8 +144,8 @@ def format_mitigation(self, issue, meta_info) -> str: mitigation = "" recommendation = meta_info[issue["Category"]].get("Recommendations") if recommendation: - mitigation += "###Recommendation:\n {}\n".format(recommendation) + mitigation += f"###Recommendation:\n {recommendation}\n" tips = meta_info[issue["Category"]].get("Tips") if tips: - mitigation += "###Tips:\n {}".format(tips) + mitigation += f"###Tips:\n {tips}" return mitigation diff --git a/dojo/tools/gcloud_artifact_scan/parser.py b/dojo/tools/gcloud_artifact_scan/parser.py index 9785d12d67..833d0b21e4 100644 --- a/dojo/tools/gcloud_artifact_scan/parser.py +++ b/dojo/tools/gcloud_artifact_scan/parser.py @@ -2,7 +2,7 @@ from dojo.models import Finding -class GCloudArtifactScanParser(object): +class GCloudArtifactScanParser: def get_scan_types(self): return ["Google Cloud Artifact Vulnerability Scan"] diff --git a/dojo/tools/generic/parser.py b/dojo/tools/generic/parser.py index 03144e71d0..07d1d5144d 100644 --- a/dojo/tools/generic/parser.py +++ b/dojo/tools/generic/parser.py @@ -9,7 +9,7 @@ from dojo.tools.parser_test import ParserTest -class GenericParser(object): +class GenericParser: ID = "Generic Findings Import" def get_scan_types(self): @@ -232,7 +232,7 @@ def _get_findings_csv(self, filename): # manage internal de-duplication key = hashlib.sha256( - f"{finding.severity}|{finding.title}|{finding.description}".encode("utf-8") + f"{finding.severity}|{finding.title}|{finding.description}".encode() ).hexdigest() if key in dupes: find = dupes[key] diff --git a/dojo/tools/ggshield/parser.py b/dojo/tools/ggshield/parser.py index 3d6373c87e..a5b362f00b 100755 --- a/dojo/tools/ggshield/parser.py +++ b/dojo/tools/ggshield/parser.py @@ -4,7 +4,7 @@ from dateutil import parser -class GgshieldParser(object): +class GgshieldParser: """ A class that can be used to parse the Gitleaks JSON report files """ diff --git a/dojo/tools/github_vulnerability/parser.py b/dojo/tools/github_vulnerability/parser.py index ac44d815e8..da848f1b7c 100644 --- a/dojo/tools/github_vulnerability/parser.py +++ b/dojo/tools/github_vulnerability/parser.py @@ -5,7 +5,7 @@ from dojo.models import Finding -class GithubVulnerabilityParser(object): +class GithubVulnerabilityParser: def get_scan_types(self): return ["Github Vulnerability Scan"] @@ -42,7 +42,7 @@ def get_findings(self, filename, test): + "/security/dependabot/{}".format(alert["number"]) ) description = ( - "[{}]({})\n".format(dependabot_url, dependabot_url) + f"[{dependabot_url}]({dependabot_url})\n" + description ) finding = Finding( diff --git a/dojo/tools/gitlab_api_fuzzing/parser.py b/dojo/tools/gitlab_api_fuzzing/parser.py index 270abdc053..a0992b0e51 100644 --- a/dojo/tools/gitlab_api_fuzzing/parser.py +++ b/dojo/tools/gitlab_api_fuzzing/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class GitlabAPIFuzzingParser(object): +class GitlabAPIFuzzingParser: """ GitLab API Fuzzing Report diff --git a/dojo/tools/gitlab_container_scan/parser.py b/dojo/tools/gitlab_container_scan/parser.py index 0912d2fd2e..65ceb27f28 100644 --- a/dojo/tools/gitlab_container_scan/parser.py +++ b/dojo/tools/gitlab_container_scan/parser.py @@ -5,7 +5,7 @@ from dojo.models import Finding -class GitlabContainerScanParser(object): +class GitlabContainerScanParser: """ GitLab's container scanning report See more: https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/container-scanning-report-format.json diff --git a/dojo/tools/gitlab_dast/parser.py b/dojo/tools/gitlab_dast/parser.py index 5627a0a06e..0c6eab1dbe 100644 --- a/dojo/tools/gitlab_dast/parser.py +++ b/dojo/tools/gitlab_dast/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding, Endpoint -class GitlabDastParser(object): +class GitlabDastParser: """ Import GitLab DAST Report in JSON format """ diff --git a/dojo/tools/gitlab_dep_scan/parser.py b/dojo/tools/gitlab_dep_scan/parser.py index 16692e8819..3928d82d1d 100644 --- a/dojo/tools/gitlab_dep_scan/parser.py +++ b/dojo/tools/gitlab_dep_scan/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class GitlabDepScanParser(object): +class GitlabDepScanParser: def get_scan_types(self): return ["GitLab Dependency Scanning Report"] diff --git a/dojo/tools/gitlab_sast/parser.py b/dojo/tools/gitlab_sast/parser.py index 91fec1e145..b00a04a5e6 100644 --- a/dojo/tools/gitlab_sast/parser.py +++ b/dojo/tools/gitlab_sast/parser.py @@ -4,7 +4,7 @@ from dojo.tools.parser_test import ParserTest -class GitlabSastParser(object): +class GitlabSastParser: def get_scan_types(self): return ["GitLab SAST Report"] diff --git a/dojo/tools/gitlab_secret_detection_report/parser.py b/dojo/tools/gitlab_secret_detection_report/parser.py index f6e89adb84..ce72f04bf9 100644 --- a/dojo/tools/gitlab_secret_detection_report/parser.py +++ b/dojo/tools/gitlab_secret_detection_report/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class GitlabSecretDetectionReportParser(object): +class GitlabSecretDetectionReportParser: """ GitLab's secret detection report See more: https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/secret-detection-report-format.json diff --git a/dojo/tools/gitleaks/parser.py b/dojo/tools/gitleaks/parser.py index 513d43dd75..ae53b19227 100644 --- a/dojo/tools/gitleaks/parser.py +++ b/dojo/tools/gitleaks/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class GitleaksParser(object): +class GitleaksParser: """ A class that can be used to parse the Gitleaks JSON report files """ diff --git a/dojo/tools/gosec/parser.py b/dojo/tools/gosec/parser.py index 4d3824913b..3efcbd9385 100644 --- a/dojo/tools/gosec/parser.py +++ b/dojo/tools/gosec/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class GosecParser(object): +class GosecParser: def get_scan_types(self): return ["Gosec Scanner"] @@ -33,11 +33,9 @@ def get_findings(self, filename, test): title = item["details"] + " - rule " + item["rule_id"] # Finding details information - findingdetail += "Filename: {}\n\n".format(filename) - findingdetail += "Line number: {}\n\n".format(str(line)) - findingdetail += "Issue Confidence: {}\n\n".format( - scanner_confidence - ) + findingdetail += f"Filename: {filename}\n\n" + findingdetail += f"Line number: {str(line)}\n\n" + findingdetail += f"Issue Confidence: {scanner_confidence}\n\n" findingdetail += "Code:\n\n" findingdetail += "```{}```".format(item["code"]) diff --git a/dojo/tools/h1/parser.py b/dojo/tools/h1/parser.py index 8d3409799f..48c367684f 100644 --- a/dojo/tools/h1/parser.py +++ b/dojo/tools/h1/parser.py @@ -7,7 +7,7 @@ __author__ = "Kirill Gotsman" -class H1Parser(object): +class H1Parser: """ A class that can be used to parse the Get All Reports JSON export from HackerOne API. """ @@ -53,9 +53,7 @@ def get_findings(self, file, test): issue_tracker_url = content["attributes"][ "issue_tracker_reference_url" ] - references = "[{}]({})\n".format( - issue_tracker_id, issue_tracker_url - ) + references = f"[{issue_tracker_id}]({issue_tracker_url})\n" except Exception: references = "" @@ -72,7 +70,7 @@ def get_findings(self, file, test): ref_link = "https://hackerone.com/reports/{}".format( content.get("id") ) - references += "[{}]({})".format(ref_link, ref_link) + references += f"[{ref_link}]({ref_link})" # Set active state of the Dojo finding if content["attributes"]["state"] in ["triaged", "new"]: @@ -132,7 +130,7 @@ def build_description(self, content): # Build the description of the Dojo finding description = "#" + content["attributes"]["title"] - description += "\nSubmitted: {}\nBy: {}\n".format(date, reporter) + description += f"\nSubmitted: {date}\nBy: {reporter}\n" # Add triaged date if triaged_date is not None: @@ -140,14 +138,14 @@ def build_description(self, content): datetime.strptime(triaged_date, "%Y-%m-%dT%H:%M:%S.%fZ"), "%Y-%m-%d", ) - description += "Triaged: {}\n".format(triaged_date) + description += f"Triaged: {triaged_date}\n" # Try to grab CVSS try: cvss = content["relationships"]["severity"]["data"]["attributes"][ "score" ] - description += "CVSS: {}\n".format(cvss) + description += f"CVSS: {cvss}\n" except Exception: pass @@ -164,9 +162,7 @@ def build_description(self, content): weakness_desc = content["relationships"]["weakness"]["data"][ "attributes" ]["description"] - description += "\n##Weakness: {}\n{}".format( - weakness_title, weakness_desc - ) + description += f"\n##Weakness: {weakness_title}\n{weakness_desc}" except Exception: pass diff --git a/dojo/tools/hadolint/parser.py b/dojo/tools/hadolint/parser.py index 9e907160fc..4624dcbf99 100644 --- a/dojo/tools/hadolint/parser.py +++ b/dojo/tools/hadolint/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class HadolintParser(object): +class HadolintParser: def get_scan_types(self): return ["Hadolint Dockerfile check"] diff --git a/dojo/tools/harbor_vulnerability/parser.py b/dojo/tools/harbor_vulnerability/parser.py index 7f5d2b8898..5d7db07ed1 100644 --- a/dojo/tools/harbor_vulnerability/parser.py +++ b/dojo/tools/harbor_vulnerability/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class HarborVulnerabilityParser(object): +class HarborVulnerabilityParser: """ Read JSON data from Harbor compatible format and import it to DefectDojo """ diff --git a/dojo/tools/hcl_appscan/parser.py b/dojo/tools/hcl_appscan/parser.py index 8f559acc53..b29cc465d7 100755 --- a/dojo/tools/hcl_appscan/parser.py +++ b/dojo/tools/hcl_appscan/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding, Endpoint -class HCLAppScanParser(object): +class HCLAppScanParser: def get_scan_types(self): return ["HCLAppScan XML"] diff --git a/dojo/tools/horusec/parser.py b/dojo/tools/horusec/parser.py index 8eeecc1dbc..a64fa2f091 100644 --- a/dojo/tools/horusec/parser.py +++ b/dojo/tools/horusec/parser.py @@ -6,7 +6,7 @@ from dojo.tools.parser_test import ParserTest -class HorusecParser(object): +class HorusecParser: """Horusec (https://github.com/ZupIT/horusec)""" ID = "Horusec" diff --git a/dojo/tools/humble/parser.py b/dojo/tools/humble/parser.py index 68ec2741bd..c99619dcfd 100644 --- a/dojo/tools/humble/parser.py +++ b/dojo/tools/humble/parser.py @@ -2,7 +2,7 @@ from dojo.models import Finding, Endpoint -class HumbleParser(object): +class HumbleParser: """Humble (https://github.com/rfc-st/humble)""" def get_scan_types(self): diff --git a/dojo/tools/huskyci/parser.py b/dojo/tools/huskyci/parser.py index 455204bd52..be0caeeb3a 100644 --- a/dojo/tools/huskyci/parser.py +++ b/dojo/tools/huskyci/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class HuskyCIParser(object): +class HuskyCIParser: """ Read JSON data from huskyCI compatible format and import it to DefectDojo """ diff --git a/dojo/tools/hydra/parser.py b/dojo/tools/hydra/parser.py index f24160ac7f..3abb2b1c1b 100644 --- a/dojo/tools/hydra/parser.py +++ b/dojo/tools/hydra/parser.py @@ -20,7 +20,7 @@ def __init__(self, generator): self.server = generator.get("server") -class HydraParser(object): +class HydraParser: """ Weak password findings from THC-Hydra (https://github.com/vanhauser-thc/thc-hydra) """ diff --git a/dojo/tools/ibm_app/parser.py b/dojo/tools/ibm_app/parser.py index 8e4147a228..f4389a9c5b 100644 --- a/dojo/tools/ibm_app/parser.py +++ b/dojo/tools/ibm_app/parser.py @@ -8,7 +8,7 @@ LOGGER = logging.getLogger(__name__) -class IbmAppParser(object): +class IbmAppParser: def get_scan_types(self): return ["IBM AppScan DAST"] diff --git a/dojo/tools/immuniweb/parser.py b/dojo/tools/immuniweb/parser.py index 6265d1f620..9b7af871d9 100644 --- a/dojo/tools/immuniweb/parser.py +++ b/dojo/tools/immuniweb/parser.py @@ -7,7 +7,7 @@ __author__ = "properam" -class ImmuniwebParser(object): +class ImmuniwebParser: def get_scan_types(self): return ["Immuniweb Scan"] diff --git a/dojo/tools/intsights/parser.py b/dojo/tools/intsights/parser.py index 2c97225fae..7b69598c80 100644 --- a/dojo/tools/intsights/parser.py +++ b/dojo/tools/intsights/parser.py @@ -7,7 +7,7 @@ from dojo.models import Finding -class IntSightsParser(object): +class IntSightsParser: """ IntSights Threat Intelligence Report """ diff --git a/dojo/tools/jfrog_xray_api_summary_artifact/parser.py b/dojo/tools/jfrog_xray_api_summary_artifact/parser.py index f62d353229..09a6066d04 100644 --- a/dojo/tools/jfrog_xray_api_summary_artifact/parser.py +++ b/dojo/tools/jfrog_xray_api_summary_artifact/parser.py @@ -8,7 +8,7 @@ from dojo.models import Finding -class JFrogXrayApiSummaryArtifactParser(object): +class JFrogXrayApiSummaryArtifactParser: # This function return a list of all the scan_type supported by your parser def get_scan_types(self): return ["JFrog Xray API Summary Artifact Scan"] diff --git a/dojo/tools/jfrog_xray_on_demand_binary_scan/parser.py b/dojo/tools/jfrog_xray_on_demand_binary_scan/parser.py index b6901c289c..0839ef5acf 100644 --- a/dojo/tools/jfrog_xray_on_demand_binary_scan/parser.py +++ b/dojo/tools/jfrog_xray_on_demand_binary_scan/parser.py @@ -6,7 +6,7 @@ from dojo.models import Finding -class JFrogXrayOnDemandBinaryScanParser(object): +class JFrogXrayOnDemandBinaryScanParser: """jfrog_xray_scan JSON reports""" def get_scan_types(self): diff --git a/dojo/tools/jfrog_xray_unified/parser.py b/dojo/tools/jfrog_xray_unified/parser.py index 23e739101c..c7e48897a2 100644 --- a/dojo/tools/jfrog_xray_unified/parser.py +++ b/dojo/tools/jfrog_xray_unified/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class JFrogXrayUnifiedParser(object): +class JFrogXrayUnifiedParser: """JFrog Xray JSON reports""" def get_scan_types(self): @@ -131,9 +131,7 @@ def get_item(vulnerability, test): component_name=component_name, component_version=component_version, file_path=vulnerability["path"], - severity_justification="CVSS v3 base score: {}\nCVSS v2 base score: {}".format( - cvss_v3, cvss_v2 - ), + severity_justification=f"CVSS v3 base score: {cvss_v3}\nCVSS v2 base score: {cvss_v2}", static_finding=True, dynamic_finding=False, references=references, diff --git a/dojo/tools/jfrogxray/parser.py b/dojo/tools/jfrogxray/parser.py index 9f45abd6be..5017bdb7d3 100644 --- a/dojo/tools/jfrogxray/parser.py +++ b/dojo/tools/jfrogxray/parser.py @@ -6,7 +6,7 @@ from dojo.models import Finding -class JFrogXrayParser(object): +class JFrogXrayParser: """JFrog Xray JSON reports""" def get_scan_types(self): diff --git a/dojo/tools/kics/parser.py b/dojo/tools/kics/parser.py index 3f5a279762..7974db2ba5 100644 --- a/dojo/tools/kics/parser.py +++ b/dojo/tools/kics/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class KICSParser(object): +class KICSParser: """ A class that can be used to parse the KICS JSON report file """ diff --git a/dojo/tools/kiuwan/parser.py b/dojo/tools/kiuwan/parser.py index a79c828ecd..98ba9b2952 100644 --- a/dojo/tools/kiuwan/parser.py +++ b/dojo/tools/kiuwan/parser.py @@ -25,7 +25,7 @@ def eval_column(self, column_value): self.severity = "Info" -class KiuwanParser(object): +class KiuwanParser: def get_scan_types(self): return ["Kiuwan Scan"] diff --git a/dojo/tools/kubeaudit/parser.py b/dojo/tools/kubeaudit/parser.py index 63a998f8ac..4b37d6d8ee 100644 --- a/dojo/tools/kubeaudit/parser.py +++ b/dojo/tools/kubeaudit/parser.py @@ -2,7 +2,7 @@ from dojo.models import Finding -class KubeAuditParser(object): +class KubeAuditParser: def get_scan_types(self): return ["Kubeaudit Scan"] diff --git a/dojo/tools/kubebench/parser.py b/dojo/tools/kubebench/parser.py index a54bcaf480..f288da9542 100644 --- a/dojo/tools/kubebench/parser.py +++ b/dojo/tools/kubebench/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class KubeBenchParser(object): +class KubeBenchParser: def get_scan_types(self): return ["kube-bench Scan"] diff --git a/dojo/tools/kubehunter/parser.py b/dojo/tools/kubehunter/parser.py index 95cc6cddb5..c7688033dd 100644 --- a/dojo/tools/kubehunter/parser.py +++ b/dojo/tools/kubehunter/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class KubeHunterParser(object): +class KubeHunterParser: """ kube-hunter hunts for security weaknesses in Kubernetes clusters. The tool was developed to increase awareness and visibility for security issues in Kubernetes environments. """ diff --git a/dojo/tools/kubescape/parser.py b/dojo/tools/kubescape/parser.py index 716244a323..8f4c790a86 100644 --- a/dojo/tools/kubescape/parser.py +++ b/dojo/tools/kubescape/parser.py @@ -2,7 +2,7 @@ from dojo.models import Finding -class KubescapeParser(object): +class KubescapeParser: def get_scan_types(self): return ["Kubescape JSON Importer"] diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index c6d5934088..965a725d32 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -9,7 +9,7 @@ logger = logging.getLogger(__name__) -class MendParser(object): +class MendParser: def get_scan_types(self): return ["Mend Scan"] diff --git a/dojo/tools/meterian/parser.py b/dojo/tools/meterian/parser.py index e47cb46901..1fee4cbc86 100644 --- a/dojo/tools/meterian/parser.py +++ b/dojo/tools/meterian/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class MeterianParser(object): +class MeterianParser: def get_scan_types(self): return ["Meterian Scan"] diff --git a/dojo/tools/microfocus_webinspect/parser.py b/dojo/tools/microfocus_webinspect/parser.py index 65032214c2..c6c5ccd7a4 100644 --- a/dojo/tools/microfocus_webinspect/parser.py +++ b/dojo/tools/microfocus_webinspect/parser.py @@ -7,7 +7,7 @@ from dojo.models import Endpoint, Finding -class MicrofocusWebinspectParser(object): +class MicrofocusWebinspectParser: """Micro Focus Webinspect XML report parser""" def get_scan_types(self): @@ -82,7 +82,7 @@ def get_findings(self, file, test): # make dupe hash key dupe_key = hashlib.sha256( - f"{finding.description}|{finding.title}|{finding.severity}".encode("utf-8") + f"{finding.description}|{finding.title}|{finding.severity}".encode() ).hexdigest() # check if dupes are present. if dupe_key in dupes: diff --git a/dojo/tools/mobsf/parser.py b/dojo/tools/mobsf/parser.py index 7c11a24239..02e43944f3 100644 --- a/dojo/tools/mobsf/parser.py +++ b/dojo/tools/mobsf/parser.py @@ -7,7 +7,7 @@ from dojo.models import Finding -class MobSFParser(object): +class MobSFParser: def get_scan_types(self): return ["MobSF Scan"] @@ -30,45 +30,45 @@ def get_findings(self, filename, test): if "name" in data: test_description = "**Info:**\n" if "packagename" in data: - test_description = "%s **Package Name:** %s\n" % (test_description, data["packagename"]) + test_description = "{} **Package Name:** {}\n".format(test_description, data["packagename"]) if "mainactivity" in data: - test_description = "%s **Main Activity:** %s\n" % (test_description, data["mainactivity"]) + test_description = "{} **Main Activity:** {}\n".format(test_description, data["mainactivity"]) if "pltfm" in data: - test_description = "%s **Platform:** %s\n" % (test_description, data["pltfm"]) + test_description = "{} **Platform:** {}\n".format(test_description, data["pltfm"]) if "sdk" in data: - test_description = "%s **SDK:** %s\n" % (test_description, data["sdk"]) + test_description = "{} **SDK:** {}\n".format(test_description, data["sdk"]) if "min" in data: - test_description = "%s **Min SDK:** %s\n" % (test_description, data["min"]) + test_description = "{} **Min SDK:** {}\n".format(test_description, data["min"]) if "targetsdk" in data: - test_description = "%s **Target SDK:** %s\n" % (test_description, data["targetsdk"]) + test_description = "{} **Target SDK:** {}\n".format(test_description, data["targetsdk"]) if "minsdk" in data: - test_description = "%s **Min SDK:** %s\n" % (test_description, data["minsdk"]) + test_description = "{} **Min SDK:** {}\n".format(test_description, data["minsdk"]) if "maxsdk" in data: - test_description = "%s **Max SDK:** %s\n" % (test_description, data["maxsdk"]) + test_description = "{} **Max SDK:** {}\n".format(test_description, data["maxsdk"]) test_description = "%s\n**File Information:**\n" % (test_description) if "name" in data: - test_description = "%s **Name:** %s\n" % (test_description, data["name"]) + test_description = "{} **Name:** {}\n".format(test_description, data["name"]) if "md5" in data: - test_description = "%s **MD5:** %s\n" % (test_description, data["md5"]) + test_description = "{} **MD5:** {}\n".format(test_description, data["md5"]) if "sha1" in data: - test_description = "%s **SHA-1:** %s\n" % (test_description, data["sha1"]) + test_description = "{} **SHA-1:** {}\n".format(test_description, data["sha1"]) if "sha256" in data: - test_description = "%s **SHA-256:** %s\n" % (test_description, data["sha256"]) + test_description = "{} **SHA-256:** {}\n".format(test_description, data["sha256"]) if "size" in data: - test_description = "%s **Size:** %s\n" % (test_description, data["size"]) + test_description = "{} **Size:** {}\n".format(test_description, data["size"]) if "urls" in data: curl = "" @@ -77,10 +77,10 @@ def get_findings(self, filename, test): curl = "%s\n" % (curl) if curl: - test_description = "%s\n**URL's:**\n %s\n" % (test_description, curl) + test_description = f"{test_description}\n**URL's:**\n {curl}\n" if "bin_anal" in data: - test_description = "%s \n**Binary Analysis:** %s\n" % (test_description, data["bin_anal"]) + test_description = "{} \n**Binary Analysis:** {}\n".format(test_description, data["bin_anal"]) test.description = html2text(test_description) diff --git a/dojo/tools/mobsfscan/parser.py b/dojo/tools/mobsfscan/parser.py index 58514eaea8..b65f63c980 100644 --- a/dojo/tools/mobsfscan/parser.py +++ b/dojo/tools/mobsfscan/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class MobsfscanParser(object): +class MobsfscanParser: """ A class that can be used to parse the mobsfscan (https://github.com/MobSF/mobsfscan) JSON report file. """ diff --git a/dojo/tools/mozilla_observatory/parser.py b/dojo/tools/mozilla_observatory/parser.py index 72e6a6d623..2f901de698 100644 --- a/dojo/tools/mozilla_observatory/parser.py +++ b/dojo/tools/mozilla_observatory/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class MozillaObservatoryParser(object): +class MozillaObservatoryParser: """Mozilla Observatory See: https://observatory.mozilla.org diff --git a/dojo/tools/ms_defender/parser.py b/dojo/tools/ms_defender/parser.py index 3bcdf56e07..ab6346fac0 100644 --- a/dojo/tools/ms_defender/parser.py +++ b/dojo/tools/ms_defender/parser.py @@ -3,7 +3,7 @@ import zipfile -class MSDefenderParser(object): +class MSDefenderParser: """ Import from MSDefender findings """ diff --git a/dojo/tools/nancy/parser.py b/dojo/tools/nancy/parser.py index 4f8a65c4ed..2c3111cb9f 100644 --- a/dojo/tools/nancy/parser.py +++ b/dojo/tools/nancy/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class NancyParser(object): +class NancyParser: def get_scan_types(self): return ["Nancy Scan"] diff --git a/dojo/tools/netsparker/parser.py b/dojo/tools/netsparker/parser.py index b79e043c81..37714c2c0f 100644 --- a/dojo/tools/netsparker/parser.py +++ b/dojo/tools/netsparker/parser.py @@ -6,7 +6,7 @@ from dojo.models import Finding, Endpoint -class NetsparkerParser(object): +class NetsparkerParser: def get_scan_types(self): return ["Netsparker Scan"] diff --git a/dojo/tools/neuvector/parser.py b/dojo/tools/neuvector/parser.py index 17be763568..b4e77abb11 100644 --- a/dojo/tools/neuvector/parser.py +++ b/dojo/tools/neuvector/parser.py @@ -10,7 +10,7 @@ NEUVECTOR_CONTAINER_SCAN_ENGAGEMENT_NAME = "NV container scan" -class NeuVectorJsonParser(object): +class NeuVectorJsonParser: def parse(self, json_output, test): tree = self.parse_json(json_output) items = [] @@ -102,9 +102,7 @@ def get_item(vulnerability, test): duplicate=False, out_of_scope=False, mitigated=None, - severity_justification="{} (CVSS v3 base score: {})\n".format( - vector, score_v3 - ), + severity_justification=f"{vector} (CVSS v3 base score: {score_v3})\n", impact=severity, ) finding.unsaved_vulnerability_ids = [vulnerability.get("name")] @@ -129,7 +127,7 @@ def convert_severity(severity): return severity.title() -class NeuVectorParser(object): +class NeuVectorParser: def get_scan_types(self): return [NEUVECTOR_SCAN_NAME] diff --git a/dojo/tools/neuvector_compliance/parser.py b/dojo/tools/neuvector_compliance/parser.py index 74e5e515fd..c16ecebe4b 100644 --- a/dojo/tools/neuvector_compliance/parser.py +++ b/dojo/tools/neuvector_compliance/parser.py @@ -80,28 +80,26 @@ def get_item(node, test): test_profile = node.get("profile", "profile unknown") - full_description = "{} ({}), {}:\n".format( - test_number, category, test_profile - ) - full_description += "{}\n".format(test_description) - full_description += "Audit: {}\n".format(test_severity) + full_description = f"{test_number} ({category}), {test_profile}:\n" + full_description += f"{test_description}\n" + full_description += f"Audit: {test_severity}\n" if "evidence" in node: full_description += "Evidence:\n{}\n".format(node.get("evidence")) if "location" in node: full_description += "Location:\n{}\n".format(node.get("location")) - full_description += "Mitigation:\n{}\n".format(mitigation) + full_description += f"Mitigation:\n{mitigation}\n" tags = node.get("tags", []) if len(tags) > 0: full_description += "Tags:\n" for t in tags: - full_description += "{}\n".format(str(t).rstrip()) + full_description += f"{str(t).rstrip()}\n" messages = node.get("message", []) if len(messages) > 0: full_description += "Messages:\n" for m in messages: - full_description += "{}\n".format(str(m).rstrip()) + full_description += f"{str(m).rstrip()}\n" finding = Finding( title=title, @@ -135,7 +133,7 @@ def convert_severity(severity): return severity.title() -class NeuVectorComplianceParser(object): +class NeuVectorComplianceParser: def get_scan_types(self): return [NEUVECTOR_SCAN_NAME] diff --git a/dojo/tools/nexpose/parser.py b/dojo/tools/nexpose/parser.py index 4fd1c85b67..8a9e5dfdb8 100644 --- a/dojo/tools/nexpose/parser.py +++ b/dojo/tools/nexpose/parser.py @@ -8,7 +8,7 @@ from dojo.models import Finding, Endpoint -class NexposeParser(object): +class NexposeParser: """ The objective of this class is to parse Nexpose's XML 2.0 Report. diff --git a/dojo/tools/nikto/json_parser.py b/dojo/tools/nikto/json_parser.py index 2d06902e46..dc463d8385 100644 --- a/dojo/tools/nikto/json_parser.py +++ b/dojo/tools/nikto/json_parser.py @@ -2,7 +2,7 @@ from dojo.models import Endpoint, Finding -class NiktoJSONParser(object): +class NiktoJSONParser: def process_json(self, file, test): data = json.load(file) if len(data) == 1 and isinstance(data, list): diff --git a/dojo/tools/nikto/parser.py b/dojo/tools/nikto/parser.py index 99ea2f2697..414a0a882d 100644 --- a/dojo/tools/nikto/parser.py +++ b/dojo/tools/nikto/parser.py @@ -2,7 +2,7 @@ from dojo.tools.nikto.xml_parser import NiktoXMLParser -class NiktoParser(object): +class NiktoParser: """Nikto web server scanner - https://cirt.net/Nikto2 The current parser support 3 sources: diff --git a/dojo/tools/nikto/xml_parser.py b/dojo/tools/nikto/xml_parser.py index 3480ffadd8..2686c3e8f6 100644 --- a/dojo/tools/nikto/xml_parser.py +++ b/dojo/tools/nikto/xml_parser.py @@ -7,7 +7,7 @@ logger = logging.getLogger(__name__) -class NiktoXMLParser(object): +class NiktoXMLParser: def process_xml(self, file, test): dupes = dict() tree = ET.parse(file) diff --git a/dojo/tools/nmap/parser.py b/dojo/tools/nmap/parser.py index 171795126c..6c62a1af88 100755 --- a/dojo/tools/nmap/parser.py +++ b/dojo/tools/nmap/parser.py @@ -5,7 +5,7 @@ from dojo.models import Endpoint, Finding -class NmapParser(object): +class NmapParser: def get_scan_types(self): return ["Nmap Scan"] @@ -54,7 +54,7 @@ def get_findings(self, file, test): "**Host OS:** %s\n" % os_match.attrib["name"] ) if "accuracy" in os_match.attrib: - host_info += "**Accuracy:** {0}%\n".format( + host_info += "**Accuracy:** {}%\n".format( os_match.attrib["accuracy"] ) @@ -74,12 +74,9 @@ def get_findings(self, file, test): # filter on open ports if "open" != port_element.find("state").attrib.get("state"): continue - title = "Open port: %s/%s" % (endpoint.port, endpoint.protocol) + title = f"Open port: {endpoint.port}/{endpoint.protocol}" description = host_info - description += "**Port/Protocol:** %s/%s\n" % ( - endpoint.port, - endpoint.protocol, - ) + description += f"**Port/Protocol:** {endpoint.port}/{endpoint.protocol}\n" service_info = "\n\n" if port_element.find("service") is not None: diff --git a/dojo/tools/noseyparker/parser.py b/dojo/tools/noseyparker/parser.py index acb28056f1..c475b93d10 100644 --- a/dojo/tools/noseyparker/parser.py +++ b/dojo/tools/noseyparker/parser.py @@ -5,7 +5,7 @@ from dojo.models import Finding -class NoseyParkerParser(object): +class NoseyParkerParser: """ Scanning secrets from repos """ diff --git a/dojo/tools/npm_audit/parser.py b/dojo/tools/npm_audit/parser.py index a9b6dfe9bf..f1255d5475 100644 --- a/dojo/tools/npm_audit/parser.py +++ b/dojo/tools/npm_audit/parser.py @@ -8,7 +8,7 @@ logger = logging.getLogger(__name__) -class NpmAuditParser(object): +class NpmAuditParser: def get_scan_types(self): return ["NPM Audit Scan"] diff --git a/dojo/tools/npm_audit_7_plus/parser.py b/dojo/tools/npm_audit_7_plus/parser.py index 1a500b8e3b..42abc86330 100644 --- a/dojo/tools/npm_audit_7_plus/parser.py +++ b/dojo/tools/npm_audit_7_plus/parser.py @@ -20,7 +20,7 @@ ''' -class NpmAudit7PlusParser(object): +class NpmAudit7PlusParser: """Represents the parser class.""" def get_scan_types(self): @@ -57,8 +57,8 @@ def parse_json(self, json_output): if tree.get("audit"): if not tree.get("audit").get("auditReportVersion"): raise ValueError( - ("This parser only supports output from npm audit version" - " 7 and above.") + "This parser only supports output from npm audit version" + " 7 and above." ) subtree = tree.get("audit").get("vulnerabilities") # output from npm audit --dry-run --json @@ -67,8 +67,8 @@ def parse_json(self, json_output): else: if not tree.get("auditReportVersion"): raise ValueError( - ("This parser only supports output from npm audit version" - " 7 and above.") + "This parser only supports output from npm audit version" + " 7 and above." ) subtree = tree.get("vulnerabilities") @@ -125,7 +125,7 @@ def get_item(item_node, tree, test): if isinstance(item_node["fixAvailable"], dict): fix_name = item_node["fixAvailable"]["name"] fix_version = item_node["fixAvailable"]["version"] - mitigation = "Update {0} to version {1}".format(fix_name, fix_version) + mitigation = f"Update {fix_name} to version {fix_version}" else: mitigation = "No specific mitigation provided by tool." @@ -187,8 +187,7 @@ def get_vuln_description(item_node, tree): if isinstance(item_node["fixAvailable"], dict): fix_name = item_node["fixAvailable"]["name"] fix_version = item_node["fixAvailable"]["version"] - mitigation = "Fix Available: Update {0} to version {1}".format( - fix_name, fix_version) + mitigation = f"Fix Available: Update {fix_name} to version {fix_version}" else: mitigation = "No specific mitigation provided by tool." diff --git a/dojo/tools/nsp/parser.py b/dojo/tools/nsp/parser.py index 40a7dcb66a..35c0fca976 100644 --- a/dojo/tools/nsp/parser.py +++ b/dojo/tools/nsp/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class NspParser(object): +class NspParser: def get_scan_types(self): return ["Node Security Platform Scan"] diff --git a/dojo/tools/nuclei/parser.py b/dojo/tools/nuclei/parser.py index 76ed959eac..f26f888811 100644 --- a/dojo/tools/nuclei/parser.py +++ b/dojo/tools/nuclei/parser.py @@ -9,7 +9,7 @@ logger = logging.getLogger(__name__) -class NucleiParser(object): +class NucleiParser: """ A class that can be used to parse the nuclei (https://github.com/projectdiscovery/nuclei) JSON report file """ diff --git a/dojo/tools/openscap/parser.py b/dojo/tools/openscap/parser.py index 9f3ba66132..25bb392cdd 100644 --- a/dojo/tools/openscap/parser.py +++ b/dojo/tools/openscap/parser.py @@ -8,7 +8,7 @@ from django.core.exceptions import ValidationError -class OpenscapParser(object): +class OpenscapParser: def get_scan_types(self): return ["Openscap Vulnerability Scan"] @@ -36,26 +36,26 @@ def get_findings(self, file, test): # read rules rules = {} - for rule in root.findall(".//{0}Rule".format(namespace)): + for rule in root.findall(f".//{namespace}Rule"): rules[rule.attrib["id"]] = { - "title": rule.findtext("./{0}title".format(namespace)) + "title": rule.findtext(f"./{namespace}title") } # go to test result - test_result = tree.find("./{0}TestResult".format(namespace)) + test_result = tree.find(f"./{namespace}TestResult") ips = [] # append all target in a list. - for ip in test_result.findall("./{0}target".format(namespace)): + for ip in test_result.findall(f"./{namespace}target"): ips.append(ip.text) - for ip in test_result.findall("./{0}target-address".format(namespace)): + for ip in test_result.findall(f"./{namespace}target-address"): ips.append(ip.text) dupes = dict() # run both rule, and rule-result in parallel so that we can get title # for failed test from rule. for rule_result in test_result.findall( - "./{0}rule-result".format(namespace) + f"./{namespace}rule-result" ): - result = rule_result.findtext("./{0}result".format(namespace)) + result = rule_result.findtext(f"./{namespace}result") # find only failed report. if "fail" in result: # get rule corresponding to rule-result @@ -69,9 +69,7 @@ def get_findings(self, file, test): ) vulnerability_ids = [] for vulnerability_id in rule_result.findall( - "./{0}ident[@system='http://cve.mitre.org']".format( - namespace - ) + f"./{namespace}ident[@system='http://cve.mitre.org']" ): vulnerability_ids.append(vulnerability_id.text) # get severity. @@ -86,7 +84,7 @@ def get_findings(self, file, test): references = "" # get references. for check_content in rule_result.findall( - "./{0}check/{0}check-content-ref".format(namespace) + f"./{namespace}check/{namespace}check-content-ref" ): references += ( "**name:** : " + check_content.attrib["name"] + "\n" diff --git a/dojo/tools/openvas/csv_parser.py b/dojo/tools/openvas/csv_parser.py index 1d2eb4428a..00c5c09991 100644 --- a/dojo/tools/openvas/csv_parser.py +++ b/dojo/tools/openvas/csv_parser.py @@ -6,7 +6,7 @@ from dojo.models import Finding, Endpoint -class ColumnMappingStrategy(object): +class ColumnMappingStrategy: mapped_column = None def __init__(self): @@ -37,7 +37,7 @@ def process_column(self, column_name, column_value, finding): class DateColumnMappingStrategy(ColumnMappingStrategy): def __init__(self): self.mapped_column = "timestamp" - super(DateColumnMappingStrategy, self).__init__() + super().__init__() def map_column_value(self, finding, column_value): finding.date = parse(column_value).date() @@ -46,7 +46,7 @@ def map_column_value(self, finding, column_value): class TitleColumnMappingStrategy(ColumnMappingStrategy): def __init__(self): self.mapped_column = "nvt name" - super(TitleColumnMappingStrategy, self).__init__() + super().__init__() def map_column_value(self, finding, column_value): finding.title = column_value @@ -55,7 +55,7 @@ def map_column_value(self, finding, column_value): class CweColumnMappingStrategy(ColumnMappingStrategy): def __init__(self): self.mapped_column = "cweid" - super(CweColumnMappingStrategy, self).__init__() + super().__init__() def map_column_value(self, finding, column_value): if column_value.isdigit(): @@ -65,7 +65,7 @@ def map_column_value(self, finding, column_value): class PortColumnMappingStrategy(ColumnMappingStrategy): def __init__(self): self.mapped_column = "port" - super(PortColumnMappingStrategy, self).__init__() + super().__init__() def map_column_value(self, finding, column_value): if column_value.isdigit(): @@ -75,7 +75,7 @@ def map_column_value(self, finding, column_value): class CveColumnMappingStrategy(ColumnMappingStrategy): def __init__(self): self.mapped_column = "cves" - super(CveColumnMappingStrategy, self).__init__() + super().__init__() def map_column_value(self, finding, column_value): if column_value != "": @@ -90,7 +90,7 @@ def map_column_value(self, finding, column_value): class NVDCVEColumnMappingStrategy(ColumnMappingStrategy): def __init__(self): self.mapped_column = "nvt oid" - super(NVDCVEColumnMappingStrategy, self).__init__() + super().__init__() def map_column_value(self, finding, column_value): cve_pattern = r'CVE-\d{4}-\d{4,7}' @@ -102,7 +102,7 @@ def map_column_value(self, finding, column_value): class ProtocolColumnMappingStrategy(ColumnMappingStrategy): def __init__(self): self.mapped_column = "port protocol" - super(ProtocolColumnMappingStrategy, self).__init__() + super().__init__() def map_column_value(self, finding, column_value): if column_value: # do not store empty protocol @@ -112,7 +112,7 @@ def map_column_value(self, finding, column_value): class IpColumnMappingStrategy(ColumnMappingStrategy): def __init__(self): self.mapped_column = "ip" - super(IpColumnMappingStrategy, self).__init__() + super().__init__() def map_column_value(self, finding, column_value): if not finding.unsaved_endpoints[ @@ -124,7 +124,7 @@ def map_column_value(self, finding, column_value): class HostnameColumnMappingStrategy(ColumnMappingStrategy): def __init__(self): self.mapped_column = "hostname" - super(HostnameColumnMappingStrategy, self).__init__() + super().__init__() def map_column_value(self, finding, column_value): if column_value: # do not override IP if hostname is empty @@ -139,7 +139,7 @@ def is_valid_severity(severity): def __init__(self): self.mapped_column = "severity" - super(SeverityColumnMappingStrategy, self).__init__() + super().__init__() def map_column_value(self, finding, column_value): if self.is_valid_severity(column_value): @@ -151,7 +151,7 @@ def map_column_value(self, finding, column_value): class DescriptionColumnMappingStrategy(ColumnMappingStrategy): def __init__(self): self.mapped_column = "summary" - super(DescriptionColumnMappingStrategy, self).__init__() + super().__init__() def map_column_value(self, finding, column_value): finding.description = column_value @@ -160,7 +160,7 @@ def map_column_value(self, finding, column_value): class MitigationColumnMappingStrategy(ColumnMappingStrategy): def __init__(self): self.mapped_column = "solution" - super(MitigationColumnMappingStrategy, self).__init__() + super().__init__() def map_column_value(self, finding, column_value): finding.mitigation = column_value @@ -169,7 +169,7 @@ def map_column_value(self, finding, column_value): class ImpactColumnMappingStrategy(ColumnMappingStrategy): def __init__(self): self.mapped_column = "vulnerability insight" - super(ImpactColumnMappingStrategy, self).__init__() + super().__init__() def map_column_value(self, finding, column_value): finding.impact = column_value @@ -178,7 +178,7 @@ def map_column_value(self, finding, column_value): class ReferencesColumnMappingStrategy(ColumnMappingStrategy): def __init__(self): self.mapped_column = "specific result" - super(ReferencesColumnMappingStrategy, self).__init__() + super().__init__() def map_column_value(self, finding, column_value): finding.references = column_value @@ -187,7 +187,7 @@ def map_column_value(self, finding, column_value): class ActiveColumnMappingStrategy(ColumnMappingStrategy): def __init__(self): self.mapped_column = "active" - super(ActiveColumnMappingStrategy, self).__init__() + super().__init__() def map_column_value(self, finding, column_value): finding.active = self.evaluate_bool_value(column_value) @@ -196,7 +196,7 @@ def map_column_value(self, finding, column_value): class VerifiedColumnMappingStrategy(ColumnMappingStrategy): def __init__(self): self.mapped_column = "verified" - super(VerifiedColumnMappingStrategy, self).__init__() + super().__init__() def map_column_value(self, finding, column_value): finding.verified = self.evaluate_bool_value(column_value) @@ -205,7 +205,7 @@ def map_column_value(self, finding, column_value): class FalsePositiveColumnMappingStrategy(ColumnMappingStrategy): def __init__(self): self.mapped_column = "falsepositive" - super(FalsePositiveColumnMappingStrategy, self).__init__() + super().__init__() def map_column_value(self, finding, column_value): finding.false_p = self.evaluate_bool_value(column_value) @@ -214,13 +214,13 @@ def map_column_value(self, finding, column_value): class DuplicateColumnMappingStrategy(ColumnMappingStrategy): def __init__(self): self.mapped_column = "duplicate" - super(DuplicateColumnMappingStrategy, self).__init__() + super().__init__() def map_column_value(self, finding, column_value): finding.duplicate = self.evaluate_bool_value(column_value) -class OpenVASCSVParser(object): +class OpenVASCSVParser: def create_chain(self): date_column_strategy = DateColumnMappingStrategy() title_column_strategy = TitleColumnMappingStrategy() diff --git a/dojo/tools/openvas/parser.py b/dojo/tools/openvas/parser.py index 6a1399f28e..ce548db587 100755 --- a/dojo/tools/openvas/parser.py +++ b/dojo/tools/openvas/parser.py @@ -2,7 +2,7 @@ from dojo.tools.openvas.xml_parser import OpenVASXMLParser -class OpenVASParser(object): +class OpenVASParser: def get_scan_types(self): return ["OpenVAS Parser"] diff --git a/dojo/tools/openvas/xml_parser.py b/dojo/tools/openvas/xml_parser.py index bc2c63dd82..5937b3c11b 100644 --- a/dojo/tools/openvas/xml_parser.py +++ b/dojo/tools/openvas/xml_parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class OpenVASXMLParser(object): +class OpenVASXMLParser: def get_findings(self, filename, test): findings = [] tree = ET.parse(filename) diff --git a/dojo/tools/ort/parser.py b/dojo/tools/ort/parser.py index d2811d3e17..d59b48be43 100644 --- a/dojo/tools/ort/parser.py +++ b/dojo/tools/ort/parser.py @@ -5,7 +5,7 @@ from dojo.models import Finding -class OrtParser(object): +class OrtParser: """Oss Review Toolkit Parser""" def get_scan_types(self): diff --git a/dojo/tools/ossindex_devaudit/parser.py b/dojo/tools/ossindex_devaudit/parser.py index 8d04bac2d4..f5ada25b3c 100644 --- a/dojo/tools/ossindex_devaudit/parser.py +++ b/dojo/tools/ossindex_devaudit/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class OssIndexDevauditParser(object): +class OssIndexDevauditParser: """OssIndex Devaudit Results Parser Parses files created by the Sonatype OssIndex Devaudit tool https://github.com/sonatype-nexus-community/DevAudit diff --git a/dojo/tools/osv_scanner/parser.py b/dojo/tools/osv_scanner/parser.py index 4d6fff7ab4..9afbefb02d 100644 --- a/dojo/tools/osv_scanner/parser.py +++ b/dojo/tools/osv_scanner/parser.py @@ -2,7 +2,7 @@ from dojo.models import Finding -class OSVScannerParser(object): +class OSVScannerParser: def get_scan_types(self): return ["OSV Scan"] diff --git a/dojo/tools/outpost24/parser.py b/dojo/tools/outpost24/parser.py index af07759f1e..097664e757 100644 --- a/dojo/tools/outpost24/parser.py +++ b/dojo/tools/outpost24/parser.py @@ -7,7 +7,7 @@ logger = logging.getLogger(__name__) -class Outpost24Parser(object): +class Outpost24Parser: def get_scan_types(self): return ["Outpost24 Scan"] @@ -57,9 +57,7 @@ def get_findings(self, file, test): else: severity = "Critical" cvss_description = detail.findtext("cvss_vector_description") - severity_justification = "{}\n{}".format( - cvss_score, cvss_description - ) + severity_justification = f"{cvss_score}\n{cvss_description}" finding = Finding( title=title, test=test, diff --git a/dojo/tools/parser_test.py b/dojo/tools/parser_test.py index 34dec50e35..6a28a08998 100644 --- a/dojo/tools/parser_test.py +++ b/dojo/tools/parser_test.py @@ -1,4 +1,4 @@ -class ParserTest(object): +class ParserTest: def __init__(self, name: str, type: str, version: str): self.name = name self.type = type diff --git a/dojo/tools/php_security_audit_v2/parser.py b/dojo/tools/php_security_audit_v2/parser.py index f1ee8022c1..36fe5b48a7 100644 --- a/dojo/tools/php_security_audit_v2/parser.py +++ b/dojo/tools/php_security_audit_v2/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class PhpSecurityAuditV2Parser(object): +class PhpSecurityAuditV2Parser: def get_scan_types(self): return ["PHP Security Audit v2"] diff --git a/dojo/tools/php_symfony_security_check/parser.py b/dojo/tools/php_symfony_security_check/parser.py index c5fb511880..3691e60639 100644 --- a/dojo/tools/php_symfony_security_check/parser.py +++ b/dojo/tools/php_symfony_security_check/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class PhpSymfonySecurityCheckParser(object): +class PhpSymfonySecurityCheckParser: def get_scan_types(self): return ["PHP Symfony Security Check"] diff --git a/dojo/tools/pmd/parser.py b/dojo/tools/pmd/parser.py index e34c1c21f5..2eea92daae 100644 --- a/dojo/tools/pmd/parser.py +++ b/dojo/tools/pmd/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class PmdParser(object): +class PmdParser: def get_scan_types(self): return ["PMD Scan"] @@ -54,7 +54,7 @@ def get_findings(self, filename, test): finding.mitigation = "No mitigation provided" key = hashlib.sha256( - f"{finding.title}|{finding.description}|{finding.file_path}|{finding.line}".encode("utf-8") + f"{finding.title}|{finding.description}|{finding.file_path}|{finding.line}".encode() ).hexdigest() if key not in dupes: diff --git a/dojo/tools/popeye/parser.py b/dojo/tools/popeye/parser.py index 67e176a911..12548d0dca 100644 --- a/dojo/tools/popeye/parser.py +++ b/dojo/tools/popeye/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class PopeyeParser(object): +class PopeyeParser: """ Popeye is a kubernetes cluster resource analyzer. """ diff --git a/dojo/tools/pwn_sast/parser.py b/dojo/tools/pwn_sast/parser.py index 0b5a942eb4..ac0b0a0912 100644 --- a/dojo/tools/pwn_sast/parser.py +++ b/dojo/tools/pwn_sast/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class PWNSASTParser(object): +class PWNSASTParser: """ A class that can be used to parse pwn_sast source code scanning results in JSON format. See https://github.com/0dayinc/pwn for additional details. """ diff --git a/dojo/tools/qualys/parser.py b/dojo/tools/qualys/parser.py index a415b4487f..b8498962f1 100644 --- a/dojo/tools/qualys/parser.py +++ b/dojo/tools/qualys/parser.py @@ -187,9 +187,7 @@ def parse_finding(host, tree): # DefectDojo does not support cvssv2 _temp["CVSS_vector"] = None - search = ".//GLOSSARY/VULN_DETAILS_LIST/VULN_DETAILS[@id='{}']".format( - _gid - ) + search = f".//GLOSSARY/VULN_DETAILS_LIST/VULN_DETAILS[@id='{_gid}']" vuln_item = tree.find(search) if vuln_item is not None: finding = Finding() @@ -298,7 +296,7 @@ def qualys_parser(qualys_xml_file): return finding_list -class QualysParser(object): +class QualysParser: def get_scan_types(self): return ["Qualys Scan"] diff --git a/dojo/tools/qualys_infrascan_webgui/parser.py b/dojo/tools/qualys_infrascan_webgui/parser.py index e60084619a..1cd6f2bf14 100644 --- a/dojo/tools/qualys_infrascan_webgui/parser.py +++ b/dojo/tools/qualys_infrascan_webgui/parser.py @@ -126,7 +126,7 @@ def qualys_convert_severity(raw_val): return "Info" -class QualysInfrascanWebguiParser(object): +class QualysInfrascanWebguiParser: def get_scan_types(self): return ["Qualys Infrastructure Scan (WebGUI XML)"] diff --git a/dojo/tools/qualys_webapp/parser.py b/dojo/tools/qualys_webapp/parser.py index c564c76cd2..4cd236f739 100644 --- a/dojo/tools/qualys_webapp/parser.py +++ b/dojo/tools/qualys_webapp/parser.py @@ -464,7 +464,7 @@ def qualys_webapp_parser(qualys_xml_file, test, unique, enable_weakness=False): return items -class QualysWebAppParser(object): +class QualysWebAppParser: def get_scan_types(self): return ["Qualys Webapp Scan"] diff --git a/dojo/tools/redhatsatellite/parser.py b/dojo/tools/redhatsatellite/parser.py index dcfb67e71a..1168205b06 100644 --- a/dojo/tools/redhatsatellite/parser.py +++ b/dojo/tools/redhatsatellite/parser.py @@ -2,7 +2,7 @@ from dojo.models import Finding -class RedHatSatelliteParser(object): +class RedHatSatelliteParser: def get_scan_types(self): return ["Red Hat Satellite"] diff --git a/dojo/tools/retirejs/parser.py b/dojo/tools/retirejs/parser.py index 2482d517dc..aaf038f898 100644 --- a/dojo/tools/retirejs/parser.py +++ b/dojo/tools/retirejs/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class RetireJsParser(object): +class RetireJsParser: def get_scan_types(self): return ["Retire.js Scan"] diff --git a/dojo/tools/risk_recon/api.py b/dojo/tools/risk_recon/api.py index 0ac61f805d..8b1a07dfbf 100644 --- a/dojo/tools/risk_recon/api.py +++ b/dojo/tools/risk_recon/api.py @@ -29,7 +29,7 @@ def __init__(self, api_key, endpoint, data): def map_toes(self): response = self.session.get( - url="{}/toes".format(self.url), + url=f"{self.url}/toes", headers={"accept": "application/json", "Authorization": self.key}, ) @@ -51,9 +51,7 @@ def map_toes(self): self.toe_map[toe_id] = filters if filters else self.data else: raise Exception( - "Unable to query Target of Evaluations due to {} - {}".format( - response.status_code, response.content - ) + f"Unable to query Target of Evaluations due to {response.status_code} - {response.content}" ) def filter_finding(self, finding): @@ -71,7 +69,7 @@ def filter_finding(self, finding): def get_findings(self): for toe in self.toe_map.keys(): response = self.session.get( - url="{}/findings/{}".format(self.url, toe), + url=f"{self.url}/findings/{toe}", headers={ "accept": "application/json", "Authorization": self.key, @@ -85,7 +83,5 @@ def get_findings(self): self.findings.append(finding) else: raise Exception( - "Unable to collect findings from toe: {} due to {} - {}".format( - toe, response.status_code, response.content - ) + f"Unable to collect findings from toe: {toe} due to {response.status_code} - {response.content}" ) diff --git a/dojo/tools/risk_recon/parser.py b/dojo/tools/risk_recon/parser.py index 8c70496d69..21bbfbbdbe 100644 --- a/dojo/tools/risk_recon/parser.py +++ b/dojo/tools/risk_recon/parser.py @@ -5,7 +5,7 @@ from dojo.tools.risk_recon.api import RiskReconAPI -class RiskReconParser(object): +class RiskReconParser: def get_scan_types(self): return ["Risk Recon API Importer"] diff --git a/dojo/tools/rusty_hog/parser.py b/dojo/tools/rusty_hog/parser.py index da0baa6c83..0488270e09 100644 --- a/dojo/tools/rusty_hog/parser.py +++ b/dojo/tools/rusty_hog/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class RustyhogParser(object): +class RustyhogParser: def get_scan_types(self): return ["Rusty Hog Scan"] @@ -27,7 +27,7 @@ def get_items(self, json_output, scanner, test): vulnerabilities=self.parse_json(json_output), scanner=scanner ) for finding in findings: - unique_key = "Finding {}".format(finding) + unique_key = f"Finding {finding}" items[unique_key] = finding return list(items.values()) @@ -81,9 +81,7 @@ def __getitem(self, vulnerabilities, scanner): elif scanner == "Choctaw Hog": """Choctaw Hog""" found_secret_string = vulnerability.get("stringsFound") - description = "**This string was found:** {}".format( - found_secret_string - ) + description = f"**This string was found:** {found_secret_string}" if vulnerability.get("commit") is not None: description += "\n**Commit message:** {}".format( vulnerability.get("commit") @@ -119,9 +117,7 @@ def __getitem(self, vulnerabilities, scanner): elif scanner == "Duroc Hog": """Duroc Hog""" found_secret_string = vulnerability.get("stringsFound") - description = "**This string was found:** {}".format( - found_secret_string - ) + description = f"**This string was found:** {found_secret_string}" if vulnerability.get("path") is not None: description += "\n**Path of Issue:** {}".format( vulnerability.get("path") @@ -137,9 +133,7 @@ def __getitem(self, vulnerabilities, scanner): elif scanner == "Gottingen Hog": """Gottingen Hog""" found_secret_string = vulnerability.get("stringsFound") - description = "**This string was found:** {}".format( - found_secret_string - ) + description = f"**This string was found:** {found_secret_string}" if vulnerability.get("issue_id") is not None: description += "\n**JIRA Issue ID:** {}".format( vulnerability.get("issue_id") @@ -154,9 +148,7 @@ def __getitem(self, vulnerabilities, scanner): ) elif scanner == "Essex Hog": found_secret_string = vulnerability.get("stringsFound") - description = "**This string was found:** {}".format( - found_secret_string - ) + description = f"**This string was found:** {found_secret_string}" if vulnerability.get("page_id") is not None: description += "\n**Confluence URL:** [{}]({})".format( vulnerability.get("url"), vulnerability.get("url") diff --git a/dojo/tools/sarif/parser.py b/dojo/tools/sarif/parser.py index e7963612b4..67af4d28bf 100644 --- a/dojo/tools/sarif/parser.py +++ b/dojo/tools/sarif/parser.py @@ -13,7 +13,7 @@ CWE_REGEX = r"cwe-\d+" -class SarifParser(object): +class SarifParser: """OASIS Static Analysis Results Interchange Format (SARIF) for version 2.1.0 only. https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=sarif @@ -267,9 +267,9 @@ def get_description(result, rule): message = get_message_from_multiformatMessageString( result["message"], rule ) - description += "**Result message:** {}\n".format(message) + description += f"**Result message:** {message}\n" if get_snippet(result) is not None: - description += "**Snippet:**\n```{}```\n".format(get_snippet(result)) + description += f"**Snippet:**\n```{get_snippet(result)}```\n" if rule is not None: if "name" in rule: description += f"**{_('Rule name')}:** {rule.get('name')}\n" diff --git a/dojo/tools/scantist/parser.py b/dojo/tools/scantist/parser.py index d4b1e6c076..0da36bbe19 100644 --- a/dojo/tools/scantist/parser.py +++ b/dojo/tools/scantist/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class ScantistParser(object): +class ScantistParser: """ Scantist Parser: Scantist does a deep scan of source code and binaries for vulnerabilities and has reports following three main categories diff --git a/dojo/tools/scout_suite/parser.py b/dojo/tools/scout_suite/parser.py index 1d019606e5..9e2d305c66 100644 --- a/dojo/tools/scout_suite/parser.py +++ b/dojo/tools/scout_suite/parser.py @@ -6,7 +6,7 @@ from dojo.tools.parser_test import ParserTest -class ScoutSuiteParser(object): +class ScoutSuiteParser: """"ScoutSuite Wiki: https://github.com/nccgroup/ScoutSuite/wiki""" ID = "Scout Suite" @@ -34,19 +34,16 @@ def get_tests(self, scan_type, handle): last_run = data["last_run"] test_description = "" - test_description = "%s**Account:** `%s`\n" % ( - test_description, - account_id, - ) - test_description = "%s**Provider:** %s\n" % ( + test_description = f"{test_description}**Account:** `{account_id}`\n" + test_description = "{}**Provider:** {}\n".format( test_description, data["provider_name"], ) - test_description = "%s**Ruleset:** `%s`\n" % ( + test_description = "{}**Ruleset:** `{}`\n".format( test_description, last_run["ruleset_name"], ) - test_description = "%s**Ruleset Description:** %s\n" % ( + test_description = "{}**Ruleset Description:** {}\n".format( test_description, last_run["ruleset_about"], ) @@ -177,7 +174,7 @@ def tabs(n): self.item_data = ( self.item_data + self.formatview(depth) - + "**%s:** %s\n\n" % (key.title(), src) + + f"**{key.title()}:** {src}\n\n" ) else: self.item_data = ( diff --git a/dojo/tools/semgrep/parser.py b/dojo/tools/semgrep/parser.py index f22364854a..b61cba1d13 100644 --- a/dojo/tools/semgrep/parser.py +++ b/dojo/tools/semgrep/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class SemgrepParser(object): +class SemgrepParser: def get_scan_types(self): return ["Semgrep JSON Report"] @@ -97,14 +97,14 @@ def get_description(self, item): description = "" message = item["extra"]["message"] - description += "**Result message:** {}\n".format(message) + description += f"**Result message:** {message}\n" snippet = item["extra"].get("lines") if snippet is not None: if "{4}" + "**CVE:** {} ({})\n" + "CVS Score: {} ({})\n" + "Summary: \n>{}" "\n\n-----\n\n".format( xml_node.attrib["cve_id"], xml_node.attrib.get("first_found_date"), diff --git a/dojo/tools/veracode_sca/parser.py b/dojo/tools/veracode_sca/parser.py index 7134615d98..c660a66ca2 100644 --- a/dojo/tools/veracode_sca/parser.py +++ b/dojo/tools/veracode_sca/parser.py @@ -12,7 +12,7 @@ from dojo.models import Finding -class VeracodeScaParser(object): +class VeracodeScaParser: vc_severity_mapping = { 1: "Info", 2: "Low", @@ -79,8 +79,8 @@ def _get_findings_json(self, file, test): severity = self.__cvss_to_severity(cvss_score) description = ( - "Project name: {0}\n" - "Title: \n>{1}" + "Project name: {}\n" + "Title: \n>{}" "\n\n-----\n\n".format( issue.get("project_name"), vulnerability.get("title") ) @@ -189,8 +189,8 @@ def get_findings_csv(self, file, test): date = None description = ( - "Project name: {0}\n" - "Title: \n>{1}" + "Project name: {}\n" + "Title: \n>{}" "\n\n-----\n\n".format(row.get("Project"), row.get("Title")) ) diff --git a/dojo/tools/wapiti/parser.py b/dojo/tools/wapiti/parser.py index 85925de990..3703e2226d 100644 --- a/dojo/tools/wapiti/parser.py +++ b/dojo/tools/wapiti/parser.py @@ -10,7 +10,7 @@ logger = logging.getLogger(__name__) -class WapitiParser(object): +class WapitiParser: """The web-application vulnerability scanner see: https://wapiti.sourceforge.io/ diff --git a/dojo/tools/wazuh/parser.py b/dojo/tools/wazuh/parser.py index 762847b81a..f4899d9cca 100644 --- a/dojo/tools/wazuh/parser.py +++ b/dojo/tools/wazuh/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding, Endpoint -class WazuhParser(object): +class WazuhParser: """ The vulnerabilities with condition "Package unfixed" are skipped because there is no fix out yet. https://github.com/wazuh/wazuh/issues/14560 diff --git a/dojo/tools/wfuzz/parser.py b/dojo/tools/wfuzz/parser.py index eb6b318669..6fcbf62b1f 100644 --- a/dojo/tools/wfuzz/parser.py +++ b/dojo/tools/wfuzz/parser.py @@ -5,7 +5,7 @@ from dojo.models import Finding, Endpoint -class WFuzzParser(object): +class WFuzzParser: """ A class that can be used to parse the WFuzz JSON report files """ diff --git a/dojo/tools/whispers/parser.py b/dojo/tools/whispers/parser.py index 42b79ee7c7..5c819df6ac 100644 --- a/dojo/tools/whispers/parser.py +++ b/dojo/tools/whispers/parser.py @@ -3,7 +3,7 @@ from dojo.models import Finding -class WhispersParser(object): +class WhispersParser: """ Identify hardcoded secrets in static structured text """ diff --git a/dojo/tools/whitehat_sentinel/parser.py b/dojo/tools/whitehat_sentinel/parser.py index 82596b33b8..8286ad3ca0 100644 --- a/dojo/tools/whitehat_sentinel/parser.py +++ b/dojo/tools/whitehat_sentinel/parser.py @@ -7,7 +7,7 @@ from dojo.models import Finding, Endpoint -class WhiteHatSentinelParser(object): +class WhiteHatSentinelParser: """ A class to parse WhiteHat Sentinel vulns from the WhiteHat Sentinel API vuln?query_site=[ SITE_ID]&format=json&display_attack_vectors=all&display_custom_risk=1&display_risk=1&display_description=custom diff --git a/dojo/tools/wiz/parser.py b/dojo/tools/wiz/parser.py index bec5fee29c..07fbf8e2d1 100644 --- a/dojo/tools/wiz/parser.py +++ b/dojo/tools/wiz/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class WizParser(object): +class WizParser: def get_scan_types(self): return ["Wiz Scan"] diff --git a/dojo/tools/wpscan/parser.py b/dojo/tools/wpscan/parser.py index b6f3bd01af..6fc25a4385 100644 --- a/dojo/tools/wpscan/parser.py +++ b/dojo/tools/wpscan/parser.py @@ -5,7 +5,7 @@ from dojo.models import Endpoint, Finding -class WpscanParser(object): +class WpscanParser: """WPScan - WordPress Security Scanner""" def get_scan_types(self): diff --git a/dojo/tools/xanitizer/parser.py b/dojo/tools/xanitizer/parser.py index 791aec06ef..80b3096b4e 100644 --- a/dojo/tools/xanitizer/parser.py +++ b/dojo/tools/xanitizer/parser.py @@ -7,7 +7,7 @@ from dojo.models import Finding -class XanitizerParser(object): +class XanitizerParser: def get_scan_types(self): return ["Xanitizer Scan"] @@ -36,9 +36,7 @@ def parse_xml(self, filename): root = tree.getroot() if "XanitizerFindingsList" not in root.tag: raise ValueError( - "'{}' is not a valid Xanitizer findings list report XML file.".format( - filename - ) + f"'{filename}' is not a valid Xanitizer findings list report XML file." ) return root @@ -90,14 +88,14 @@ def generate_title(self, finding, line): file = finding.find("file") if pckg is not None and cl is not None: if line: - title = "{} ({}.{}:{})".format(title, pckg.text, cl.text, line) + title = f"{title} ({pckg.text}.{cl.text}:{line})" else: - title = "{} ({}.{})".format(title, pckg.text, cl.text) + title = f"{title} ({pckg.text}.{cl.text})" else: if line: - title = "{} ({}:{})".format(title, file.text, line) + title = f"{title} ({file.text}:{line})" else: - title = "{} ({})".format(title, file.text) + title = f"{title} ({file.text})" return title @@ -109,7 +107,7 @@ def generate_description(self, finding): if finding.find("startNode") is not None: startnode = finding.find("startNode") endnode = finding.find("endNode") - description = "{}\n-----\n".format(description) + description = f"{description}\n-----\n" description = "{}\n**Starting at:** {} - **Line** {}".format( description, startnode.get("classFQN"), startnode.get("lineNo") ) @@ -120,19 +118,15 @@ def generate_description(self, finding): description = self.add_code(endnode, True, description) elif finding.find("node") is not None: node = finding.find("node") - description = "{}\n-----\n".format(description) + description = f"{description}\n-----\n" line = node.get("lineNo") location = node.get("classFQN") if location is None: location = node.get("relativePath") if line is not None and int(line) > 0: - description = "{}\n**Finding at:** {} - **Line** {}".format( - description, location, line - ) + description = f"{description}\n**Finding at:** {location} - **Line** {line}" else: - description = "{}\n**Finding at:** {}".format( - description, location - ) + description = f"{description}\n**Finding at:** {location}" description = self.add_code(node, True, description) return description @@ -146,12 +140,10 @@ def add_code(self, node, showline, description): if showline or len(codelines) == 1: for code in codelines: if code.get("finding") == "true": - description = "{}\n**Finding Line:** {}".format( - description, code.text - ) + description = f"{description}\n**Finding Line:** {code.text}" if len(codelines) > 1: - description = "{}\n**Code Excerpt:** ".format(description) + description = f"{description}\n**Code Excerpt:** " for code in codelines: if code.text: description = "{}\n{}: {}".format( diff --git a/dojo/tools/yarn_audit/parser.py b/dojo/tools/yarn_audit/parser.py index 5f0ae8b39a..a4feda6c46 100644 --- a/dojo/tools/yarn_audit/parser.py +++ b/dojo/tools/yarn_audit/parser.py @@ -4,7 +4,7 @@ from dojo.tools.utils import get_npm_cwe -class YarnAuditParser(object): +class YarnAuditParser: def get_scan_types(self): return ["Yarn Audit Scan"] diff --git a/dojo/tools/zap/parser.py b/dojo/tools/zap/parser.py index f7411daea2..b835c1543e 100755 --- a/dojo/tools/zap/parser.py +++ b/dojo/tools/zap/parser.py @@ -4,7 +4,7 @@ from dojo.models import Endpoint, Finding -class ZapParser(object): +class ZapParser: """Parser for XML file generated by the OWASP Zed Attacl Proxy (ZAP) tool https://www.zaproxy.org/.""" MAPPING_SEVERITY = {"0": "Info", "1": "Low", "2": "Medium", "3": "High"} diff --git a/dojo/user/validators.py b/dojo/user/validators.py index c3eee9cfbe..767bc560b5 100644 --- a/dojo/user/validators.py +++ b/dojo/user/validators.py @@ -6,7 +6,7 @@ from dojo.utils import get_system_setting -class MinLengthValidator(object): +class MinLengthValidator: def validate(self, password, user=None): if len(password) < get_system_setting('minimum_password_length'): raise ValidationError( @@ -20,7 +20,7 @@ def get_help_text(self): minimum_length=get_system_setting('minimum_password_length'))) -class MaxLengthValidator(object): +class MaxLengthValidator: def validate(self, password, user=None): if len(password) > get_system_setting('maximum_password_length'): raise ValidationError( @@ -34,7 +34,7 @@ def get_help_text(self): maximum_length=get_system_setting('maximum_password_length'))) -class NumberValidator(object): +class NumberValidator: def validate(self, password, user=None): if not re.findall(r'\d', password) and get_system_setting('number_character_required'): raise ValidationError( @@ -47,7 +47,7 @@ def get_help_text(self): return gettext('Password must contain at least 1 digit, 0-9.') -class UppercaseValidator(object): +class UppercaseValidator: def validate(self, password, user=None): if not re.findall('[A-Z]', password) and get_system_setting('uppercase_character_required'): raise ValidationError( @@ -60,7 +60,7 @@ def get_help_text(self): return gettext('Password must contain at least 1 uppercase letter, A-Z.') -class LowercaseValidator(object): +class LowercaseValidator: def validate(self, password, user=None): if not re.findall('[a-z]', password) and get_system_setting('lowercase_character_required'): raise ValidationError( @@ -73,7 +73,7 @@ def get_help_text(self): return gettext('Password must contain at least 1 lowercase letter, a-z.') -class SymbolValidator(object): +class SymbolValidator: def validate(self, password, user=None): contains_special_character = re.findall(r'[(){}\[\]|~!@#$%^&*_\-+=;:\'",\`<>\./?]', password) if not contains_special_character and get_system_setting('special_character_required'): diff --git a/dojo/utils.py b/dojo/utils.py index 3e7c0af47e..e442730fe7 100644 --- a/dojo/utils.py +++ b/dojo/utils.py @@ -251,7 +251,7 @@ def are_endpoints_duplicates(new_finding, to_duplicate_finding): list1 = get_endpoints_as_url(new_finding) list2 = get_endpoints_as_url(to_duplicate_finding) - deduplicationLogger.debug("Starting deduplication by endpoint fields for finding {} with urls {} and finding {} with urls {}".format(new_finding.id, list1, to_duplicate_finding.id, list2)) + deduplicationLogger.debug(f"Starting deduplication by endpoint fields for finding {new_finding.id} with urls {list1} and finding {to_duplicate_finding.id} with urls {list2}") if list1 == [] and list2 == []: return True @@ -1173,7 +1173,7 @@ def opened_in_period(start_date, end_date, **kwargs): return oip -class FileIterWrapper(object): +class FileIterWrapper: def __init__(self, flo, chunk_size=1024**2): self.flo = flo self.chunk_size = chunk_size @@ -1287,23 +1287,21 @@ def handle_uploaded_threat(f, eng): if not os.path.isdir(settings.MEDIA_ROOT + '/threat/'): # Create the folder os.mkdir(settings.MEDIA_ROOT + '/threat/') - with open(settings.MEDIA_ROOT + '/threat/%s%s' % (eng.id, extension), + with open(settings.MEDIA_ROOT + f'/threat/{eng.id}{extension}', 'wb+') as destination: for chunk in f.chunks(): destination.write(chunk) - eng.tmodel_path = settings.MEDIA_ROOT + '/threat/%s%s' % (eng.id, - extension) + eng.tmodel_path = settings.MEDIA_ROOT + f'/threat/{eng.id}{extension}' eng.save() def handle_uploaded_selenium(f, cred): _name, extension = os.path.splitext(f.name) - with open(settings.MEDIA_ROOT + '/selenium/%s%s' % (cred.id, extension), + with open(settings.MEDIA_ROOT + f'/selenium/{cred.id}{extension}', 'wb+') as destination: for chunk in f.chunks(): destination.write(chunk) - cred.selenium_script = settings.MEDIA_ROOT + '/selenium/%s%s' % (cred.id, - extension) + cred.selenium_script = settings.MEDIA_ROOT + f'/selenium/{cred.id}{extension}' cred.save() @@ -1513,8 +1511,7 @@ def calculate_grade(product, *args, **kwargs): low = severity_count['numerical_severity__count'] aeval = Interpreter() aeval(system_settings.product_grade) - grade_product = "grade_product(%s, %s, %s, %s)" % ( - critical, high, medium, low) + grade_product = f"grade_product({critical}, {high}, {medium}, {low})" product.prod_numeric_grade = aeval(grade_product) super(Product, product).save() @@ -1561,7 +1558,7 @@ def get_work_days(start: date, end: date): # Used to display the counts and enabled tabs in the product view -class Product_Tab(): +class Product_Tab: def __init__(self, product, title=None, tab=None): self.product = product self.title = title @@ -1896,7 +1893,7 @@ def _create_notifications(): findings_list.append(n.finding) # producing a "combined" SLA breach notification - title_combined = "SLA alert (%s): product type '%s', product '%s'" % (kind, pt, p) + title_combined = f"SLA alert ({kind}): product type '{pt}', product '{p}'" product = combined_notifications[pt][p][kind][0].finding.test.engagement.product create_notification( event='sla_breach_combined', @@ -1920,20 +1917,14 @@ def _create_notifications(): try: if system_settings.enable_finding_sla: logger.info("About to process findings for SLA notifications.") - logger.debug("Active {}, Verified {}, Has JIRA {}, pre-breach {}, post-breach {}".format( - system_settings.enable_notify_sla_active, - system_settings.enable_notify_sla_active_verified, - system_settings.enable_notify_sla_jira_only, - settings.SLA_NOTIFY_PRE_BREACH, - settings.SLA_NOTIFY_POST_BREACH, - )) + logger.debug(f"Active {system_settings.enable_notify_sla_active}, Verified {system_settings.enable_notify_sla_active_verified}, Has JIRA {system_settings.enable_notify_sla_jira_only}, pre-breach {settings.SLA_NOTIFY_PRE_BREACH}, post-breach {settings.SLA_NOTIFY_POST_BREACH}") query = None if system_settings.enable_notify_sla_active_verified: query = Q(active=True, verified=True, is_mitigated=False, duplicate=False) elif system_settings.enable_notify_sla_active: query = Q(active=True, is_mitigated=False, duplicate=False) - logger.debug("My query: {}".format(query)) + logger.debug(f"My query: {query}") no_jira_findings = {} if system_settings.enable_notify_sla_jira_only: @@ -1966,7 +1957,7 @@ def _create_notifications(): if (sla_age < 0) and (settings.SLA_NOTIFY_POST_BREACH < abs(sla_age)): post_breach_no_notify_count += 1 # Skip finding notification if breached for too long - logger.debug("Finding {} breached the SLA {} days ago. Skipping notifications.".format(finding.id, abs(sla_age))) + logger.debug(f"Finding {finding.id} breached the SLA {abs(sla_age)} days ago. Skipping notifications.") continue do_jira_sla_comment = False @@ -1980,29 +1971,26 @@ def _create_notifications(): jira_count += 1 jira_instance = jira_helper.get_jira_instance(finding) if jira_instance is not None: - logger.debug("JIRA config for finding is {}".format(jira_instance)) + logger.debug(f"JIRA config for finding is {jira_instance}") # global config or product config set, product level takes precedence try: # TODO: see new property from #2649 to then replace, somehow not working with prefetching though. product_jira_sla_comment_enabled = jira_helper.get_jira_project(finding).product_jira_sla_notification except Exception as e: logger.error("The product is not linked to a JIRA configuration! Something is weird here.") - logger.error("Error is: {}".format(e)) + logger.error(f"Error is: {e}") jiraconfig_sla_notification_enabled = jira_instance.global_jira_sla_notification if jiraconfig_sla_notification_enabled or product_jira_sla_comment_enabled: - logger.debug("Global setting {} -- Product setting {}".format( - jiraconfig_sla_notification_enabled, - product_jira_sla_comment_enabled - )) + logger.debug(f"Global setting {jiraconfig_sla_notification_enabled} -- Product setting {product_jira_sla_comment_enabled}") do_jira_sla_comment = True - logger.debug("JIRA issue is {}".format(jira_issue.jira_key)) + logger.debug(f"JIRA issue is {jira_issue.jira_key}") - logger.debug("Finding {} has {} days left to breach SLA.".format(finding.id, sla_age)) + logger.debug(f"Finding {finding.id} has {sla_age} days left to breach SLA.") if (sla_age < 0): post_breach_count += 1 - logger.info("Finding {} has breached by {} days.".format(finding.id, abs(sla_age))) + logger.info(f"Finding {finding.id} has breached by {abs(sla_age)} days.") abs_sla_age = abs(sla_age) if not system_settings.enable_notify_sla_exponential_backoff or abs_sla_age == 1 or (abs_sla_age & (abs_sla_age - 1) == 0): _add_notification(finding, 'breached') @@ -2011,23 +1999,16 @@ def _create_notifications(): # The finding is within the pre-breach period elif (sla_age > 0) and (sla_age <= settings.SLA_NOTIFY_PRE_BREACH): pre_breach_count += 1 - logger.info("Security SLA pre-breach warning for finding ID {}. Days remaining: {}".format(finding.id, sla_age)) + logger.info(f"Security SLA pre-breach warning for finding ID {finding.id}. Days remaining: {sla_age}") _add_notification(finding, 'prebreach') # The finding breaches the SLA today elif (sla_age == 0): at_breach_count += 1 - logger.info("Security SLA breach warning. Finding ID {} breaching today ({})".format(finding.id, sla_age)) + logger.info(f"Security SLA breach warning. Finding ID {finding.id} breaching today ({sla_age})") _add_notification(finding, 'breaching') _create_notifications() - logger.info("SLA run results: Pre-breach: {}, at-breach: {}, post-breach: {}, post-breach-no-notify: {}, with-jira: {}, TOTAL: {}".format( - pre_breach_count, - at_breach_count, - post_breach_count, - post_breach_no_notify_count, - jira_count, - total_count - )) + logger.info(f"SLA run results: Pre-breach: {pre_breach_count}, at-breach: {at_breach_count}, post-breach: {post_breach_count}, post-breach-no-notify: {post_breach_no_notify_count}, with-jira: {jira_count}, TOTAL: {total_count}") except System_Settings.DoesNotExist: logger.info("Findings SLA is not enabled.") @@ -2213,7 +2194,7 @@ def mass_model_updater(model_type, models, function, fields, page_size=1000, ord def to_str_typed(obj): """ for code that handles multiple types of objects, print not only __str__ but prefix the type of the object""" - return '%s: %s' % (type(obj), obj) + return f'{type(obj)}: {obj}' def get_product(obj): @@ -2266,7 +2247,7 @@ def get_enabled_notifications_list(): # Alerts need to enabled by default enabled = ['alert'] for choice in NOTIFICATION_CHOICES: - if get_system_setting('enable_{}_notifications'.format(choice[0])): + if get_system_setting(f'enable_{choice[0]}_notifications'): enabled.append(choice[0]) return enabled @@ -2276,7 +2257,7 @@ def is_finding_groups_enabled(): return get_system_setting("enable_finding_groups") -class async_delete(): +class async_delete: def __init__(self, *args, **kwargs): self.mapping = { 'Product_Type': [ diff --git a/dojo/views.py b/dojo/views.py index 829f749d64..f6df1bdac5 100755 --- a/dojo/views.py +++ b/dojo/views.py @@ -216,8 +216,6 @@ def access_file(request, fid, oid, obj_type, url=False): raise Http404() # If reaching this far, user must have permission to get file file = get_object_or_404(FileUpload, pk=fid) - redirect_url = '{media_root}/{file_name}'.format( - media_root=settings.MEDIA_ROOT, - file_name=file.file.url.lstrip(settings.MEDIA_URL)) + redirect_url = f'{settings.MEDIA_ROOT}/{file.file.url.lstrip(settings.MEDIA_URL)}' print(redirect_url) return FileResponse(open(redirect_url, "rb")) diff --git a/dojo/wsgi.py b/dojo/wsgi.py index 49ae1d27be..83f57ec172 100644 --- a/dojo/wsgi.py +++ b/dojo/wsgi.py @@ -38,7 +38,7 @@ def is_debugger_listening(port): # Checking for RUN_MAIN for those that want to run the app locally with the python interpreter instead of uwsgi if os.environ.get("DD_DEBUG") == "True" and not os.getenv("RUN_MAIN") and is_debugger_listening(debugpy_port) != 0: - logger.info("DD_DEBUG is set to True, setting remote debugging on port {}".format(debugpy_port)) + logger.info(f"DD_DEBUG is set to True, setting remote debugging on port {debugpy_port}") try: import debugpy @@ -49,7 +49,7 @@ def is_debugger_listening(port): }) debugpy.listen(("0.0.0.0", debugpy_port)) if os.environ.get("DD_DEBUG_WAIT_FOR_CLIENT") == "True": - logger.info("Waiting for the debugging client to connect on port {}".format(debugpy_port)) + logger.info(f"Waiting for the debugging client to connect on port {debugpy_port}") debugpy.wait_for_client() print("Debugging client connected, resuming execution") except RuntimeError as e: diff --git a/pyproject.toml b/pyproject.toml index b8965e3168..0ced12b186 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ # Enable the pycodestyle (`E`) and Pyflakes (`F`) rules by default. # Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or # McCabe complexity (`C901`) by default. - lint.select = ["E", "F", "FLY", "TRY004", "TRY2"] + lint.select = ["E", "F", "UP", "FLY", "TRY004", "TRY2"] lint.ignore = ["E501", "E722", "F821"] # Allow autofix for all enabled rules (when `--fix`) is provided. diff --git a/tests/announcement_banner_test.py b/tests/announcement_banner_test.py index 05658982e2..d2b6bd6c53 100644 --- a/tests/announcement_banner_test.py +++ b/tests/announcement_banner_test.py @@ -11,7 +11,7 @@ class AnnouncementBannerTest(BaseTestCase): def __init__(self, method_name, type): - super(AnnouncementBannerTest, self).__init__(method_name) + super().__init__(method_name) self.type = type def test_setup(self): diff --git a/tests/base_test_class.py b/tests/base_test_class.py index 64ce2189c4..a418a5b464 100644 --- a/tests/base_test_class.py +++ b/tests/base_test_class.py @@ -464,7 +464,7 @@ def tearDownDriver(cls): dd_driver.quit() -class WebdriverOnlyNewLogFacade(object): +class WebdriverOnlyNewLogFacade: last_timestamp = 0 diff --git a/tests/notifications_test.py b/tests/notifications_test.py index 4c82f3e3ac..24069547f3 100644 --- a/tests/notifications_test.py +++ b/tests/notifications_test.py @@ -12,14 +12,14 @@ class NotificationTest(BaseTestCase): def __init__(self, method_name, type): - super(NotificationTest, self).__init__(method_name) + super().__init__(method_name) self.type = type def enable_notification(self): driver = self.driver # Navigate to the System Settings driver.get(self.base_url + "system_settings") - mail_control = driver.find_element(By.ID, "id_enable_{}_notifications".format(self.type)) + mail_control = driver.find_element(By.ID, f"id_enable_{self.type}_notifications") if not mail_control.is_selected(): mail_control.click() driver.find_element(By.CSS_SELECTOR, "input.btn.btn-primary").click() @@ -28,7 +28,7 @@ def disable_notification(self): driver = self.driver # Navigate to the System Settings driver.get(self.base_url + "system_settings") - mail_control = driver.find_element(By.ID, "id_enable_{}_notifications".format(self.type)) + mail_control = driver.find_element(By.ID, f"id_enable_{self.type}_notifications") if mail_control.is_selected(): mail_control.click() driver.find_element(By.CSS_SELECTOR, "input.btn.btn-primary").click() @@ -42,7 +42,7 @@ def test_disable_personal_notification(self): self.disable_notification() driver.get(self.base_url + "notifications") try: - driver.find_element(By.XPATH, "//input[@name='product_added' and @value='{}']".format(self.type)) + driver.find_element(By.XPATH, f"//input[@name='product_added' and @value='{self.type}']") assert False except NoSuchElementException: assert True @@ -55,7 +55,7 @@ def test_enable_personal_notification(self): self.enable_notification() driver.get(self.base_url + "notifications") try: - driver.find_element(By.XPATH, "//input[@name='product_added' and @value='{}']".format(self.type)) + driver.find_element(By.XPATH, f"//input[@name='product_added' and @value='{self.type}']") assert True except NoSuchElementException: if self.type == 'msteams': @@ -73,7 +73,7 @@ def test_disable_system_notification(self): self.disable_notification() driver.get(self.base_url + "notifications/system") try: - driver.find_element(By.XPATH, "//input[@name='product_added' and @value='{}']".format(self.type)) + driver.find_element(By.XPATH, f"//input[@name='product_added' and @value='{self.type}']") assert False except NoSuchElementException: assert True @@ -86,7 +86,7 @@ def test_enable_system_notification(self): self.enable_notification() driver.get(self.base_url + "notifications/system") try: - driver.find_element(By.XPATH, "//input[@name='product_added' and @value='{}']".format(self.type)) + driver.find_element(By.XPATH, f"//input[@name='product_added' and @value='{self.type}']") assert True except NoSuchElementException: assert False @@ -100,7 +100,7 @@ def test_disable_template_notification(self): self.disable_notification() driver.get(self.base_url + "notifications/template") try: - driver.find_element(By.XPATH, "//input[@name='product_added' and @value='{}']".format(self.type)) + driver.find_element(By.XPATH, f"//input[@name='product_added' and @value='{self.type}']") assert False except NoSuchElementException: assert True @@ -113,7 +113,7 @@ def test_enable_template_notification(self): self.enable_notification() driver.get(self.base_url + "notifications/template") try: - driver.find_element(By.XPATH, "//input[@name='product_added' and @value='{}']".format(self.type)) + driver.find_element(By.XPATH, f"//input[@name='product_added' and @value='{self.type}']") assert True except NoSuchElementException: if self.type == 'msteams': diff --git a/tests/product_test.py b/tests/product_test.py index b50ce7395b..efe868dde9 100644 --- a/tests/product_test.py +++ b/tests/product_test.py @@ -8,7 +8,7 @@ from notifications_test import NotificationTest -class WaitForPageLoad(object): +class WaitForPageLoad: def __init__(self, browser, timeout): self.browser = browser self.timeout = time.time() + timeout @@ -27,7 +27,7 @@ def __exit__(self, *_): else: time.sleep(0.2) raise Exception( - 'Timeout waiting for {}s'.format(self.timeout) + f'Timeout waiting for {self.timeout}s' ) diff --git a/tests/zap.py b/tests/zap.py index 18a5d7b6f8..a62aa54691 100755 --- a/tests/zap.py +++ b/tests/zap.py @@ -14,12 +14,12 @@ class Main: address = "127.0.0.1" port = 8080 - print(("Checking if ZAP is running, connecting to ZAP on http://" + address + ":" + str(port))) + print("Checking if ZAP is running, connecting to ZAP on http://" + address + ":" + str(port)) s = socket.socket() try: s.connect((address, port)) - except socket.error: + except OSError: print("Error connecting to ZAP, exiting.") sys.exit(0) @@ -35,19 +35,19 @@ class Main: # Defining context name as hostname from URL and creating context using it. contextname = urlparse(targetURL).netloc - print(("Context Name: " + contextname)) + print("Context Name: " + contextname) # Step1: Create context contextid = zap.context.new_context(contextname, apikey) - print(("ContextID: " + contextid)) + print("ContextID: " + contextid) # Step2: Include in the context result = zap.context.include_in_context(contextname, targetURLregex, apikey) - print(("URL regex defined in context: " + result)) + print("URL regex defined in context: " + result) # Step3: Session Management - Default is cookieBasedSessionManagement result = zap.sessionManagement.set_session_management_method(contextid, "cookieBasedSessionManagement", None, apikey) - print(("Session method defined: " + result)) + print("Session method defined: " + result) loginUrl = "http://os.environ['DD_BASE_URL']/login" # loginUrlregex = "\Q" + loginUrl + "\E.*" @@ -58,14 +58,14 @@ class Main: # Wait for passive scanning to complete while (int(zap.pscan.records_to_scan) > 0): - print(('Records to passive scan : ' + zap.pscan.records_to_scan)) + print('Records to passive scan : ' + zap.pscan.records_to_scan) time.sleep(15) print('Passive scanning complete') - print(('Actively Scanning target ' + targetURL)) + print('Actively Scanning target ' + targetURL) ascan_id = zap.ascan.scan(targetURL, None, None, None, None, None, apikey) # Can provide more options for active scan here instead of using None. while (int(zap.ascan.status(ascan_id)) < 100): - print(('Scan progress %: ' + zap.ascan.status(ascan_id))) + print('Scan progress %: ' + zap.ascan.status(ascan_id)) time.sleep(15) print('Scan completed') diff --git a/unittests/dojo_test_case.py b/unittests/dojo_test_case.py index 62c9f46546..97683a4968 100644 --- a/unittests/dojo_test_case.py +++ b/unittests/dojo_test_case.py @@ -27,7 +27,7 @@ def get_unit_tests_path(): return os.path.dirname(os.path.realpath(__file__)) -class DojoTestUtilsMixin(object): +class DojoTestUtilsMixin: def get_test_admin(self, *args, **kwargs): return User.objects.get(username='admin') @@ -377,7 +377,7 @@ def assert_jira_updated_map_changed(self, test_id, updated_map): findings = Test.objects.get(id=test_id).finding_set.all() for finding in findings: logger.debug('finding!') - self.assertNotEquals(jira_helper.get_jira_updated(finding), updated_map[finding.id]) + self.assertNotEqual(jira_helper.get_jira_updated(finding), updated_map[finding.id]) # Toggle epic mapping on jira product def toggle_jira_project_epic_mapping(self, obj, value): diff --git a/unittests/test_adminsite.py b/unittests/test_adminsite.py index bc48a7ea45..eb639f279e 100644 --- a/unittests/test_adminsite.py +++ b/unittests/test_adminsite.py @@ -13,7 +13,7 @@ def test_is_model_defined(self): if subclass.__module__ == 'dojo.models': if not ((subclass.__name__[:9] == "Tagulous_") and (subclass.__name__[-5:] == "_tags")): with self.subTest(type="base", subclass=subclass): - self.assertIn(subclass, admin.site._registry.keys(), "{} is not registered in 'admin.site' in models.py".format(subclass)) + self.assertIn(subclass, admin.site._registry.keys(), f"{subclass} is not registered in 'admin.site' in models.py") else: with self.subTest(type="tag", subclass=subclass): - self.assertIn(subclass, admin.site._registry.keys(), "{} is not registered in 'tagulous.admin' in models.py".format(subclass)) + self.assertIn(subclass, admin.site._registry.keys(), f"{subclass} is not registered in 'tagulous.admin' in models.py") diff --git a/unittests/test_bulk_risk_acceptance_api.py b/unittests/test_bulk_risk_acceptance_api.py index f19ccb9602..9fdf1f90ee 100644 --- a/unittests/test_bulk_risk_acceptance_api.py +++ b/unittests/test_bulk_risk_acceptance_api.py @@ -39,29 +39,29 @@ def setUpTestData(cls): target_start=datetime.datetime(2000, 1, 1, tzinfo=datetime.timezone.utc), target_end=datetime.datetime(2000, 2, 1, tzinfo=datetime.timezone.utc)) def create_finding(test: Test, reporter: User, cve: str) -> Finding: - return Finding(test=test, title='Finding {}'.format(cve), cve=cve, severity='High', verified=True, + return Finding(test=test, title=f'Finding {cve}', cve=cve, severity='High', verified=True, description='Hello world!', mitigation='Delete system32', impact='Everything', reporter=reporter, numerical_severity='S1', static_finding=True, dynamic_finding=False) Finding.objects.bulk_create( - map(lambda i: create_finding(cls.test_a, cls.user, 'CVE-1999-{}'.format(i)), range(50, 150, 3))) + map(lambda i: create_finding(cls.test_a, cls.user, f'CVE-1999-{i}'), range(50, 150, 3))) for finding in Finding.objects.filter(test=cls.test_a): Vulnerability_Id.objects.get_or_create(finding=finding, vulnerability_id=finding.cve) Finding.objects.bulk_create( - map(lambda i: create_finding(cls.test_b, cls.user, 'CVE-1999-{}'.format(i)), range(51, 150, 3))) + map(lambda i: create_finding(cls.test_b, cls.user, f'CVE-1999-{i}'), range(51, 150, 3))) for finding in Finding.objects.filter(test=cls.test_b): Vulnerability_Id.objects.get_or_create(finding=finding, vulnerability_id=finding.cve) Finding.objects.bulk_create( - map(lambda i: create_finding(cls.test_c, cls.user, 'CVE-1999-{}'.format(i)), range(52, 150, 3))) + map(lambda i: create_finding(cls.test_c, cls.user, f'CVE-1999-{i}'), range(52, 150, 3))) for finding in Finding.objects.filter(test=cls.test_c): Vulnerability_Id.objects.get_or_create(finding=finding, vulnerability_id=finding.cve) Finding.objects.bulk_create( - map(lambda i: create_finding(cls.test_d, cls.user, 'CVE-2000-{}'.format(i)), range(50, 150, 3))) + map(lambda i: create_finding(cls.test_d, cls.user, f'CVE-2000-{i}'), range(50, 150, 3))) for finding in Finding.objects.filter(test=cls.test_d): Vulnerability_Id.objects.get_or_create(finding=finding, vulnerability_id=finding.cve) Finding.objects.bulk_create( - map(lambda i: create_finding(cls.test_e, cls.user, 'CVE-1999-{}'.format(i)), range(50, 150, 3))) + map(lambda i: create_finding(cls.test_e, cls.user, f'CVE-1999-{i}'), range(50, 150, 3))) for finding in Finding.objects.filter(test=cls.test_e): Vulnerability_Id.objects.get_or_create(finding=finding, vulnerability_id=finding.cve) @@ -70,7 +70,7 @@ def setUp(self) -> None: self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.token.key) def test_test_accept_risks(self): - accepted_risks = [{'vulnerability_id': 'CVE-1999-{}'.format(i), 'justification': 'Demonstration purposes', + accepted_risks = [{'vulnerability_id': f'CVE-1999-{i}', 'justification': 'Demonstration purposes', 'accepted_by': 'King of the Internet'} for i in range(100, 150)] result = self.client.post(reverse('test-accept-risks', kwargs={'pk': self.test_a.id}), data=accepted_risks, format='json') @@ -83,7 +83,7 @@ def test_test_accept_risks(self): self.assertEqual(self.engagement_2a.risk_acceptance.count(), 0) def test_engagement_accept_risks(self): - accepted_risks = [{'vulnerability_id': 'CVE-1999-{}'.format(i), 'justification': 'Demonstration purposes', + accepted_risks = [{'vulnerability_id': f'CVE-1999-{i}', 'justification': 'Demonstration purposes', 'accepted_by': 'King of the Internet'} for i in range(100, 150)] result = self.client.post(reverse('engagement-accept-risks', kwargs={'pk': self.engagement.id}), data=accepted_risks, format='json') @@ -94,7 +94,7 @@ def test_engagement_accept_risks(self): self.assertEqual(self.engagement_2a.unaccepted_open_findings.count(), 34) def test_finding_accept_risks(self): - accepted_risks = [{'vulnerability_id': 'CVE-1999-{}'.format(i), 'justification': 'Demonstration purposes', + accepted_risks = [{'vulnerability_id': f'CVE-1999-{i}', 'justification': 'Demonstration purposes', 'accepted_by': 'King of the Internet'} for i in range(60, 140)] result = self.client.post(reverse('finding-accept-risks'), data=accepted_risks, format='json') self.assertEqual(len(result.json()), 106) diff --git a/unittests/test_deduplication_logic.py b/unittests/test_deduplication_logic.py index 86d05f67c7..5b7ae6bdd3 100644 --- a/unittests/test_deduplication_logic.py +++ b/unittests/test_deduplication_logic.py @@ -1158,12 +1158,12 @@ def log_findings(self, findings): else: logger.debug('\t\t' + 'findings:') for finding in findings: - logger.debug('\t\t\t{:4.4}'.format(str(finding.id)) + ': "' + '{:20.20}'.format(finding.title) + '": ' + '{:5.5}'.format(finding.severity) + ': act: ' + '{:5.5}'.format(str(finding.active)) - + ': ver: ' + '{:5.5}'.format(str(finding.verified)) + ': mit: ' + '{:5.5}'.format(str(finding.is_mitigated)) - + ': dup: ' + '{:5.5}'.format(str(finding.duplicate)) + ': dup_id: ' - + ('{:4.4}'.format(str(finding.duplicate_finding.id)) if finding.duplicate_finding else 'None') + ': hash_code: ' + str(finding.hash_code) + logger.debug(f'\t\t\t{str(finding.id):4.4}' + ': "' + f'{finding.title:20.20}' + '": ' + f'{finding.severity:5.5}' + ': act: ' + f'{str(finding.active):5.5}' + + ': ver: ' + f'{str(finding.verified):5.5}' + ': mit: ' + f'{str(finding.is_mitigated):5.5}' + + ': dup: ' + f'{str(finding.duplicate):5.5}' + ': dup_id: ' + + (f'{str(finding.duplicate_finding.id):4.4}' if finding.duplicate_finding else 'None') + ': hash_code: ' + str(finding.hash_code) + ': eps: ' + str(finding.endpoints.count()) + ": notes: " + str([n.id for n in finding.notes.all()]) - + ': uid: ' + '{:5.5}'.format(str(finding.unique_id_from_tool)) + (' fp' if finding.false_p else '') + + ': uid: ' + f'{str(finding.unique_id_from_tool):5.5}' + (' fp' if finding.false_p else '') ) logger.debug('\t\tendpoints') diff --git a/unittests/test_endpoint_meta_import.py b/unittests/test_endpoint_meta_import.py index e0ec437c42..23981ab0b7 100644 --- a/unittests/test_endpoint_meta_import.py +++ b/unittests/test_endpoint_meta_import.py @@ -12,7 +12,7 @@ # test methods to be used both by API Test and UI Test -class EndpointMetaImportMixin(object): +class EndpointMetaImportMixin: def __init__(self, *args, **kwargs): self.meta_import_full = 'endpoint_meta_import/full_endpoint_meta_import.csv' self.meta_import_no_hostname = 'endpoint_meta_import/no_hostname_endpoint_meta_import.csv' diff --git a/unittests/test_endpoint_model.py b/unittests/test_endpoint_model.py index 71535e0732..634130bb3a 100644 --- a/unittests/test_endpoint_model.py +++ b/unittests/test_endpoint_model.py @@ -37,7 +37,7 @@ def test_truncates_large_attributes(self): path = "foo" * 1000 query = "bar" * 1000 fragment = "baz" * 1000 - endpoint = Endpoint.from_uri('http://alice@foo.bar:8080/{}?{}#{}'.format(path, query, fragment)) + endpoint = Endpoint.from_uri(f'http://alice@foo.bar:8080/{path}?{query}#{fragment}') self.assertEqual(len(endpoint.path), 500) self.assertEqual(len(endpoint.query), 1000) self.assertEqual(len(endpoint.fragment), 500) diff --git a/unittests/test_false_positive_history_logic.py b/unittests/test_false_positive_history_logic.py index 853737850f..808af00f74 100644 --- a/unittests/test_false_positive_history_logic.py +++ b/unittests/test_false_positive_history_logic.py @@ -1675,12 +1675,12 @@ def log_findings(self, findings): else: logger.debug('\t\t' + 'findings:') for finding in findings: - logger.debug('\t\t\t{:4.4}'.format(str(finding.id)) + ': "' + '{:20.20}'.format(finding.title) + '": ' + '{:5.5}'.format(finding.severity) + ': act: ' + '{:5.5}'.format(str(finding.active)) - + ': ver: ' + '{:5.5}'.format(str(finding.verified)) + ': mit: ' + '{:5.5}'.format(str(finding.is_mitigated)) - + ': dup: ' + '{:5.5}'.format(str(finding.duplicate)) + ': dup_id: ' - + ('{:4.4}'.format(str(finding.duplicate_finding.id)) if finding.duplicate_finding else 'None') + ': hash_code: ' + str(finding.hash_code) + logger.debug(f'\t\t\t{str(finding.id):4.4}' + ': "' + f'{finding.title:20.20}' + '": ' + f'{finding.severity:5.5}' + ': act: ' + f'{str(finding.active):5.5}' + + ': ver: ' + f'{str(finding.verified):5.5}' + ': mit: ' + f'{str(finding.is_mitigated):5.5}' + + ': dup: ' + f'{str(finding.duplicate):5.5}' + ': dup_id: ' + + (f'{str(finding.duplicate_finding.id):4.4}' if finding.duplicate_finding else 'None') + ': hash_code: ' + str(finding.hash_code) + ': eps: ' + str(finding.endpoints.count()) + ": notes: " + str([n.id for n in finding.notes.all()]) - + ': uid: ' + '{:5.5}'.format(str(finding.unique_id_from_tool)) + (' fp' if finding.false_p else '') + + ': uid: ' + f'{str(finding.unique_id_from_tool):5.5}' + (' fp' if finding.false_p else '') ) logger.debug('\t\tendpoints') @@ -1734,7 +1734,7 @@ def copy_and_reset_product(self, id): org = Product.objects.get(id=id) new = org new.pk = None - new.name = '%s (Copy %s)' % (org.name, datetime.now()) + new.name = f'{org.name} (Copy {datetime.now()})' # return unsaved new product and reloaded existing product return new, Product.objects.get(id=id) @@ -1746,7 +1746,7 @@ def change_finding_unique_id(self, finding): return finding def change_finding_title(self, finding): - finding.title = '%s (Copy %s)' % (finding.title, datetime.now()) + finding.title = f'{finding.title} (Copy {datetime.now()})' return finding def change_finding_severity(self, finding): diff --git a/unittests/test_import_reimport.py b/unittests/test_import_reimport.py index 535bc488d1..79524465f4 100644 --- a/unittests/test_import_reimport.py +++ b/unittests/test_import_reimport.py @@ -50,7 +50,7 @@ # 5 active sev medium # test methods to be used both by API Test and UI Test -class ImportReimportMixin(object): +class ImportReimportMixin: def __init__(self, *args, **kwargs): self.scans_path = '/scans/' diff --git a/unittests/test_importers_importer.py b/unittests/test_importers_importer.py index 096539b292..a51b21e456 100644 --- a/unittests/test_importers_importer.py +++ b/unittests/test_importers_importer.py @@ -297,7 +297,7 @@ def test_import_with_invalid_parameters(self): Product_Type.objects.create(name=another_product_type_name) import0 = self.import_scan_with_params(NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, engagement=None, product_type_name=another_product_type_name, product_name=PRODUCT_NAME_DEFAULT, engagement_name='valentijn', expected_http_status_code=400) - self.assertEqual(import0, ["Product '%s' doesn't exist in Product_Type '%s'" % (PRODUCT_NAME_DEFAULT, another_product_type_name)]) + self.assertEqual(import0, [f"Product '{PRODUCT_NAME_DEFAULT}' doesn't exist in Product_Type '{another_product_type_name}'"]) with self.subTest('invalid engagement'): import0 = self.import_scan_with_params(NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, @@ -505,7 +505,7 @@ def test_reimport_with_invalid_parameters(self): import0 = self.reimport_scan_with_params(None, NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, engagement=None, product_type_name=another_product_type_name, product_name=PRODUCT_NAME_DEFAULT, engagement_name='valentijn', expected_http_status_code=400) - self.assertEqual(import0, ["Product '%s' doesn't exist in Product_Type '%s'" % (PRODUCT_NAME_DEFAULT, another_product_type_name)]) + self.assertEqual(import0, [f"Product '{PRODUCT_NAME_DEFAULT}' doesn't exist in Product_Type '{another_product_type_name}'"]) with self.subTest('invalid engagement'): import0 = self.reimport_scan_with_params(None, NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, diff --git a/unittests/test_jira_config_engagement.py b/unittests/test_jira_config_engagement.py index 9506a264f6..0fede4ca68 100644 --- a/unittests/test_jira_config_engagement.py +++ b/unittests/test_jira_config_engagement.py @@ -11,7 +11,7 @@ logger = logging.getLogger(__name__) -class JIRAConfigEngagementBase(object): +class JIRAConfigEngagementBase: def get_new_engagement_with_jira_project_data(self): return { 'name': 'new engagement', diff --git a/unittests/test_jira_import_and_pushing_api.py b/unittests/test_jira_import_and_pushing_api.py index dd50794c0a..76593c1967 100644 --- a/unittests/test_jira_import_and_pushing_api.py +++ b/unittests/test_jira_import_and_pushing_api.py @@ -44,7 +44,7 @@ def assert_cassette_played(self): self.assertTrue(self.cassette.all_played) def _get_vcr(self, **kwargs): - my_vcr = super(JIRAImportAndPushTestApi, self)._get_vcr(**kwargs) + my_vcr = super()._get_vcr(**kwargs) my_vcr.record_mode = 'once' my_vcr.path_transformer = VCR.ensure_suffix('.yaml') my_vcr.filter_headers = ['Authorization', 'X-Atlassian-Token'] diff --git a/unittests/test_parsers.py b/unittests/test_parsers.py index ac2b75730c..afd849aa7c 100644 --- a/unittests/test_parsers.py +++ b/unittests/test_parsers.py @@ -79,7 +79,7 @@ def test_file_existence(self): if file.is_file() and file.name != '__pycache__' and file.name != "__init__.py": f = os.path.join(basedir, 'dojo', 'tools', parser_dir.name, file.name) read_true = False - for line in open(f, "r").readlines(): + for line in open(f).readlines(): if read_true is True: if ('"utf-8"' in str(line) or "'utf-8'" in str(line) or '"utf-8-sig"' in str(line) or "'utf-8-sig'" in str(line)) and i <= 4: read_true = False diff --git a/unittests/test_rest_framework.py b/unittests/test_rest_framework.py index 1120419c89..377cf1dcbf 100644 --- a/unittests/test_rest_framework.py +++ b/unittests/test_rest_framework.py @@ -111,7 +111,7 @@ def format_url(path): return f"{BASE_API_URL}{path}" -class SchemaChecker(): +class SchemaChecker: def __init__(self, components): self._prefix = [] self._has_failed = False @@ -272,7 +272,7 @@ class TestType(Enum): CONFIGURATION_PERMISSIONS = 3 -class BaseClass(): +class BaseClass: class RESTEndpointTest(DojoAPITestCase): def __init__(self, *args, **kwargs): DojoAPITestCase.__init__(self, *args, **kwargs) @@ -1043,7 +1043,7 @@ def test_request_response_post_and_download(self): length = FileUpload.objects.count() payload = { "title": level, - "file": open(f'{str(self.path)}/scans/acunetix/one_finding.xml', 'r') + "file": open(f'{str(self.path)}/scans/acunetix/one_finding.xml') } response = self.client.post(f'/api/v2/{level}/files/', payload) self.assertEqual(201, response.status_code, response.data) @@ -1051,7 +1051,7 @@ def test_request_response_post_and_download(self): # Save the ID of the newly created file object self.url_levels[level] = response.data.get('id') # Test the download - with open(f'{str(self.path)}/scans/acunetix/one_finding.xml', 'r') as file: + with open(f'{str(self.path)}/scans/acunetix/one_finding.xml') as file: file_data = file.read() for level, file_id in self.url_levels.items(): response = self.client.get(f'/api/v2/{level}/files/download/{file_id}/') diff --git a/unittests/test_utils.py b/unittests/test_utils.py index 30b4721621..3cad8f7e00 100644 --- a/unittests/test_utils.py +++ b/unittests/test_utils.py @@ -162,7 +162,7 @@ def test_user_post_save_email_pattern_does_not_match(self, mock_notifications, m save_mock_member.save.assert_not_called() -class assertNumOfModelsCreated(): +class assertNumOfModelsCreated: def __init__(self, test_case, queryset, num): self.test_case = test_case self.queryset = queryset diff --git a/unittests/tools/test_asff_parser.py b/unittests/tools/test_asff_parser.py index bcbe7bb56b..df8c38cd35 100644 --- a/unittests/tools/test_asff_parser.py +++ b/unittests/tools/test_asff_parser.py @@ -12,7 +12,7 @@ def sample_path(file_name): class TestAsffParser(DojoTestCase): def load_sample_json(self, file_name): - with open(sample_path(file_name), "r") as file: + with open(sample_path(file_name)) as file: return json.load(file) def common_check_finding(self, finding, data, index, guarddutydate=False): @@ -35,7 +35,7 @@ def common_check_finding(self, finding, data, index, guarddutydate=False): def test_asff_one_vuln(self): data = self.load_sample_json("one_vuln.json") - with open(sample_path("one_vuln.json"), "r") as file: + with open(sample_path("one_vuln.json")) as file: parser = AsffParser() findings = parser.get_findings(file, Test()) self.assertEqual(1, len(findings)) @@ -43,7 +43,7 @@ def test_asff_one_vuln(self): def test_asff_many_vulns(self): data = self.load_sample_json("many_vulns.json") - with open(sample_path("many_vulns.json"), "r") as file: + with open(sample_path("many_vulns.json")) as file: parser = AsffParser() findings = parser.get_findings(file, Test()) self.assertEqual(len(findings), 5) @@ -52,7 +52,7 @@ def test_asff_many_vulns(self): def test_asff_guardduty(self): data = self.load_sample_json("guardduty/Unusual Behaviors-User-Persistence IAMUser-NetworkPermissions.json") - with open(sample_path("guardduty/Unusual Behaviors-User-Persistence IAMUser-NetworkPermissions.json"), "r") as file: + with open(sample_path("guardduty/Unusual Behaviors-User-Persistence IAMUser-NetworkPermissions.json")) as file: parser = AsffParser() findings = parser.get_findings(file, Test()) self.assertEqual(len(findings), 1) diff --git a/unittests/tools/test_dependency_check_parser.py b/unittests/tools/test_dependency_check_parser.py index 7963acdcd7..0d22d7e1b0 100644 --- a/unittests/tools/test_dependency_check_parser.py +++ b/unittests/tools/test_dependency_check_parser.py @@ -8,7 +8,7 @@ from ..dojo_test_case import DojoTestCase -class TestFile(object): +class TestFile: def read(self): return self.content diff --git a/unittests/tools/test_generic_parser.py b/unittests/tools/test_generic_parser.py index de4b8252ec..fd10079b07 100644 --- a/unittests/tools/test_generic_parser.py +++ b/unittests/tools/test_generic_parser.py @@ -4,7 +4,7 @@ from dojo.tools.generic.parser import GenericParser -class TestFile(object): +class TestFile: def read(self): return self.content diff --git a/unittests/tools/test_tenable_parser.py b/unittests/tools/test_tenable_parser.py index b79c48c3d7..7ad5485851 100644 --- a/unittests/tools/test_tenable_parser.py +++ b/unittests/tools/test_tenable_parser.py @@ -109,7 +109,7 @@ def test_parse_some_findings_csv_bytes_nessus_legacy(self): for finding in findings: for endpoint in finding.unsaved_endpoints: endpoint.clean() - testfile = open(path.join(path.dirname(__file__), "../scans/tenable/nessus/nessus_many_vuln2-all.csv"), "rt") + testfile = open(path.join(path.dirname(__file__), "../scans/tenable/nessus/nessus_many_vuln2-all.csv")) parser = TenableParser() findings = parser.get_findings(testfile, self.create_test()) for finding in findings: diff --git a/unittests/tools/test_vcg_parser.py b/unittests/tools/test_vcg_parser.py index 5b030be780..7e7abf55b3 100644 --- a/unittests/tools/test_vcg_parser.py +++ b/unittests/tools/test_vcg_parser.py @@ -10,7 +10,7 @@ from dojo.tools.vcg.parser import VCGXmlParser -class TestFile(object): +class TestFile: def read(self): return self.content From 5d65e50de5704cb8901143a1452764a5548eb923 Mon Sep 17 00:00:00 2001 From: DefectDojo release bot Date: Mon, 8 Apr 2024 18:05:01 +0000 Subject: [PATCH 008/138] Update versions in application files --- components/package.json | 2 +- dojo/__init__.py | 2 +- helm/defectdojo/Chart.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/package.json b/components/package.json index baf3a55892..41e9d22009 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "defectdojo", - "version": "2.33.1", + "version": "2.34.0-dev", "license" : "BSD-3-Clause", "private": true, "dependencies": { diff --git a/dojo/__init__.py b/dojo/__init__.py index af78621888..4758913441 100644 --- a/dojo/__init__.py +++ b/dojo/__init__.py @@ -4,6 +4,6 @@ # Django starts so that shared_task will use this app. from .celery import app as celery_app # noqa: F401 -__version__ = '2.33.1' +__version__ = '2.34.0-dev' __url__ = 'https://github.com/DefectDojo/django-DefectDojo' __docs__ = 'https://documentation.defectdojo.com' diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index d7d9428c7a..ae5a01ffa4 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 -appVersion: "2.33.1" +appVersion: "2.34.0-dev" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.119 +version: 1.6.120-dev icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap From bf60b544c737a2bb0b1c5fc44db877093dec4c56 Mon Sep 17 00:00:00 2001 From: DefectDojo Date: Mon, 8 Apr 2024 18:06:27 +0000 Subject: [PATCH 009/138] Update helm lock file Signed-off-by: DefectDojo --- helm/defectdojo/Chart.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/helm/defectdojo/Chart.lock b/helm/defectdojo/Chart.lock index 04c171e2c5..55ee782665 100644 --- a/helm/defectdojo/Chart.lock +++ b/helm/defectdojo/Chart.lock @@ -4,7 +4,7 @@ dependencies: version: 9.19.1 - name: postgresql repository: https://charts.bitnami.com/bitnami - version: 15.2.0 + version: 15.2.4 - name: postgresql-ha repository: https://charts.bitnami.com/bitnami version: 9.4.11 @@ -14,5 +14,5 @@ dependencies: - name: redis repository: https://charts.bitnami.com/bitnami version: 19.0.2 -digest: sha256:e4fa2641d160547748ba41a729ea67574601003b8f5da322832d88bd18acb6bd -generated: "2024-04-01T09:55:40.430476431Z" +digest: sha256:9a6157ef79354795f47ebea124f48c044c5d816a9424dbb17d555828734bb014 +generated: "2024-04-08T18:06:18.688462714Z" From 2060466098fc67d16a07814e513820d081d4015a Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Tue, 9 Apr 2024 01:48:39 +0200 Subject: [PATCH 010/138] nancy: migrate from cve to unsaved_vulnerability_ids (#9834) --- dojo/tools/nancy/parser.py | 1 - unittests/tools/test_nancy_parser.py | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/dojo/tools/nancy/parser.py b/dojo/tools/nancy/parser.py index 2c3111cb9f..5b79c6c1e5 100644 --- a/dojo/tools/nancy/parser.py +++ b/dojo/tools/nancy/parser.py @@ -63,7 +63,6 @@ def get_items(self, vulnerable, test): static_finding=True, dynamic_finding=False, vuln_id_from_tool=associated_vuln["Id"], - cve=associated_vuln['Cve'], references="\n".join(references), ) diff --git a/unittests/tools/test_nancy_parser.py b/unittests/tools/test_nancy_parser.py index 55a8f36329..fdb7e77c28 100644 --- a/unittests/tools/test_nancy_parser.py +++ b/unittests/tools/test_nancy_parser.py @@ -23,6 +23,8 @@ def test_nancy_parser_with_one_vuln_has_one_findings(self): self.assertEqual('Info', finding.severity) self.assertIsNotNone(finding.description) self.assertGreater(len(finding.description), 0) + self.assertEqual(None, finding.cve) + self.assertEqual("CVE-2017-1000070", finding.unsaved_vulnerability_ids[0]) self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N", finding.cvssv3) def test_nancy_plus_parser_with_many_vuln_has_many_findings(self): From e668b2ed5b6adef1ed19109e83d720270d2ca0ec Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Tue, 9 Apr 2024 01:50:47 +0200 Subject: [PATCH 011/138] yarn_audit: migrate from cve to unsaved_vulnerability_ids (#9833) --- dojo/tools/yarn_audit/parser.py | 5 ++++- unittests/tools/test_yarn_audit_parser.py | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/dojo/tools/yarn_audit/parser.py b/dojo/tools/yarn_audit/parser.py index a4feda6c46..b1670a0a7b 100644 --- a/dojo/tools/yarn_audit/parser.py +++ b/dojo/tools/yarn_audit/parser.py @@ -85,7 +85,6 @@ def get_items_auditci(self, tree, test): # https://github.com/DefectDojo/django test=test, severity=self.severitytranslator(severity=tree.get("advisories").get(element).get("severity")), description=description, - cve=tree.get("advisories").get(element).get("cves")[0], mitigation=tree.get("advisories").get(element).get("recommendation"), references=url + "\n" + references, component_name=tree.get("advisories").get(element).get("module_name"), @@ -98,6 +97,10 @@ def get_items_auditci(self, tree, test): # https://github.com/DefectDojo/django static_finding=True, dynamic_finding=False, ) + if tree.get("advisories").get(element).get("cves") != []: + dojo_finding.unsaved_vulnerability_ids = list() + for cve in tree.get("advisories").get(element).get("cves"): + dojo_finding.unsaved_vulnerability_ids.append(cve) if tree.get("advisories").get(element).get("cwe") != []: dojo_finding.cwe = tree.get("advisories").get(element).get("cwe")[0].strip("CWE-") items.append(dojo_finding) diff --git a/unittests/tools/test_yarn_audit_parser.py b/unittests/tools/test_yarn_audit_parser.py index d887225946..77177d3f3a 100644 --- a/unittests/tools/test_yarn_audit_parser.py +++ b/unittests/tools/test_yarn_audit_parser.py @@ -64,6 +64,8 @@ def test_yarn_audit_parser_with_multiple_cwes_per_finding_list(self): self.assertEqual(2, len(findings)) self.assertEqual(findings[0].cwe, 918) self.assertEqual(findings[1].cwe, 1035) + self.assertEqual(findings[1].cve, None) + self.assertEqual(findings[1].unsaved_vulnerability_ids[0], "CVE-2021-3807") def test_yarn_audit_parser_empty_with_error(self): with self.assertRaises(ValueError) as context: @@ -83,3 +85,5 @@ def test_yarn_audit_parser_issue_6495(self): testfile.close() self.assertEqual(3, len(findings)) self.assertEqual(findings[0].cwe, "1321") + self.assertEqual(findings[1].unsaved_vulnerability_ids[0], "CVE-2022-25851") + self.assertEqual(findings[1].cve, None) From 0a8eb435bcda1041bfda3e22c51aaca37b739635 Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Tue, 9 Apr 2024 01:51:12 +0200 Subject: [PATCH 012/138] osv_scanner: migrate from cve to unsaved_vulnerability_ids (#9832) --- dojo/tools/osv_scanner/parser.py | 6 ++++-- unittests/tools/test_osv_scanner_parser.py | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/dojo/tools/osv_scanner/parser.py b/dojo/tools/osv_scanner/parser.py index 9afbefb02d..0e8608a2fe 100644 --- a/dojo/tools/osv_scanner/parser.py +++ b/dojo/tools/osv_scanner/parser.py @@ -37,7 +37,7 @@ def get_findings(self, file, test): package_version = package["package"]["version"] package_ecosystem = package["package"]["ecosystem"] for vulnerability in package["vulnerabilities"]: - vulnerabilityid = vulnerability["id"] + vulnerabilityid = vulnerability.get("id", "") vulnerabilitysummary = vulnerability.get("summary", "") vulnerabilitydetails = vulnerability["details"] vulnerabilitypackagepurl = vulnerability["affected"][0].get("package", "") @@ -65,9 +65,11 @@ def get_findings(self, file, test): component_name=package_name, component_version=package_version, cwe=cwe, - cve=vulnerabilityid, file_path=source_path, references=reference, ) + if vulnerabilityid != "": + finding.unsaved_vulnerability_ids = list() + finding.unsaved_vulnerability_ids.append(vulnerabilityid) findings.append(finding) return findings diff --git a/unittests/tools/test_osv_scanner_parser.py b/unittests/tools/test_osv_scanner_parser.py index af7dac0050..bde834cc17 100644 --- a/unittests/tools/test_osv_scanner_parser.py +++ b/unittests/tools/test_osv_scanner_parser.py @@ -19,7 +19,8 @@ def test_some_findings(self): finding = findings[0] self.assertEqual(finding.cwe, "CWE-506") self.assertEqual(finding.title, "MAL-2023-1035_flot-axis") - self.assertEqual(finding.cve, "MAL-2023-1035") + self.assertEqual(finding.cve, None) + self.assertEqual(finding.unsaved_vulnerability_ids[0], "MAL-2023-1035") self.assertEqual(finding.severity, "Low") def test_many_findings(self): @@ -29,7 +30,8 @@ def test_many_findings(self): self.assertEqual(66, len(findings)) finding = findings[0] self.assertEqual(finding.title, "GHSA-25mq-v84q-4j7r_guzzlehttp/guzzle") - self.assertEqual(finding.cve, "GHSA-25mq-v84q-4j7r") + self.assertEqual(finding.cve, None) + self.assertEqual(finding.unsaved_vulnerability_ids[0], "GHSA-25mq-v84q-4j7r") self.assertEqual(finding.severity, "High") finding = findings[3] self.assertEqual(finding.static_finding, True) From c7ce7649332e02e3dae3378d3c1333a99c922a84 Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Tue, 9 Apr 2024 01:52:43 +0200 Subject: [PATCH 013/138] rework intsights to split csv and json (#9855) --- dojo/tools/intsights/csv_handler.py | 95 ++++++++++++++++ dojo/tools/intsights/json_handler.py | 51 +++++++++ dojo/tools/intsights/parser.py | 155 +-------------------------- 3 files changed, 150 insertions(+), 151 deletions(-) create mode 100644 dojo/tools/intsights/csv_handler.py create mode 100644 dojo/tools/intsights/json_handler.py diff --git a/dojo/tools/intsights/csv_handler.py b/dojo/tools/intsights/csv_handler.py new file mode 100644 index 0000000000..3369d4f010 --- /dev/null +++ b/dojo/tools/intsights/csv_handler.py @@ -0,0 +1,95 @@ +import collections +import csv +import io + + +class IntSightsCSVParser(object): + def _parse_csv(self, csv_file) -> [dict]: + """ + + Parses entries from the CSV file object into a list of alerts + Args: + csv_file: The JSON file object to parse + Returns: + A list of alerts [dict()] + + """ + default_keys = [ + "Alert ID", + "Title", + "Description", + "Severity", + "Type", + "Source Date (UTC)", + "Report Date (UTC)", + "Network Type", + "Source URL", + "Source Name", + "Assets", + "Tags", + "Assignees", + "Remediation", + "Status", + "Closed Reason", + "Additional Info", + "Rating", + "Alert Link" + ] + + # These keys require a value. If one ore more of the values is null or empty, the entire Alert is ignored. + # This is to avoid attempting to import incomplete Findings. + required_keys = ["alert_id", "title", "severity", "status"] + + alerts = [] + invalid_alerts = [] + + content = csv_file.read() + if isinstance(content, bytes): + content = content.decode("utf-8") + csv_reader = csv.DictReader( + io.StringIO(content), delimiter=",", quotechar='"' + ) + + # Don't bother parsing if the keys don't match exactly what's expected + if collections.Counter(default_keys) == collections.Counter( + csv_reader.fieldnames + ): + default_valud = "None provided" + for alert in csv_reader: + alert["alert_id"] = alert.pop("Alert ID") + alert["title"] = alert.pop("Title") + alert["description"] = alert.pop("Description") + alert["severity"] = alert.pop("Severity") + alert["type"] = alert.pop( + "Type", + ) + alert["source_date"] = alert.pop( + "Source Date (UTC)", default_valud + ) + alert["report_date"] = alert.pop( + "Report Date (UTC)", default_valud + ) + alert["network_type"] = alert.pop( + "Network Type", default_valud + ) + alert["source_url"] = alert.pop("Source URL", default_valud) + alert["assets"] = alert.pop("Assets", default_valud) + alert["tags"] = alert.pop("Tags", default_valud) + alert["status"] = alert.pop("Status", default_valud) + alert["alert_link"] = alert.pop("Alert Link") + alert.pop("Assignees") + alert.pop("Remediation") + alert.pop("Closed Reason") + alert.pop("Rating") + for key in required_keys: + if not alert[key]: + invalid_alerts.append(alert) + + if alert not in invalid_alerts: + alerts.append(alert) + else: + self._LOGGER.error( + "The CSV file has one or more missing or unexpected header values" + ) + + return alerts diff --git a/dojo/tools/intsights/json_handler.py b/dojo/tools/intsights/json_handler.py new file mode 100644 index 0000000000..d3d2faae6d --- /dev/null +++ b/dojo/tools/intsights/json_handler.py @@ -0,0 +1,51 @@ +import json + + +class IntSightsJSONParser(object): + def _parse_json(self, json_file) -> [dict]: + """ + Parses entries from the JSON object into a list of alerts + Args: + json_file: The JSON file object to parse + Returns: + A list of alerts [dict()] + """ + alerts = [] + + original_alerts = json.load(json_file) + for original_alert in original_alerts.get("Alerts", []): + alert = dict() + alert["alert_id"] = original_alert["_id"] + alert["title"] = original_alert["Details"]["Title"] + alert["description"] = original_alert["Details"]["Description"] + alert["severity"] = original_alert["Details"]["Severity"] + alert["type"] = original_alert["Details"]["Type"] + alert["source_date"] = original_alert["Details"]["Source"].get( + "Date", "None provided" + ) + alert["report_date"] = original_alert.get( + "FoundDate", "None provided" + ) + alert["network_type"] = original_alert["Details"]["Source"].get( + "NetworkType" + ) + alert["source_url"] = original_alert["Details"]["Source"].get( + "URL" + ) + alert["assets"] = ",".join( + [item.get("Value") for item in original_alert["Assets"]] + ) + alert["tags"] = original_alert["Details"].get("Tags") + alert["status"] = ( + "Closed" + if original_alert["Closed"].get("IsClosed") + else "Open" + ) + alert["alert_link"] = ( + f"https://dashboard.intsights.com/#/threat-command/alerts?search=" + f'{original_alert["_id"]}' + ) + + alerts.append(alert) + + return alerts diff --git a/dojo/tools/intsights/parser.py b/dojo/tools/intsights/parser.py index 7b69598c80..094dc4d795 100644 --- a/dojo/tools/intsights/parser.py +++ b/dojo/tools/intsights/parser.py @@ -1,10 +1,7 @@ -import collections -import csv -import io -import json import logging - from dojo.models import Finding +from dojo.tools.intsights.csv_handler import IntSightsCSVParser +from dojo.tools.intsights.json_handler import IntSightsJSONParser class IntSightsParser: @@ -23,144 +20,6 @@ def get_label_for_scan_types(self, scan_type): def get_description_for_scan_types(self, scan_type): return "IntSights report file can be imported in JSON format." - def _parse_json(self, json_file) -> [dict]: - """ - Parses entries from the JSON object into a list of alerts - Args: - json_file: The JSON file object to parse - Returns: - A list of alerts [dict()] - """ - alerts = [] - - original_alerts = json.load(json_file) - for original_alert in original_alerts.get("Alerts", []): - alert = dict() - alert["alert_id"] = original_alert["_id"] - alert["title"] = original_alert["Details"]["Title"] - alert["description"] = original_alert["Details"]["Description"] - alert["severity"] = original_alert["Details"]["Severity"] - alert["type"] = original_alert["Details"]["Type"] - alert["source_date"] = original_alert["Details"]["Source"].get( - "Date", "None provided" - ) - alert["report_date"] = original_alert.get( - "FoundDate", "None provided" - ) - alert["network_type"] = original_alert["Details"]["Source"].get( - "NetworkType" - ) - alert["source_url"] = original_alert["Details"]["Source"].get( - "URL" - ) - alert["assets"] = ",".join( - [item.get("Value") for item in original_alert["Assets"]] - ) - alert["tags"] = original_alert["Details"].get("Tags") - alert["status"] = ( - "Closed" - if original_alert["Closed"].get("IsClosed") - else "Open" - ) - alert["alert_link"] = ( - f"https://dashboard.intsights.com/#/threat-command/alerts?search=" - f'{original_alert["_id"]}' - ) - - alerts.append(alert) - - return alerts - - def _parse_csv(self, csv_file) -> [dict]: - """ - - Parses entries from the CSV file object into a list of alerts - Args: - csv_file: The JSON file object to parse - Returns: - A list of alerts [dict()] - - """ - default_keys = [ - "Alert ID", - "Title", - "Description", - "Severity", - "Type", - "Source Date (UTC)", - "Report Date (UTC)", - "Network Type", - "Source URL", - "Source Name", - "Assets", - "Tags", - "Assignees", - "Remediation", - "Status", - "Closed Reason", - "Additional Info", - "Rating", - "Alert Link" - ] - - # These keys require a value. If one ore more of the values is null or empty, the entire Alert is ignored. - # This is to avoid attempting to import incomplete Findings. - required_keys = ["alert_id", "title", "severity", "status"] - - alerts = [] - invalid_alerts = [] - - content = csv_file.read() - if isinstance(content, bytes): - content = content.decode("utf-8") - csv_reader = csv.DictReader( - io.StringIO(content), delimiter=",", quotechar='"' - ) - - # Don't bother parsing if the keys don't match exactly what's expected - if collections.Counter(default_keys) == collections.Counter( - csv_reader.fieldnames - ): - default_valud = "None provided" - for alert in csv_reader: - alert["alert_id"] = alert.pop("Alert ID") - alert["title"] = alert.pop("Title") - alert["description"] = alert.pop("Description") - alert["severity"] = alert.pop("Severity") - alert["type"] = alert.pop( - "Type", - ) - alert["source_date"] = alert.pop( - "Source Date (UTC)", default_valud - ) - alert["report_date"] = alert.pop( - "Report Date (UTC)", default_valud - ) - alert["network_type"] = alert.pop( - "Network Type", default_valud - ) - alert["source_url"] = alert.pop("Source URL", default_valud) - alert["assets"] = alert.pop("Assets", default_valud) - alert["tags"] = alert.pop("Tags", default_valud) - alert["status"] = alert.pop("Status", default_valud) - alert["alert_link"] = alert.pop("Alert Link") - alert.pop("Assignees") - alert.pop("Remediation") - alert.pop("Closed Reason") - alert.pop("Rating") - for key in required_keys: - if not alert[key]: - invalid_alerts.append(alert) - - if alert not in invalid_alerts: - alerts.append(alert) - else: - self._LOGGER.error( - "The CSV file has one or more missing or unexpected header values" - ) - - return alerts - def _build_finding_description(self, alert: dict) -> str: """ Builds an IntSights Finding description from various pieces of information. @@ -185,21 +44,18 @@ def _build_finding_description(self, alert: dict) -> str: def get_findings(self, file, test): duplicates = dict() - if file.name.lower().endswith(".json"): - alerts = self._parse_json( + alerts = IntSightsJSONParser()._parse_json( file, ) elif file.name.lower().endswith(".csv"): - alerts = self._parse_csv(file) + alerts = IntSightsCSVParser()._parse_csv(file) else: raise ValueError( "Filename extension not recognized. Use .json or .csv" ) - for alert in alerts: dupe_key = alert["alert_id"] - alert = Finding( title=alert["title"], test=test, @@ -212,10 +68,7 @@ def get_findings(self, file, test): dynamic_finding=True, unique_id_from_tool=alert["alert_id"] ) - duplicates[dupe_key] = alert - if dupe_key not in duplicates: duplicates[dupe_key] = True - return duplicates.values() From bc99f9ad273eeb8208d6e856e335a42deff44ca7 Mon Sep 17 00:00:00 2001 From: kiblik Date: Tue, 9 Apr 2024 01:53:04 +0200 Subject: [PATCH 014/138] Ruff: Add checks which are fully solved (#9864) --- pyproject.toml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 0ced12b186..5e1aee3805 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,25 @@ # Enable the pycodestyle (`E`) and Pyflakes (`F`) rules by default. # Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or # McCabe complexity (`C901`) by default. - lint.select = ["E", "F", "UP", "FLY", "TRY004", "TRY2"] + lint.select = [ + "F", + "E", + "W", + "UP", + "YTT", + "ASYNC", + "TRIO", + "ICN", + "LOG", + "SLOT", + "PD", + "PGH", + "TRY004", + "TRY2", + "FLY", + "NPY", + "AIR", +] lint.ignore = ["E501", "E722", "F821"] # Allow autofix for all enabled rules (when `--fix`) is provided. From d11b4579299f02acdbf8edab5c361b11516956cc Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Tue, 9 Apr 2024 01:53:16 +0200 Subject: [PATCH 015/138] :sparkles: add RHSA link for RedHatSatellite findings (#9877) --- dojo/settings/settings.dist.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index add788caaa..b1552bf456 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -1687,6 +1687,7 @@ def saml2_attrib_map_format(dict): 'SNYK': 'https://snyk.io/vuln/', 'RUSTSEC': 'https://rustsec.org/advisories/', 'VNS': 'https://vulners.com/', + 'RHSA': 'https://access.redhat.com/errata/', } # List of acceptable file types that can be uploaded to a given object via arbitrary file upload FILE_UPLOAD_TYPES = env("DD_FILE_UPLOAD_TYPES") From 0892763d471549b21bb2942be2fed9c1def1693e Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Tue, 9 Apr 2024 01:56:13 +0200 Subject: [PATCH 016/138] :hammer: restructure json in scout suite unittests (#9874) --- unittests/scans/scout_suite/new2.js | 56664 +++++++++++++++++- unittests/scans/scout_suite/no_vuln.js | 1475 +- unittests/scans/scout_suite/two_findings.js | 1599 +- 3 files changed, 59735 insertions(+), 3 deletions(-) diff --git a/unittests/scans/scout_suite/new2.js b/unittests/scans/scout_suite/new2.js index aa6187265c..3909e3576b 100644 --- a/unittests/scans/scout_suite/new2.js +++ b/unittests/scans/scout_suite/new2.js @@ -1,2 +1,56664 @@ scoutsuite_results = -{"account_id": "430150006394","environment": null,"last_run": {"ruleset_about": "This ruleset consists of numerous rules that are considered standard by NCC Group. The rules enabled range from violations of well-known security best practices to gaps resulting from less-known security implications of provider-specific mechanisms. Additional rules exist, some of them requiring extra-parameters to be configured, and some of them being applicable to a limited number of users.","ruleset_name": "default","run_parameters": {"excluded_regions": [],"regions": [],"services": [],"skipped_services": []},"summary": {"acm": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 2},"awslambda": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 1,"rules_count": 0},"cloudformation": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 1},"cloudtrail": {"checked_items": 16,"flagged_items": 16,"max_level": "danger","resources_count": 0,"rules_count": 8},"cloudwatch": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 1},"config": {"checked_items": 17,"flagged_items": 17,"max_level": "warning","resources_count": 0,"rules_count": 1},"directconnect": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 0},"dynamodb": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 0},"ec2": {"checked_items": 679,"flagged_items": 100,"max_level": "danger","resources_count": 20,"rules_count": 28},"efs": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 0},"elasticache": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 0},"elb": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 3},"elbv2": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 5},"emr": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 0},"iam": {"checked_items": 121,"flagged_items": 14,"max_level": "danger","resources_count": 22,"rules_count": 36},"kms": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 1},"rds": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 17,"rules_count": 8},"redshift": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 6},"route53": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 3},"s3": {"checked_items": 26,"flagged_items": 10,"max_level": "warning","resources_count": 2,"rules_count": 18},"secretsmanager": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 0},"ses": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 4},"sns": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 7},"sqs": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 7},"vpc": {"checked_items": 250,"flagged_items": 199,"max_level": "warning","resources_count": 0,"rules_count": 9}},"time": "2021-10-01 20:47:09+0200","version": "5.10.2"},"metadata": {"analytics": {"emr": {"resources": {"clusters": {"callbacks": [["match_security_groups_and_resources_callback",{"sg_id_attribute_name": "","sg_list_attribute_name": ["Ec2InstanceAttributes","EmrManagedMasterSecurityGroup"],"status_path": ["Status","State"]}],["match_security_groups_and_resources_callback",{"sg_id_attribute_name": "","sg_list_attribute_name": ["Ec2InstanceAttributes","EmrManagedSlaveSecurityGroup"],"status_path": ["Status","State"]}]],"cols": 2,"count": 0,"full_path": "services.emr.regions.id.vpcs.id.clusters","path": "services.emr.regions.id.vpcs.id.clusters","script": "services.emr.regions.vpcs.clusters"}}}},"compute": {"awslambda": {"resources": {"functions": {"callbacks": [["match_security_groups_and_resources_callback",{"sg_list_attribute_name": ["VpcConfig","SecurityGroupIds"],"status_path": ["runtime"]}]],"count": 1,"full_path": "services.awslambda.regions.id.functions","path": "services.awslambda.regions.id.functions","script": "services.awslambda.regions.functions"}}},"ec2": {"resources": {"images": {"cols": 2,"count": 0,"full_path": "services.ec2.regions.id.images","path": "services.ec2.regions.id.images","script": "services.ec2.regions.images"},"instances": {"callbacks": [["match_instances_and_subnets_callback",{}]],"cols": 2,"count": 0,"full_path": "services.ec2.regions.id.vpcs.id.instances","path": "services.ec2.regions.id.vpcs.id.instances","script": "services.ec2.regions.vpcs.instances"},"network_interfaces": {"callbacks": [["match_security_groups_and_resources_callback",{"sg_id_attribute_name": "GroupId","sg_list_attribute_name": ["Groups"]}]],"count": 0,"full_path": "services.ec2.regions.id.vpcs.id.network_interfaces","hidden": true,"path": "services.ec2.regions.id.vpcs.id.network_interfaces","script": "services.ec2.regions.vpcs.network_interfaces"},"security_groups": {"cols": 2,"count": 20,"full_path": "services.ec2.regions.id.vpcs.id.security_groups","path": "services.ec2.regions.id.vpcs.id.security_groups","script": "services.ec2.regions.vpcs.security_groups"},"snapshots": {"cols": 2,"count": 0,"full_path": "services.ec2.regions.id.snapshots","path": "services.ec2.regions.id.snapshots","script": "services.ec2.regions.snapshots"},"volumes": {"cols": 2,"count": 0,"full_path": "services.ec2.regions.id.volumes","path": "services.ec2.regions.id.volumes","script": "services.ec2.regions.volumes"}},"summaries": {"external attack surface": {"callbacks": [["list_ec2_network_attack_surface_callback",{"path": "services.ec2.regions.id.vpcs.id.instances.id.network_interfaces.id.PrivateIpAddresses"}]],"cols": 1,"path": "services.ec2.external_attack_surface"}}},"elb": {"resources": {"elb_policies": {"cols": 2,"count": 0,"full_path": "services.elb.regions.id.elb_policies","path": "services.elb.regions.id.elb_policies","script": "services.elb.regions.elb_policies"},"elbs": {"callbacks": [["match_security_groups_and_resources_callback",{"sg_id_attribute_name": "GroupId","sg_list_attribute_name": ["security_groups"],"status_path": ["Scheme"]}],["get_lb_attack_surface",{}]],"cols": 2,"count": 0,"full_path": "services.elb.regions.id.vpcs.id.elbs","path": "services.elb.regions.id.vpcs.id.elbs","script": "services.elb.regions.vpcs.elbs"}},"summaries": {"external attack surface": {"cols": 1,"path": "services.elb.external_attack_surface"}}},"elbv2": {"resources": {"lbs": {"callbacks": [["match_security_groups_and_resources_callback",{"sg_id_attribute_name": "GroupId","sg_list_attribute_name": ["security_groups"],"status_path": ["State","Code"]}],["get_lb_attack_surface",{}]],"cols": 2,"count": 0,"full_path": "services.elbv2.regions.id.vpcs.id.lbs","path": "services.elbv2.regions.id.vpcs.id.lbs","script": "services.elbv2.regions.vpcs.lbs"}},"summaries": {"external attack surface": {"cols": 1,"path": "services.elbv2.external_attack_surface"}}},"summaries": {"external attack surface": {"callbacks": [["merge",{"attribute": "external_attack_surface"}]],"cols": 1,"path": "service_groups.compute.summaries.external_attack_surface"}}},"containers": {"ecr": {"resources": {"images": {"cols": 2,"path": "services.ecr.regions.id.images"},"repositories": {"cols": 2,"path": "services.ecr.regions.id.repositories"}}},"ecs": {"resources": {"clusters": {"cols": 2,"path": "services.ecs.regions.id.clusters"},"regions": {"cols": 2,"path": "services.ecs.regions"}}},"eks": {"resources": {"clusters": {"cols": 2,"path": "services.eks.regions.id.clusters"}}}},"database": {"docdb": {"resources": {"clusters": {"path": "services.docdb.regions.id.clusters"}}},"dynamodb": {"resources": {"tables": {"count": 0,"full_path": "services.dynamodb.regions.id.tables","path": "services.dynamodb.regions.id.tables","script": "services.dynamodb.regions.tables"}}},"elasticache": {"resources": {"clusters": {"callbacks": [["match_security_groups_and_resources_callback",{"sg_id_attribute_name": "SecurityGroupId","sg_list_attribute_name": ["SecurityGroups"],"status_path": ["CacheClusterStatus"]}],["get_db_attack_surface",{}]],"cols": 2,"count": 0,"full_path": "services.elasticache.regions.id.vpcs.id.clusters","path": "services.elasticache.regions.id.vpcs.id.clusters","script": "services.elasticache.regions.vpcs.clusters"},"parameter_groups": {"cols": 2,"count": 216,"full_path": "services.elasticache.regions.id.parameter_groups","path": "services.elasticache.regions.id.parameter_groups","script": "services.elasticache.regions.parameter_groups"},"security_groups": {"cols": 2,"count": 0,"full_path": "services.elasticache.regions.id.security_groups","no_exceptions": true,"path": "services.elasticache.regions.id.security_groups","script": "services.elasticache.regions.security_groups"},"subnet_groups": {"cols": 2,"count": 0,"full_path": "services.elasticache.regions.id.vpcs.id.subnet_groups","path": "services.elasticache.regions.id.vpcs.id.subnet_groups","script": "services.elasticache.regions.vpcs.subnet_groups"}}},"rds": {"resources": {"instances": {"callbacks": [["match_security_groups_and_resources_callback",{"sg_id_attribute_name": "VpcSecurityGroupId","sg_list_attribute_name": ["VpcSecurityGroups"],"status_path": ["DBInstanceStatus"]}],["get_db_attack_surface",{}]],"cols": 2,"count": 0,"full_path": "services.rds.regions.id.vpcs.id.instances","path": "services.rds.regions.id.vpcs.id.instances","script": "services.rds.regions.vpcs.instances"},"parameter_groups": {"cols": 2,"count": 0,"full_path": "services.rds.regions.id.parameter_groups","path": "services.rds.regions.id.parameter_groups","script": "services.rds.regions.parameter_groups"},"security_groups": {"cols": 2,"count": 17,"full_path": "services.rds.regions.id.security_groups","no_exceptions": true,"path": "services.rds.regions.id.security_groups","script": "services.rds.regions.security_groups"},"snapshots": {"cols": 2,"count": 0,"full_path": "services.rds.regions.id.vpcs.id.snapshots","path": "services.rds.regions.id.vpcs.id.snapshots","script": "services.rds.regions.vpcs.snapshots"},"subnet_groups": {"cols": 2,"count": 0,"full_path": "services.rds.regions.id.vpcs.id.subnet_groups","path": "services.rds.regions.id.vpcs.id.subnet_groups","script": "services.rds.regions.vpcs.subnet_groups"}},"summaries": {"external attack surface": {"cols": 1,"path": "services.rds.external_attack_surface"}}},"redshift": {"resources": {"clusters": {"callbacks": [["match_security_groups_and_resources_callback",{"sg_id_attribute_name": "VpcSecurityGroupId","sg_list_attribute_name": ["VpcSecurityGroups"],"status_path": ["ClusterStatus"]}],["get_db_attack_surface",{}]],"cols": 2,"count": 0,"full_path": "services.redshift.regions.id.vpcs.id.clusters","path": "services.redshift.regions.id.vpcs.id.clusters","script": "services.redshift.regions.vpcs.clusters"},"parameter_groups": {"cols": 2,"count": 0,"full_path": "services.redshift.regions.id.parameter_groups","path": "services.redshift.regions.id.parameter_groups","script": "services.redshift.regions.parameter_groups"},"security_groups": {"cols": 2,"count": 0,"full_path": "services.redshift.regions.id.security_groups","path": "services.redshift.regions.id.security_groups","script": "services.redshift.regions.security_groups"}},"summaries": {"external attack surface": {"cols": 1,"path": "services.redshift.external_attack_surface"}}},"summaries": {"external attack surface": {"callbacks": [["merge",{"attribute": "external_attack_surface"}]],"cols": 1,"path": "service_groups.database.summaries.external_attack_surface"}}},"management": {"cloudformation": {"resources": {"stacks": {"callbacks": [["match_roles_and_cloudformation_stacks_callback",{}]],"cols": 2,"count": 0,"full_path": "services.cloudformation.regions.id.stacks","path": "services.cloudformation.regions.id.stacks","script": "services.cloudformation.regions.stacks"}}},"cloudtrail": {"resources": {"regions": {"cols": 2,"count": 16,"full_path": "services.cloudtrail.regions","path": "services.cloudtrail.regions","script": "services.cloudtrail.regions"},"trails": {"cols": 2,"count": 0,"full_path": "services.cloudtrail.regions.id.trails","path": "services.cloudtrail.regions.id.trails","script": "services.cloudtrail.regions.trails"}}},"cloudwatch": {"resources": {"alarms": {"cols": 2,"count": 0,"full_path": "services.cloudwatch.regions.id.alarms","path": "services.cloudwatch.regions.id.alarms","script": "services.cloudwatch.regions.alarms"},"metric_filters": {"cols": 2,"count": 0,"full_path": "services.cloudwatch.regions.id.metric_filters","path": "services.cloudwatch.regions.id.metric_filters","script": "services.cloudwatch.regions.metric_filters"}}},"config": {"resources": {"recorders": {"count": 0,"full_path": "services.config.regions.id.recorders","path": "services.config.regions.id.recorders","script": "services.config.regions.recorders"},"regions": {"cols": 2,"count": 17,"full_path": "services.config.regions","path": "services.config.regions","script": "services.config.regions"},"rules": {"count": 0,"full_path": "services.config.regions.id.rules","path": "services.config.regions.id.rules","script": "services.config.regions.rules"}}}},"messaging": {"ses": {"resources": {"identities": {"cols": 2,"count": 0,"full_path": "services.ses.regions.id.identities","path": "services.ses.regions.id.identities","script": "services.ses.regions.identities"}}},"sns": {"resources": {"topics": {"cols": 2,"count": 0,"full_path": "services.sns.regions.id.topics","path": "services.sns.regions.id.topics","script": "services.sns.regions.topics"}}},"sqs": {"resources": {"queues": {"cols": 2,"count": 0,"full_path": "services.sqs.regions.id.queues","path": "services.sqs.regions.id.queues","script": "services.sqs.regions.queues"}}}},"network": {"directconnect": {"resources": {"connections": {"cols": 2,"count": 0,"full_path": "services.directconnect.connections","path": "services.directconnect.connections","script": "services.directconnect.connections"}}},"route53": {"resources": {"domains": {"cols": 2,"count": 0,"full_path": "services.route53.regions.id.domains","path": "services.route53.regions.id.domains","script": "services.route53.regions.domains"},"hosted_zones": {"cols": 2,"count": 0,"full_path": "services.route53.regions.id.hosted_zones","path": "services.route53.regions.id.hosted_zones","script": "services.route53.regions.hosted_zones"}}},"vpc": {"resources": {"flow_logs": {"callbacks": [["sort_vpc_flow_logs_callback",{}],["match_roles_and_vpc_flowlogs_callback",{}]],"count": 0,"full_path": "services.vpc.regions.id.flow_logs","path": "services.vpc.regions.id.flow_logs","script": "services.vpc.regions.flow_logs"},"network_acls": {"callbacks": [["match_network_acls_and_subnets_callback",{}],["process_network_acls_callback",{}]],"cols": 2,"count": 17,"full_path": "services.vpc.regions.id.vpcs.id.network_acls","path": "services.vpc.regions.id.vpcs.id.network_acls","script": "services.vpc.regions.vpcs.network_acls"},"peering_connections": {"callbacks": [["process_vpc_peering_connections_callback",{}]],"count": 0,"full_path": "services.vpc.regions.id.peering_connections","path": "services.vpc.regions.id.peering_connections","script": "services.vpc.regions.peering_connections"},"subnets": {"cols": 2,"count": 55,"full_path": "services.vpc.regions.id.vpcs.id.subnets","path": "services.vpc.regions.id.vpcs.id.subnets","script": "services.vpc.regions.vpcs.subnets"},"vpcs": {"cols": 2,"count": 17,"full_path": "services.vpc.regions.id.vpcs","path": "services.vpc.regions.id.vpcs","script": "services.vpc.regions.vpcs"}}}},"security": {"acm": {"resources": {"certificates": {"cols": 2,"count": 0,"full_path": "services.acm.regions.id.certificates","path": "services.acm.regions.id.certificates","script": "services.acm.regions.certificates"}}},"cognito": {"resources": {"identity_pools": {"cols": 2,"path": "services.cognito.regions.id.identity_pools"},"user_pools": {"cols": 2,"path": "services.cognito.regions.id.user_pools"}}},"guardduty": {"resources": {"detectors": {"path": "services.guardduty.regions.id.detectors"},"regions": {"cols": 2,"path": "services.guardduty.regions"}}},"iam": {"resources": {"credential_reports": {"cols": 2,"count": 2,"full_path": "services.iam.credential_reports","path": "services.iam.credential_reports","script": "services.iam.credential_reports"},"groups": {"cols": 2,"count": 1,"full_path": "services.iam.groups","path": "services.iam.groups","script": "services.iam.groups"},"policies": {"cols": 2,"count": 9,"full_path": "services.iam.policies","path": "services.iam.policies","script": "services.iam.policies"},"roles": {"cols": 2,"count": 9,"full_path": "services.iam.roles","path": "services.iam.roles","script": "services.iam.roles"},"users": {"cols": 2,"count": 1,"full_path": "services.iam.users","path": "services.iam.users","script": "services.iam.users"}},"summaries": {"password_policy": {"cols": 1,"path": "services.iam.password_policy"},"permissions": {"cols": 1,"path": "services.iam.permissions"}}},"kms": {"resources": {"keys": {"count": 0,"full_path": "services.kms.regions.id.keys","path": "services.kms.regions.id.keys","script": "services.kms.regions.keys"}}},"secretsmanager": {"resources": {"secrets": {"cols": 2,"count": 0,"full_path": "services.secretsmanager.regions.id.secrets","path": "services.secretsmanager.regions.id.secrets","script": "services.secretsmanager.regions.secrets"}}}},"storage": {"efs": {"hidden": true,"resources": {"file_systems": {"callbacks": [["match_security_groups_and_resources_callback",{"sg_list_attribute_name": ["security_groups"],"status_path": ["LifeCycleState"]}]],"path": "services.efs.regions.id.file_systems"}}},"s3": {"resources": {"buckets": {"cols": 2,"count": 2,"full_path": "services.s3.buckets","path": "services.s3.buckets","script": "services.s3.buckets"}}}}},"partition": "aws","provider_code": "aws","provider_name": "Amazon Web Services","result_format": "json","service_groups": {"compute": {"summaries": {"external_attack_surface": {}}},"database": {"summaries": {"external_attack_surface": {}}}},"service_list": ["acm","awslambda","cloudformation","cloudtrail","cloudwatch","config","directconnect","dynamodb","ec2","efs","elasticache","elb","elbv2","emr","iam","kms","rds","redshift","route53","s3","ses","sns","sqs","vpc","secretsmanager"],"services": {"acm": {"certificates_count": 0,"filters": {},"findings": {"acm-certificate-with-close-expiration-date": {"checked_items": 0,"compliance": null,"dashboard_name": "Certificates","description": "ACM Certificate Expiring in Less Than 7 Days","flagged_items": 0,"id_suffix": "NotAfter","items": [],"level": "warning","path": "acm.regions.id.certificates.id","rationale": "Ensure that certificates which are in use are not about to expire.","references": null,"remediation": null,"service": "ACM"},"acm-certificate-with-transparency-logging-disabled": {"checked_items": 0,"compliance": null,"dashboard_name": "Certificates","description": "ACM Certificate with Transparency Logging Set to Disabled","flagged_items": 0,"id_suffix": "CertificateTransparencyLoggingPreference","items": [],"level": "warning","path": "acm.regions.id.certificates.id","rationale": "Disabling Transparency Logging may result in browsers not trusting your certificate. As of April 30 2018, Google Chrome no longer trusts public SSL/TLS certificates that are not recorded in a certificate transparency log. Transparency Logging should be enabled as a best practice.","references": ["https://aws.amazon.com/blogs/security/how-to-get-ready-for-certificate-transparency/"],"remediation": null,"service": "ACM"}},"regions": {"ap-northeast-1": {"certificates": {},"certificates_count": 0,"id": "ap-northeast-1","name": "ap-northeast-1","region": "ap-northeast-1"},"ap-northeast-2": {"certificates": {},"certificates_count": 0,"id": "ap-northeast-2","name": "ap-northeast-2","region": "ap-northeast-2"},"ap-northeast-3": {"certificates": {},"certificates_count": 0,"id": "ap-northeast-3","name": "ap-northeast-3","region": "ap-northeast-3"},"ap-south-1": {"certificates": {},"certificates_count": 0,"id": "ap-south-1","name": "ap-south-1","region": "ap-south-1"},"ap-southeast-1": {"certificates": {},"certificates_count": 0,"id": "ap-southeast-1","name": "ap-southeast-1","region": "ap-southeast-1"},"ap-southeast-2": {"certificates": {},"certificates_count": 0,"id": "ap-southeast-2","name": "ap-southeast-2","region": "ap-southeast-2"},"ca-central-1": {"certificates": {},"certificates_count": 0,"id": "ca-central-1","name": "ca-central-1","region": "ca-central-1"},"eu-central-1": {"certificates": {},"certificates_count": 0,"id": "eu-central-1","name": "eu-central-1","region": "eu-central-1"},"eu-north-1": {"certificates": {},"certificates_count": 0,"id": "eu-north-1","name": "eu-north-1","region": "eu-north-1"},"eu-west-1": {"certificates": {},"certificates_count": 0,"id": "eu-west-1","name": "eu-west-1","region": "eu-west-1"},"eu-west-2": {"certificates": {},"certificates_count": 0,"id": "eu-west-2","name": "eu-west-2","region": "eu-west-2"},"eu-west-3": {"certificates": {},"certificates_count": 0,"id": "eu-west-3","name": "eu-west-3","region": "eu-west-3"},"sa-east-1": {"certificates": {},"certificates_count": 0,"id": "sa-east-1","name": "sa-east-1","region": "sa-east-1"},"us-east-1": {"certificates": {},"certificates_count": 0,"id": "us-east-1","name": "us-east-1","region": "us-east-1"},"us-east-2": {"certificates": {},"certificates_count": 0,"id": "us-east-2","name": "us-east-2","region": "us-east-2"},"us-west-1": {"certificates": {},"certificates_count": 0,"id": "us-west-1","name": "us-west-1","region": "us-west-1"},"us-west-2": {"certificates": {},"certificates_count": 0,"id": "us-west-2","name": "us-west-2","region": "us-west-2"}},"regions_count": 17},"awslambda": {"filters": {},"findings": {},"functions_count": 1,"regions": {"ap-northeast-1": {"functions": {},"functions_count": 0,"id": "ap-northeast-1","name": "ap-northeast-1","region": "ap-northeast-1"},"ap-northeast-2": {"functions": {},"functions_count": 0,"id": "ap-northeast-2","name": "ap-northeast-2","region": "ap-northeast-2"},"ap-northeast-3": {"functions": {},"functions_count": 0,"id": "ap-northeast-3","name": "ap-northeast-3","region": "ap-northeast-3"},"ap-south-1": {"functions": {},"functions_count": 0,"id": "ap-south-1","name": "ap-south-1","region": "ap-south-1"},"ap-southeast-1": {"functions": {},"functions_count": 0,"id": "ap-southeast-1","name": "ap-southeast-1","region": "ap-southeast-1"},"ap-southeast-2": {"functions": {},"functions_count": 0,"id": "ap-southeast-2","name": "ap-southeast-2","region": "ap-southeast-2"},"ca-central-1": {"functions": {},"functions_count": 0,"id": "ca-central-1","name": "ca-central-1","region": "ca-central-1"},"eu-central-1": {"functions": {},"functions_count": 0,"id": "eu-central-1","name": "eu-central-1","region": "eu-central-1"},"eu-north-1": {"functions": {},"functions_count": 0,"id": "eu-north-1","name": "eu-north-1","region": "eu-north-1"},"eu-west-1": {"functions": {"load-wikipedia": {"access_policy": {"Id": "default","Statement": [],"Version": "2012-10-17"},"arn": "arn:aws:lambda:eu-west-1:430150006394:function:load-wikipedia","code_sha256": "txY7sj38mwfot6uoeqMhNs4P/VycimyJcRBdlDBTyik=","code_size": 506,"description": "","env_variable_names": [],"env_variable_values": [],"env_variables": [],"execution_role": {"Arn": "arn:aws:iam::430150006394:role/service-role/load-wikipedia","AssumeRolePolicyDocument": {"Statement": [{"Action": "sts:AssumeRole","Effect": "Allow","Principal": {"Service": "lambda.amazonaws.com"}}],"Version": "2012-10-17"},"CreateDate": "2019-01-23 17:01:24+00:00","MaxSessionDuration": 3600,"Path": "/service-role/","RoleId": "AROAJY5MNJYDKGD2UIATQ","RoleLastUsed": {},"RoleName": "load-wikipedia","policies": [{"Document": {"Statement": [{"Action": "logs:CreateLogGroup","Effect": "Allow","Resource": "arn:aws:logs:eu-west-1:430150006394:*"},{"Action": ["logs:CreateLogStream","logs:PutLogEvents"],"Effect": "Allow","Resource": ["arn:aws:logs:eu-west-1:430150006394:log-group:/aws/lambda/load-wikipedia:*"]}],"Version": "2012-10-17"},"PolicyArn": "arn:aws:iam::430150006394:policy/service-role/AWSLambdaBasicExecutionRole-676647ec-377e-496c-8355-37f23bf12c85","PolicyName": "AWSLambdaBasicExecutionRole-676647ec-377e-496c-8355-37f23bf12c85"}],"policy_statements": [{"Action": "logs:CreateLogGroup","Effect": "Allow","Resource": "arn:aws:logs:eu-west-1:430150006394:*"},{"Action": ["logs:CreateLogStream","logs:PutLogEvents"],"Effect": "Allow","Resource": ["arn:aws:logs:eu-west-1:430150006394:log-group:/aws/lambda/load-wikipedia:*"]}]},"handler": "lambda_function.lambda_handler","last_modified": "2019-01-25T17:47:21.038+0000","memory_size": 128,"name": "load-wikipedia","region": "eu-west-1","revision_id": "9ec6c002-9048-4d53-a4c2-001e406827b3","role_arn": "arn:aws:iam::430150006394:role/service-role/load-wikipedia","runtime": "python2.7","timeout": 3,"tracing_config": {"Mode": "PassThrough"},"version": "$LATEST"}},"functions_count": 1,"id": "eu-west-1","name": "eu-west-1","region": "eu-west-1"},"eu-west-2": {"functions": {},"functions_count": 0,"id": "eu-west-2","name": "eu-west-2","region": "eu-west-2"},"eu-west-3": {"functions": {},"functions_count": 0,"id": "eu-west-3","name": "eu-west-3","region": "eu-west-3"},"sa-east-1": {"functions": {},"functions_count": 0,"id": "sa-east-1","name": "sa-east-1","region": "sa-east-1"},"us-east-1": {"functions": {},"functions_count": 0,"id": "us-east-1","name": "us-east-1","region": "us-east-1"},"us-east-2": {"functions": {},"functions_count": 0,"id": "us-east-2","name": "us-east-2","region": "us-east-2"},"us-west-1": {"functions": {},"functions_count": 0,"id": "us-west-1","name": "us-west-1","region": "us-west-1"},"us-west-2": {"functions": {},"functions_count": 0,"id": "us-west-2","name": "us-west-2","region": "us-west-2"}},"regions_count": 17},"cloudformation": {"filters": {},"findings": {"cloudformation-stack-with-role": {"checked_items": 0,"compliance": null,"dashboard_name": "Stacks","description": "Role Passed to Stack","flagged_items": 0,"items": [],"level": "danger","path": "cloudformation.regions.id.stacks.id","rationale": "Passing a role to CloudFormation stacks may result in privilege escalation because IAM users with privileges within the CloudFormation scope implicitly inherit the stack's role's permissions. Consequently, it should be ensured that the IAM privileges assigned to the stack's role follow the principle of least privilege.","references": ["https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/best-practices.html"],"remediation": null,"service": "CloudFormation"}},"regions": {"ap-northeast-1": {"id": "ap-northeast-1","name": "ap-northeast-1","region": "ap-northeast-1","stacks": {},"stacks_count": 0},"ap-northeast-2": {"id": "ap-northeast-2","name": "ap-northeast-2","region": "ap-northeast-2","stacks": {},"stacks_count": 0},"ap-northeast-3": {"id": "ap-northeast-3","name": "ap-northeast-3","region": "ap-northeast-3","stacks": {},"stacks_count": 0},"ap-south-1": {"id": "ap-south-1","name": "ap-south-1","region": "ap-south-1","stacks": {},"stacks_count": 0},"ap-southeast-1": {"id": "ap-southeast-1","name": "ap-southeast-1","region": "ap-southeast-1","stacks": {},"stacks_count": 0},"ap-southeast-2": {"id": "ap-southeast-2","name": "ap-southeast-2","region": "ap-southeast-2","stacks": {},"stacks_count": 0},"ca-central-1": {"id": "ca-central-1","name": "ca-central-1","region": "ca-central-1","stacks": {},"stacks_count": 0},"eu-central-1": {"id": "eu-central-1","name": "eu-central-1","region": "eu-central-1","stacks": {},"stacks_count": 0},"eu-north-1": {"id": "eu-north-1","name": "eu-north-1","region": "eu-north-1","stacks": {},"stacks_count": 0},"eu-west-1": {"id": "eu-west-1","name": "eu-west-1","region": "eu-west-1","stacks": {},"stacks_count": 0},"eu-west-2": {"id": "eu-west-2","name": "eu-west-2","region": "eu-west-2","stacks": {},"stacks_count": 0},"eu-west-3": {"id": "eu-west-3","name": "eu-west-3","region": "eu-west-3","stacks": {},"stacks_count": 0},"sa-east-1": {"id": "sa-east-1","name": "sa-east-1","region": "sa-east-1","stacks": {},"stacks_count": 0},"us-east-1": {"id": "us-east-1","name": "us-east-1","region": "us-east-1","stacks": {},"stacks_count": 0},"us-east-2": {"id": "us-east-2","name": "us-east-2","region": "us-east-2","stacks": {},"stacks_count": 0},"us-west-1": {"id": "us-west-1","name": "us-west-1","region": "us-west-1","stacks": {},"stacks_count": 0},"us-west-2": {"id": "us-west-2","name": "us-west-2","region": "us-west-2","stacks": {},"stacks_count": 0}},"regions_count": 17,"stacks_count": 0},"cloudtrail": {"DuplicatedGlobalServiceEvents": false,"IncludeGlobalServiceEvents": false,"filters": {},"findings": {"cloudtrail-duplicated-global-services-logging": {"checked_items": 0,"compliance": null,"dashboard_name": "Configurations","description": "Global Service Logging Duplicated","flagged_items": 0,"id_suffix": "IncludeGlobalServiceEvents","items": [],"level": "warning","path": "cloudtrail.regions.id.trails.id","rationale": "Global service logging is enabled in multiple Trails. While this does not jeopardize the security of the environment, duplicated entries in logs increase the difficulty to investigate potential incidents.","references": ["https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-concepts.html#cloudtrail-concepts-global-service-events"],"remediation": null,"service": "CloudTrail"},"cloudtrail-no-cloudwatch-integration": {"checked_items": 0,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "2.4","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "2.4","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "2.4","version": "1.2.0"}],"dashboard_name": "Configurations","description": "Trail Is Not Integrated with CloudWatch","display_path": "cloudtrail.regions.id.trails.id","flagged_items": 0,"id_suffix": "TrailCloudwatchNoIntegration","items": [],"level": "warning","path": "cloudtrail.regions.id.trails.id","rationale": "The lack of integration with CloudWatch hinders ral-time and historic activity logging as well as not allowing the configuration of alarms and notifications for anomalous account activity.","references": null,"remediation": "Configure each Trail to have a CloudWatch Logs group attached","service": "CloudTrail"},"cloudtrail-no-data-logging": {"checked_items": 0,"compliance": null,"dashboard_name": "Configurations","description": "Data Events Logging Not Configured","display_path": "cloudtrail.regions.id.trails.id","flagged_items": 0,"id_suffix": "cloudtrail-data-events-disabled","items": [],"level": "warning","path": "cloudtrail.regions.id.trails.id","rationale": "CloudTrail Data Logging is not configured, which means that S3 access and Lambda invocations are not logged.

Note: S3 bucket logging can be used in place of CloudTrail data events for S3. If that is the case, logs for Lambda invocations may still be missing.","references": ["https://docs.aws.amazon.com/awscloudtrail/latest/userguide/logging-data-events-with-cloudtrail.html"],"remediation": null,"service": "CloudTrail"},"cloudtrail-no-encryption-with-kms": {"checked_items": 0,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "2.7","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "2.7","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "2.7","version": "1.2.0"}],"dashboard_name": "Configurations","description": "CloudTrail Logs Not Encrypted with KMS Customer Master Keys (CMKs)","display_path": "cloudtrail.regions.id.trails.id","flagged_items": 0,"id_suffix": "cloudtrail-kms-key-unused","items": [],"level": "danger","path": "cloudtrail.regions.id.trails.id","rationale": "Not encrypting CloudTrail logs with SSE-KMS affects the confidentiality of the log data.","references": ["https://docs.aws.amazon.com/awscloudtrail/latest/userguide/encrypting-cloudtrail-log-files-with-aws-kms.html"],"remediation": "Ensure each Trail is encrypted with a KMS key","service": "CloudTrail"},"cloudtrail-no-global-services-logging": {"checked_items": 0,"compliance": null,"dashboard_name": "Configurations","description": "Global Service Logging Disabled","flagged_items": 0,"id_suffix": "IncludeGlobalServiceEvents","items": [],"level": "danger","path": "cloudtrail.regions.id.trails.id","rationale": "API activity for global services such as IAM and STS is not logged. Investigation of incidents will be incomplete due to the lack of information.","references": ["https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-concepts.html#cloudtrail-concepts-global-service-events"],"remediation": null,"service": "CloudTrail"},"cloudtrail-no-log-file-validation": {"checked_items": 0,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "2.2","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "2.2","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "2.2","version": "1.2.0"}],"dashboard_name": "Configurations","description": "Log File Validation Is Disabled","display_path": "cloudtrail.regions.id.trails.id","flagged_items": 0,"id_suffix": "LogFileValidationDisabled","items": [],"level": "danger","path": "cloudtrail.regions.id.trails.id","rationale": "The lack of log file validation prevents from verifying the integrity of CloudTrail log files.","references": ["https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-log-file-validation-intro.html"],"remediation": "Ensure that each Trail has Enable log file validation set to Yes","service": "CloudTrail"},"cloudtrail-no-logging": {"checked_items": 0,"class_suffix": "IsLogging","compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "2.1","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "2.1","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "2.1","version": "1.2.0"}],"dashboard_name": "Configurations","description": "Disabled Trails","flagged_items": 0,"items": [],"level": "danger","path": "cloudtrail.regions.id.trails.id","rationale": "Logging is disabled for a given Trail. Depending on the configuration, logs for important API activity may be missing.","references": ["https://docs.aws.amazon.com/awscloudtrail/latest/userguide/best-practices-security.html"],"remediation": "Configure all Trails to enable Logging, set Apply trail to all regions and ensure that Read/Write Events are set to ALL","service": "CloudTrail"},"cloudtrail-not-configured": {"checked_items": 16,"compliance": null,"dashboard_name": "Regions","description": "CloudTrail Service Not Configured","flagged_items": 16,"id_suffix": "NotConfigured","items": ["cloudtrail.regions.ap-northeast-1.NotConfigured","cloudtrail.regions.ap-northeast-2.NotConfigured","cloudtrail.regions.ap-south-1.NotConfigured","cloudtrail.regions.ap-southeast-1.NotConfigured","cloudtrail.regions.ap-southeast-2.NotConfigured","cloudtrail.regions.ca-central-1.NotConfigured","cloudtrail.regions.eu-central-1.NotConfigured","cloudtrail.regions.eu-north-1.NotConfigured","cloudtrail.regions.eu-west-1.NotConfigured","cloudtrail.regions.eu-west-2.NotConfigured","cloudtrail.regions.eu-west-3.NotConfigured","cloudtrail.regions.sa-east-1.NotConfigured","cloudtrail.regions.us-east-1.NotConfigured","cloudtrail.regions.us-east-2.NotConfigured","cloudtrail.regions.us-west-1.NotConfigured","cloudtrail.regions.us-west-2.NotConfigured"],"level": "danger","path": "cloudtrail.regions.id","rationale": "CloudTrail is not configured, which means that API activity is not logged.","references": ["https://docs.aws.amazon.com/awscloudtrail/latest/userguide/best-practices-security.html"],"remediation": null,"service": "CloudTrail"}},"regions": {"ap-northeast-1": {"id": "ap-northeast-1","name": "ap-northeast-1","region": "ap-northeast-1","trails": {},"trails_count": 0},"ap-northeast-2": {"id": "ap-northeast-2","name": "ap-northeast-2","region": "ap-northeast-2","trails": {},"trails_count": 0},"ap-south-1": {"id": "ap-south-1","name": "ap-south-1","region": "ap-south-1","trails": {},"trails_count": 0},"ap-southeast-1": {"id": "ap-southeast-1","name": "ap-southeast-1","region": "ap-southeast-1","trails": {},"trails_count": 0},"ap-southeast-2": {"id": "ap-southeast-2","name": "ap-southeast-2","region": "ap-southeast-2","trails": {},"trails_count": 0},"ca-central-1": {"id": "ca-central-1","name": "ca-central-1","region": "ca-central-1","trails": {},"trails_count": 0},"eu-central-1": {"id": "eu-central-1","name": "eu-central-1","region": "eu-central-1","trails": {},"trails_count": 0},"eu-north-1": {"id": "eu-north-1","name": "eu-north-1","region": "eu-north-1","trails": {},"trails_count": 0},"eu-west-1": {"id": "eu-west-1","name": "eu-west-1","region": "eu-west-1","trails": {},"trails_count": 0},"eu-west-2": {"id": "eu-west-2","name": "eu-west-2","region": "eu-west-2","trails": {},"trails_count": 0},"eu-west-3": {"id": "eu-west-3","name": "eu-west-3","region": "eu-west-3","trails": {},"trails_count": 0},"sa-east-1": {"id": "sa-east-1","name": "sa-east-1","region": "sa-east-1","trails": {},"trails_count": 0},"us-east-1": {"id": "us-east-1","name": "us-east-1","region": "us-east-1","trails": {},"trails_count": 0},"us-east-2": {"id": "us-east-2","name": "us-east-2","region": "us-east-2","trails": {},"trails_count": 0},"us-west-1": {"id": "us-west-1","name": "us-west-1","region": "us-west-1","trails": {},"trails_count": 0},"us-west-2": {"id": "us-west-2","name": "us-west-2","region": "us-west-2","trails": {},"trails_count": 0}},"regions_count": 16,"trails_count": 0},"cloudwatch": {"alarms_count": 0,"filters": {},"findings": {"cloudwatch-alarm-without-actions": {"checked_items": 0,"compliance": null,"dashboard_name": "Alarms","description": "Alarm without Action","flagged_items": 0,"id_suffix": "NoActions","items": [],"level": "warning","path": "cloudwatch.regions.id.alarms.id","rationale": "Each alarm should have at least one action","references": ["https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html"],"remediation": null,"service": "CloudWatch"}},"metric_filters_count": 0,"regions": {"ap-northeast-1": {"alarms": {},"alarms_count": 0,"id": "ap-northeast-1","metric_filters": {},"metric_filters_count": 0,"metric_filters_pattern_checks": {"aws_configuration_changes": false,"cloudtrail_configuration_changes": false,"cmk_deletion": false,"console_authentication_failures": false,"console_login_mfa": false,"iam_policy_changes": false,"nacl_changes": false,"network_gateways_changes": false,"root_usage": false,"route_table_changes": false,"s3_policy_changes": false,"security_group_changes": false,"unauthorized_api_calls": false,"vpc_changes": false},"name": "ap-northeast-1","region": "ap-northeast-1"},"ap-northeast-2": {"alarms": {},"alarms_count": 0,"id": "ap-northeast-2","metric_filters": {},"metric_filters_count": 0,"metric_filters_pattern_checks": {"aws_configuration_changes": false,"cloudtrail_configuration_changes": false,"cmk_deletion": false,"console_authentication_failures": false,"console_login_mfa": false,"iam_policy_changes": false,"nacl_changes": false,"network_gateways_changes": false,"root_usage": false,"route_table_changes": false,"s3_policy_changes": false,"security_group_changes": false,"unauthorized_api_calls": false,"vpc_changes": false},"name": "ap-northeast-2","region": "ap-northeast-2"},"ap-northeast-3": {"alarms": {},"alarms_count": 0,"id": "ap-northeast-3","metric_filters": {},"metric_filters_count": 0,"metric_filters_pattern_checks": {"aws_configuration_changes": false,"cloudtrail_configuration_changes": false,"cmk_deletion": false,"console_authentication_failures": false,"console_login_mfa": false,"iam_policy_changes": false,"nacl_changes": false,"network_gateways_changes": false,"root_usage": false,"route_table_changes": false,"s3_policy_changes": false,"security_group_changes": false,"unauthorized_api_calls": false,"vpc_changes": false},"name": "ap-northeast-3","region": "ap-northeast-3"},"ap-south-1": {"alarms": {},"alarms_count": 0,"id": "ap-south-1","metric_filters": {},"metric_filters_count": 0,"metric_filters_pattern_checks": {"aws_configuration_changes": false,"cloudtrail_configuration_changes": false,"cmk_deletion": false,"console_authentication_failures": false,"console_login_mfa": false,"iam_policy_changes": false,"nacl_changes": false,"network_gateways_changes": false,"root_usage": false,"route_table_changes": false,"s3_policy_changes": false,"security_group_changes": false,"unauthorized_api_calls": false,"vpc_changes": false},"name": "ap-south-1","region": "ap-south-1"},"ap-southeast-1": {"alarms": {},"alarms_count": 0,"id": "ap-southeast-1","metric_filters": {},"metric_filters_count": 0,"metric_filters_pattern_checks": {"aws_configuration_changes": false,"cloudtrail_configuration_changes": false,"cmk_deletion": false,"console_authentication_failures": false,"console_login_mfa": false,"iam_policy_changes": false,"nacl_changes": false,"network_gateways_changes": false,"root_usage": false,"route_table_changes": false,"s3_policy_changes": false,"security_group_changes": false,"unauthorized_api_calls": false,"vpc_changes": false},"name": "ap-southeast-1","region": "ap-southeast-1"},"ap-southeast-2": {"alarms": {},"alarms_count": 0,"id": "ap-southeast-2","metric_filters": {},"metric_filters_count": 0,"metric_filters_pattern_checks": {"aws_configuration_changes": false,"cloudtrail_configuration_changes": false,"cmk_deletion": false,"console_authentication_failures": false,"console_login_mfa": false,"iam_policy_changes": false,"nacl_changes": false,"network_gateways_changes": false,"root_usage": false,"route_table_changes": false,"s3_policy_changes": false,"security_group_changes": false,"unauthorized_api_calls": false,"vpc_changes": false},"name": "ap-southeast-2","region": "ap-southeast-2"},"ca-central-1": {"alarms": {},"alarms_count": 0,"id": "ca-central-1","metric_filters": {},"metric_filters_count": 0,"metric_filters_pattern_checks": {"aws_configuration_changes": false,"cloudtrail_configuration_changes": false,"cmk_deletion": false,"console_authentication_failures": false,"console_login_mfa": false,"iam_policy_changes": false,"nacl_changes": false,"network_gateways_changes": false,"root_usage": false,"route_table_changes": false,"s3_policy_changes": false,"security_group_changes": false,"unauthorized_api_calls": false,"vpc_changes": false},"name": "ca-central-1","region": "ca-central-1"},"eu-central-1": {"alarms": {},"alarms_count": 0,"id": "eu-central-1","metric_filters": {},"metric_filters_count": 0,"metric_filters_pattern_checks": {"aws_configuration_changes": false,"cloudtrail_configuration_changes": false,"cmk_deletion": false,"console_authentication_failures": false,"console_login_mfa": false,"iam_policy_changes": false,"nacl_changes": false,"network_gateways_changes": false,"root_usage": false,"route_table_changes": false,"s3_policy_changes": false,"security_group_changes": false,"unauthorized_api_calls": false,"vpc_changes": false},"name": "eu-central-1","region": "eu-central-1"},"eu-north-1": {"alarms": {},"alarms_count": 0,"id": "eu-north-1","metric_filters": {},"metric_filters_count": 0,"metric_filters_pattern_checks": {"aws_configuration_changes": false,"cloudtrail_configuration_changes": false,"cmk_deletion": false,"console_authentication_failures": false,"console_login_mfa": false,"iam_policy_changes": false,"nacl_changes": false,"network_gateways_changes": false,"root_usage": false,"route_table_changes": false,"s3_policy_changes": false,"security_group_changes": false,"unauthorized_api_calls": false,"vpc_changes": false},"name": "eu-north-1","region": "eu-north-1"},"eu-west-1": {"alarms": {},"alarms_count": 0,"id": "eu-west-1","metric_filters": {},"metric_filters_count": 0,"metric_filters_pattern_checks": {"aws_configuration_changes": false,"cloudtrail_configuration_changes": false,"cmk_deletion": false,"console_authentication_failures": false,"console_login_mfa": false,"iam_policy_changes": false,"nacl_changes": false,"network_gateways_changes": false,"root_usage": false,"route_table_changes": false,"s3_policy_changes": false,"security_group_changes": false,"unauthorized_api_calls": false,"vpc_changes": false},"name": "eu-west-1","region": "eu-west-1"},"eu-west-2": {"alarms": {},"alarms_count": 0,"id": "eu-west-2","metric_filters": {},"metric_filters_count": 0,"metric_filters_pattern_checks": {"aws_configuration_changes": false,"cloudtrail_configuration_changes": false,"cmk_deletion": false,"console_authentication_failures": false,"console_login_mfa": false,"iam_policy_changes": false,"nacl_changes": false,"network_gateways_changes": false,"root_usage": false,"route_table_changes": false,"s3_policy_changes": false,"security_group_changes": false,"unauthorized_api_calls": false,"vpc_changes": false},"name": "eu-west-2","region": "eu-west-2"},"eu-west-3": {"alarms": {},"alarms_count": 0,"id": "eu-west-3","metric_filters": {},"metric_filters_count": 0,"metric_filters_pattern_checks": {"aws_configuration_changes": false,"cloudtrail_configuration_changes": false,"cmk_deletion": false,"console_authentication_failures": false,"console_login_mfa": false,"iam_policy_changes": false,"nacl_changes": false,"network_gateways_changes": false,"root_usage": false,"route_table_changes": false,"s3_policy_changes": false,"security_group_changes": false,"unauthorized_api_calls": false,"vpc_changes": false},"name": "eu-west-3","region": "eu-west-3"},"sa-east-1": {"alarms": {},"alarms_count": 0,"id": "sa-east-1","metric_filters": {},"metric_filters_count": 0,"metric_filters_pattern_checks": {"aws_configuration_changes": false,"cloudtrail_configuration_changes": false,"cmk_deletion": false,"console_authentication_failures": false,"console_login_mfa": false,"iam_policy_changes": false,"nacl_changes": false,"network_gateways_changes": false,"root_usage": false,"route_table_changes": false,"s3_policy_changes": false,"security_group_changes": false,"unauthorized_api_calls": false,"vpc_changes": false},"name": "sa-east-1","region": "sa-east-1"},"us-east-1": {"alarms": {},"alarms_count": 0,"id": "us-east-1","metric_filters": {},"metric_filters_count": 0,"metric_filters_pattern_checks": {"aws_configuration_changes": false,"cloudtrail_configuration_changes": false,"cmk_deletion": false,"console_authentication_failures": false,"console_login_mfa": false,"iam_policy_changes": false,"nacl_changes": false,"network_gateways_changes": false,"root_usage": false,"route_table_changes": false,"s3_policy_changes": false,"security_group_changes": false,"unauthorized_api_calls": false,"vpc_changes": false},"name": "us-east-1","region": "us-east-1"},"us-east-2": {"alarms": {},"alarms_count": 0,"id": "us-east-2","metric_filters": {},"metric_filters_count": 0,"metric_filters_pattern_checks": {"aws_configuration_changes": false,"cloudtrail_configuration_changes": false,"cmk_deletion": false,"console_authentication_failures": false,"console_login_mfa": false,"iam_policy_changes": false,"nacl_changes": false,"network_gateways_changes": false,"root_usage": false,"route_table_changes": false,"s3_policy_changes": false,"security_group_changes": false,"unauthorized_api_calls": false,"vpc_changes": false},"name": "us-east-2","region": "us-east-2"},"us-west-1": {"alarms": {},"alarms_count": 0,"id": "us-west-1","metric_filters": {},"metric_filters_count": 0,"metric_filters_pattern_checks": {"aws_configuration_changes": false,"cloudtrail_configuration_changes": false,"cmk_deletion": false,"console_authentication_failures": false,"console_login_mfa": false,"iam_policy_changes": false,"nacl_changes": false,"network_gateways_changes": false,"root_usage": false,"route_table_changes": false,"s3_policy_changes": false,"security_group_changes": false,"unauthorized_api_calls": false,"vpc_changes": false},"name": "us-west-1","region": "us-west-1"},"us-west-2": {"alarms": {},"alarms_count": 0,"id": "us-west-2","metric_filters": {},"metric_filters_count": 0,"metric_filters_pattern_checks": {"aws_configuration_changes": false,"cloudtrail_configuration_changes": false,"cmk_deletion": false,"console_authentication_failures": false,"console_login_mfa": false,"iam_policy_changes": false,"nacl_changes": false,"network_gateways_changes": false,"root_usage": false,"route_table_changes": false,"s3_policy_changes": false,"security_group_changes": false,"unauthorized_api_calls": false,"vpc_changes": false},"name": "us-west-2","region": "us-west-2"}},"regions_count": 17},"config": {"filters": {},"findings": {"config-recorder-not-configured": {"checked_items": 17,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "2.5","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "2.5","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "2.5","version": "1.2.0"}],"dashboard_name": "Regions","description": "AWS Config Not Enabled","flagged_items": 17,"id_suffix": "NotConfigured","items": ["config.regions.ap-northeast-1.NotConfigured","config.regions.ap-northeast-2.NotConfigured","config.regions.ap-northeast-3.NotConfigured","config.regions.ap-south-1.NotConfigured","config.regions.ap-southeast-1.NotConfigured","config.regions.ap-southeast-2.NotConfigured","config.regions.ca-central-1.NotConfigured","config.regions.eu-central-1.NotConfigured","config.regions.eu-north-1.NotConfigured","config.regions.eu-west-1.NotConfigured","config.regions.eu-west-2.NotConfigured","config.regions.eu-west-3.NotConfigured","config.regions.sa-east-1.NotConfigured","config.regions.us-east-1.NotConfigured","config.regions.us-east-2.NotConfigured","config.regions.us-west-1.NotConfigured","config.regions.us-west-2.NotConfigured"],"level": "warning","path": "config.regions.id","rationale": "No AWS Config recorders are configured, which means that changes in AWS resource configuration are not logged. This hinders security analysis, resource change tracking and compliance auditing.","references": ["https://aws.amazon.com/blogs/mt/aws-config-best-practices/"],"remediation": "Enable AWS Config in all regions, define the resources you want to record in each region and include global resources (IAM resources)","service": "Config"}},"recorders_count": 0,"regions": {"ap-northeast-1": {"id": "ap-northeast-1","name": "ap-northeast-1","recorders": {},"recorders_count": 0,"region": "ap-northeast-1","rules": {},"rules_count": 0},"ap-northeast-2": {"id": "ap-northeast-2","name": "ap-northeast-2","recorders": {},"recorders_count": 0,"region": "ap-northeast-2","rules": {},"rules_count": 0},"ap-northeast-3": {"id": "ap-northeast-3","name": "ap-northeast-3","recorders": {},"recorders_count": 0,"region": "ap-northeast-3","rules": {},"rules_count": 0},"ap-south-1": {"id": "ap-south-1","name": "ap-south-1","recorders": {},"recorders_count": 0,"region": "ap-south-1","rules": {},"rules_count": 0},"ap-southeast-1": {"id": "ap-southeast-1","name": "ap-southeast-1","recorders": {},"recorders_count": 0,"region": "ap-southeast-1","rules": {},"rules_count": 0},"ap-southeast-2": {"id": "ap-southeast-2","name": "ap-southeast-2","recorders": {},"recorders_count": 0,"region": "ap-southeast-2","rules": {},"rules_count": 0},"ca-central-1": {"id": "ca-central-1","name": "ca-central-1","recorders": {},"recorders_count": 0,"region": "ca-central-1","rules": {},"rules_count": 0},"eu-central-1": {"id": "eu-central-1","name": "eu-central-1","recorders": {},"recorders_count": 0,"region": "eu-central-1","rules": {},"rules_count": 0},"eu-north-1": {"id": "eu-north-1","name": "eu-north-1","recorders": {},"recorders_count": 0,"region": "eu-north-1","rules": {},"rules_count": 0},"eu-west-1": {"id": "eu-west-1","name": "eu-west-1","recorders": {},"recorders_count": 0,"region": "eu-west-1","rules": {},"rules_count": 0},"eu-west-2": {"id": "eu-west-2","name": "eu-west-2","recorders": {},"recorders_count": 0,"region": "eu-west-2","rules": {},"rules_count": 0},"eu-west-3": {"id": "eu-west-3","name": "eu-west-3","recorders": {},"recorders_count": 0,"region": "eu-west-3","rules": {},"rules_count": 0},"sa-east-1": {"id": "sa-east-1","name": "sa-east-1","recorders": {},"recorders_count": 0,"region": "sa-east-1","rules": {},"rules_count": 0},"us-east-1": {"id": "us-east-1","name": "us-east-1","recorders": {},"recorders_count": 0,"region": "us-east-1","rules": {},"rules_count": 0},"us-east-2": {"id": "us-east-2","name": "us-east-2","recorders": {},"recorders_count": 0,"region": "us-east-2","rules": {},"rules_count": 0},"us-west-1": {"id": "us-west-1","name": "us-west-1","recorders": {},"recorders_count": 0,"region": "us-west-1","rules": {},"rules_count": 0},"us-west-2": {"id": "us-west-2","name": "us-west-2","recorders": {},"recorders_count": 0,"region": "us-west-2","rules": {},"rules_count": 0}},"regions_count": 17,"rules_count": 0},"directconnect": {"connections_count": 0,"filters": {},"findings": {},"regions": {"ap-northeast-1": {"connections": {},"connections_count": 0,"id": "ap-northeast-1","name": "ap-northeast-1","region": "ap-northeast-1"},"ap-northeast-2": {"connections": {},"connections_count": 0,"id": "ap-northeast-2","name": "ap-northeast-2","region": "ap-northeast-2"},"ap-northeast-3": {"connections": {},"connections_count": 0,"id": "ap-northeast-3","name": "ap-northeast-3","region": "ap-northeast-3"},"ap-south-1": {"connections": {},"connections_count": 0,"id": "ap-south-1","name": "ap-south-1","region": "ap-south-1"},"ap-southeast-1": {"connections": {},"connections_count": 0,"id": "ap-southeast-1","name": "ap-southeast-1","region": "ap-southeast-1"},"ap-southeast-2": {"connections": {},"connections_count": 0,"id": "ap-southeast-2","name": "ap-southeast-2","region": "ap-southeast-2"},"ca-central-1": {"connections": {},"connections_count": 0,"id": "ca-central-1","name": "ca-central-1","region": "ca-central-1"},"eu-central-1": {"connections": {},"connections_count": 0,"id": "eu-central-1","name": "eu-central-1","region": "eu-central-1"},"eu-north-1": {"connections": {},"connections_count": 0,"id": "eu-north-1","name": "eu-north-1","region": "eu-north-1"},"eu-west-1": {"connections": {},"connections_count": 0,"id": "eu-west-1","name": "eu-west-1","region": "eu-west-1"},"eu-west-2": {"connections": {},"connections_count": 0,"id": "eu-west-2","name": "eu-west-2","region": "eu-west-2"},"eu-west-3": {"connections": {},"connections_count": 0,"id": "eu-west-3","name": "eu-west-3","region": "eu-west-3"},"sa-east-1": {"connections": {},"connections_count": 0,"id": "sa-east-1","name": "sa-east-1","region": "sa-east-1"},"us-east-1": {"connections": {},"connections_count": 0,"id": "us-east-1","name": "us-east-1","region": "us-east-1"},"us-east-2": {"connections": {},"connections_count": 0,"id": "us-east-2","name": "us-east-2","region": "us-east-2"},"us-west-1": {"connections": {},"connections_count": 0,"id": "us-west-1","name": "us-west-1","region": "us-west-1"},"us-west-2": {"connections": {},"connections_count": 0,"id": "us-west-2","name": "us-west-2","region": "us-west-2"}},"regions_count": 17},"dynamodb": {"filters": {},"findings": {},"regions": {"ap-northeast-1": {"id": "ap-northeast-1","name": "ap-northeast-1","region": "ap-northeast-1","tables": {},"tables_count": 0},"ap-northeast-2": {"id": "ap-northeast-2","name": "ap-northeast-2","region": "ap-northeast-2","tables": {},"tables_count": 0},"ap-northeast-3": {"id": "ap-northeast-3","name": "ap-northeast-3","region": "ap-northeast-3","tables": {},"tables_count": 0},"ap-south-1": {"id": "ap-south-1","name": "ap-south-1","region": "ap-south-1","tables": {},"tables_count": 0},"ap-southeast-1": {"id": "ap-southeast-1","name": "ap-southeast-1","region": "ap-southeast-1","tables": {},"tables_count": 0},"ap-southeast-2": {"id": "ap-southeast-2","name": "ap-southeast-2","region": "ap-southeast-2","tables": {},"tables_count": 0},"ca-central-1": {"id": "ca-central-1","name": "ca-central-1","region": "ca-central-1","tables": {},"tables_count": 0},"eu-central-1": {"id": "eu-central-1","name": "eu-central-1","region": "eu-central-1","tables": {},"tables_count": 0},"eu-north-1": {"id": "eu-north-1","name": "eu-north-1","region": "eu-north-1","tables": {},"tables_count": 0},"eu-west-1": {"id": "eu-west-1","name": "eu-west-1","region": "eu-west-1","tables": {},"tables_count": 0},"eu-west-2": {"id": "eu-west-2","name": "eu-west-2","region": "eu-west-2","tables": {},"tables_count": 0},"eu-west-3": {"id": "eu-west-3","name": "eu-west-3","region": "eu-west-3","tables": {},"tables_count": 0},"sa-east-1": {"id": "sa-east-1","name": "sa-east-1","region": "sa-east-1","tables": {},"tables_count": 0},"us-east-1": {"id": "us-east-1","name": "us-east-1","region": "us-east-1","tables": {},"tables_count": 0},"us-east-2": {"id": "us-east-2","name": "us-east-2","region": "us-east-2","tables": {},"tables_count": 0},"us-west-1": {"id": "us-west-1","name": "us-west-1","region": "us-west-1","tables": {},"tables_count": 0},"us-west-2": {"id": "us-west-2","name": "us-west-2","region": "us-west-2","tables": {},"tables_count": 0}},"regions_count": 17,"tables_count": 0},"ec2": {"filters": {"ec2-instance-with-open-nacls": {"checked_items": 0,"compliance": null,"dashboard_name": "ENIs","description": "Public instance with open NACLs","display_path": "ec2.regions.id.vpcs.id.instances.id","flagged_items": 0,"items": [],"level": "","path": "ec2.regions.id.vpcs.id.instances.id.network_interfaces.id","rationale": "","references": null,"remediation": null,"service": "EC2"},"ec2-security-group-with-public-cidr-grant": {"checked_items": 6,"compliance": null,"dashboard_name": "Rules","description": "Security group whitelists public CIDRs","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 6,"items": ["ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.0-65535.cidrs.0.CIDR","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.0.CIDR","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.1.CIDR","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.2.CIDR","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.3.CIDR","ec2.regions.eu-west-3.vpcs.vpc-87d3fdee.security_groups.sg-000c4c21c24f75b85.rules.ingress.protocols.TCP.ports.22.cidrs.0.CIDR"],"level": "","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.ingress.protocols.id.ports.id.cidrs.id.CIDR","rationale": null,"references": null,"remediation": null,"service": "EC2"}},"findings": {"ec2-ami-public": {"checked_items": 0,"compliance": null,"dashboard_name": "Images","description": "Publicly Accessible AMI","flagged_items": 0,"id_suffix": "image_is_public","items": [],"level": "danger","path": "ec2.regions.id.images.id","rationale": "AMIs should never intentionally be made public. If they need to be shared this can be done with specific AWS accounts.","references": ["https://aws.amazon.com/security/security-bulletins/reminder-about-safely-sharing-and-using-public-amis/"],"remediation": null,"service": "EC2"},"ec2-default-security-group-in-use": {"checked_items": 20,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "4.4","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.4","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.3","version": "1.2.0"}],"dashboard_name": "Security groups","description": "Default Security Groups in Use","flagged_items": 0,"id_suffix": "default_in_use","items": [],"level": "warning","path": "ec2.regions.id.vpcs.id.security_groups.id","rationale": "The use of default security groups can indicate a lack of intentional enforcement of the principle of least privilege. Use custom security groups to ensure you are properly minimizing privilege and access.","references": ["https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-cis-controls-4.3"],"remediation": "Ensure resources are not within default security groups. Instead, create a custom security group tailored to each resource needs.","service": "EC2"},"ec2-default-security-group-with-rules": {"checked_items": 40,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "4.4","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.4","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.3","version": "1.2.0"}],"dashboard_name": "Rulesets","description": "Non-empty Rulesets for Default Security Groups","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 34,"id_suffix": "default_with_rules","items": ["ec2.regions.ap-northeast-1.vpcs.vpc-0cbc506a.security_groups.sg-6569b32b.rules.ingress.default_with_rules","ec2.regions.ap-northeast-1.vpcs.vpc-0cbc506a.security_groups.sg-6569b32b.rules.egress.default_with_rules","ec2.regions.ap-northeast-2.vpcs.vpc-73f44e18.security_groups.sg-854e9bfe.rules.ingress.default_with_rules","ec2.regions.ap-northeast-2.vpcs.vpc-73f44e18.security_groups.sg-854e9bfe.rules.egress.default_with_rules","ec2.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.security_groups.sg-9be71df6.rules.ingress.default_with_rules","ec2.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.security_groups.sg-9be71df6.rules.egress.default_with_rules","ec2.regions.ap-south-1.vpcs.vpc-2651a14d.security_groups.sg-3e983346.rules.ingress.default_with_rules","ec2.regions.ap-south-1.vpcs.vpc-2651a14d.security_groups.sg-3e983346.rules.egress.default_with_rules","ec2.regions.ap-southeast-1.vpcs.vpc-04ed1062.security_groups.sg-71eb4839.rules.ingress.default_with_rules","ec2.regions.ap-southeast-1.vpcs.vpc-04ed1062.security_groups.sg-71eb4839.rules.egress.default_with_rules","ec2.regions.ap-southeast-2.vpcs.vpc-5d22c33b.security_groups.sg-8a48ccc0.rules.ingress.default_with_rules","ec2.regions.ap-southeast-2.vpcs.vpc-5d22c33b.security_groups.sg-8a48ccc0.rules.egress.default_with_rules","ec2.regions.ca-central-1.vpcs.vpc-b5113ddd.security_groups.sg-62215504.rules.ingress.default_with_rules","ec2.regions.ca-central-1.vpcs.vpc-b5113ddd.security_groups.sg-62215504.rules.egress.default_with_rules","ec2.regions.eu-central-1.vpcs.vpc-78b43312.security_groups.sg-c1194bbf.rules.ingress.default_with_rules","ec2.regions.eu-central-1.vpcs.vpc-78b43312.security_groups.sg-c1194bbf.rules.egress.default_with_rules","ec2.regions.eu-north-1.vpcs.vpc-fa259d93.security_groups.sg-09c1e96a.rules.ingress.default_with_rules","ec2.regions.eu-north-1.vpcs.vpc-fa259d93.security_groups.sg-09c1e96a.rules.egress.default_with_rules","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-186a6a69.rules.ingress.default_with_rules","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-186a6a69.rules.egress.default_with_rules","ec2.regions.eu-west-2.vpcs.vpc-3fa2fa57.security_groups.sg-223b755a.rules.ingress.default_with_rules","ec2.regions.eu-west-2.vpcs.vpc-3fa2fa57.security_groups.sg-223b755a.rules.egress.default_with_rules","ec2.regions.eu-west-3.vpcs.vpc-87d3fdee.security_groups.sg-4cc9d827.rules.ingress.default_with_rules","ec2.regions.eu-west-3.vpcs.vpc-87d3fdee.security_groups.sg-4cc9d827.rules.egress.default_with_rules","ec2.regions.sa-east-1.vpcs.vpc-b14fa4d7.security_groups.sg-3965844c.rules.ingress.default_with_rules","ec2.regions.sa-east-1.vpcs.vpc-b14fa4d7.security_groups.sg-3965844c.rules.egress.default_with_rules","ec2.regions.us-east-1.vpcs.vpc-ba1cbdc7.security_groups.sg-4574a94e.rules.ingress.default_with_rules","ec2.regions.us-east-1.vpcs.vpc-ba1cbdc7.security_groups.sg-4574a94e.rules.egress.default_with_rules","ec2.regions.us-east-2.vpcs.vpc-e429ad8f.security_groups.sg-a81474db.rules.ingress.default_with_rules","ec2.regions.us-east-2.vpcs.vpc-e429ad8f.security_groups.sg-a81474db.rules.egress.default_with_rules","ec2.regions.us-west-1.vpcs.vpc-6e6fa508.security_groups.sg-778f4e3e.rules.ingress.default_with_rules","ec2.regions.us-west-1.vpcs.vpc-6e6fa508.security_groups.sg-778f4e3e.rules.egress.default_with_rules","ec2.regions.us-west-2.vpcs.vpc-d45709ac.security_groups.sg-a9b5628e.rules.ingress.default_with_rules","ec2.regions.us-west-2.vpcs.vpc-d45709ac.security_groups.sg-a9b5628e.rules.egress.default_with_rules"],"level": "warning","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id","rationale": "The default security group created in each VPC comes with rules allowing all inbound traffic from instances assigned to the same security group, as well as all outbound traffic. In order to improve system hardening, you should remove all rules from the default security groups so that they restricts all traffic. Should an instance be created without custom security groups, it will inherit the default security group and be unable to communicate with other instances within the VPC until the required custom security groups are assigned.","references": ["https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-cis-controls-4.3"],"remediation": "Ensure the default security group of every VPC restricts all traffic","service": "EC2"},"ec2-ebs-snapshot-not-encrypted": {"checked_items": 0,"compliance": null,"dashboard_name": "Snapshots","description": "EBS Snapshot Not Encrypted","flagged_items": 0,"id_suffix": "encrypted","items": [],"level": "danger","path": "ec2.regions.id.snapshots.id","rationale": "Data-at-rest should be encrypted.","references": ["https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html"],"remediation": null,"service": "EC2"},"ec2-ebs-snapshot-public": {"checked_items": 0,"compliance": null,"dashboard_name": "Snapshots","description": "Public EBS Snapshot","flagged_items": 0,"id_suffix": "public","items": [],"level": "danger","path": "ec2.regions.id.snapshots.id","rationale": "Snapshots should never be public, as this risks exposing sensitive data.","references": ["https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-modifying-snapshot-permissions.html"],"remediation": null,"service": "EC2"},"ec2-ebs-volume-not-encrypted": {"checked_items": 0,"compliance": null,"dashboard_name": "Volumes","description": "EBS Volume Not Encrypted","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.volumes.id","rationale": "Enabling encryption of EBS volumes ensures that data is encrypted both at-rest and in-transit (between an instance and its attached EBS storage).","references": ["https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html"],"remediation": null,"service": "EC2"},"ec2-instance-with-user-data-secrets": {"checked_items": 0,"compliance": null,"dashboard_name": "Instances","description": "Potential Secret in Instance User Data","flagged_items": 0,"id_suffix": "potential_secrets","items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.instances.id","rationale": "It was detected that the EC2 instance was configured with user data, which could potentially include secrets. Although user data can only be accessed from within the instance itself, the data is not protected by cryptographic methods. Anyone who can access the instance can view its metadata. It should therefore be ensured that sensitive data, such as passwords and SSH keys, are not stored as user data.","references": ["https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html"],"remediation": null,"service": "EC2"},"ec2-security-group-opens-DNS-port-to-all": {"checked_items": 26,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.2.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.2.0"}],"dashboard_name": "Rules","description": "Security Group Opens DNS Port to All","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "The security group was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.","references": null,"remediation": "Remove the inbound rules that expose open ports","service": "EC2"},"ec2-security-group-opens-MongoDB-port-to-all": {"checked_items": 26,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.2.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.2.0"}],"dashboard_name": "Rules","description": "Security Group Opens MongoDB Port to All","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "The security group was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.","references": null,"remediation": "Remove the inbound rules that expose open ports","service": "EC2"},"ec2-security-group-opens-MsSQL-port-to-all": {"checked_items": 26,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.2.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.2.0"}],"dashboard_name": "Rules","description": "Security Group Opens MsSQL Port to All","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "The security group was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.","references": null,"remediation": "Remove the inbound rules that expose open ports","service": "EC2"},"ec2-security-group-opens-MySQL-port-to-all": {"checked_items": 26,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.2.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.2.0"}],"dashboard_name": "Rules","description": "Security Group Opens MySQL Port to All","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "The security group was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.","references": null,"remediation": "Remove the inbound rules that expose open ports","service": "EC2"},"ec2-security-group-opens-NFS-port-to-all": {"checked_items": 26,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.2.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.2.0"}],"dashboard_name": "Rules","description": "Security Group Opens NFS Port to All","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "The security group was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.","references": null,"remediation": "Remove the inbound rules that expose open ports","service": "EC2"},"ec2-security-group-opens-Oracle DB-port-to-all": {"checked_items": 26,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.2.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.2.0"}],"dashboard_name": "Rules","description": "Security Group Opens Oracle DB Port to All","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "The security group was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.","references": null,"remediation": "Remove the inbound rules that expose open ports","service": "EC2"},"ec2-security-group-opens-PostgreSQL-port-to-all": {"checked_items": 26,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.2.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.2.0"}],"dashboard_name": "Rules","description": "Security Group Opens PostgreSQL Port to All","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "The security group was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.","references": null,"remediation": "Remove the inbound rules that expose open ports","service": "EC2"},"ec2-security-group-opens-RDP-port-to-all": {"checked_items": 26,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.2.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.2.0"}],"dashboard_name": "Rules","description": "Security Group Opens RDP Port to All","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "The security group was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.","references": null,"remediation": "Remove the inbound rules that expose open ports","service": "EC2"},"ec2-security-group-opens-SMTP-port-to-all": {"checked_items": 26,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.2.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.2.0"}],"dashboard_name": "Rules","description": "Security Group Opens SMTP Port to All","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "The security group was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.","references": null,"remediation": "Remove the inbound rules that expose open ports","service": "EC2"},"ec2-security-group-opens-SSH-port-to-all": {"checked_items": 26,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.1","version": "1.2.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.2","version": "1.2.0"}],"dashboard_name": "Rules","description": "Security Group Opens SSH Port to All","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "The security group was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.","references": null,"remediation": "Remove the inbound rules that expose open ports","service": "EC2"},"ec2-security-group-opens-TCP-port-to-all": {"checked_items": 26,"compliance": null,"dashboard_name": "Rules","description": "Security Group Opens TCP Port to All","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "warning","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "The security group was found to be exposing a port to all source addresses. Ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.","references": null,"remediation": null,"service": "EC2"},"ec2-security-group-opens-UDP-port-to-all": {"checked_items": 26,"compliance": null,"dashboard_name": "Rules","description": "Security Group Opens UDP Port to All","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "warning","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "The security group was found to be exposing a port to all source addresses. Ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.","references": null,"remediation": null,"service": "EC2"},"ec2-security-group-opens-all-ports": {"checked_items": 45,"compliance": null,"dashboard_name": "Rules","description": "Security Group Opens All Ports","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 21,"items": ["ec2.regions.ap-northeast-1.vpcs.vpc-0cbc506a.security_groups.sg-6569b32b.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.ap-northeast-2.vpcs.vpc-73f44e18.security_groups.sg-854e9bfe.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.security_groups.sg-9be71df6.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.ap-south-1.vpcs.vpc-2651a14d.security_groups.sg-3e983346.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.ap-southeast-1.vpcs.vpc-04ed1062.security_groups.sg-71eb4839.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.ap-southeast-2.vpcs.vpc-5d22c33b.security_groups.sg-8a48ccc0.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.ca-central-1.vpcs.vpc-b5113ddd.security_groups.sg-62215504.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.eu-central-1.vpcs.vpc-78b43312.security_groups.sg-c1194bbf.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.eu-north-1.vpcs.vpc-fa259d93.security_groups.sg-09c1e96a.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-02063087593480392.rules.ingress.protocols.TCP.ports.0-65535","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-02063087593480392.rules.ingress.protocols.UDP.ports.0-65535","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.0-65535","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.UDP.ports.0-65535","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-186a6a69.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.eu-west-2.vpcs.vpc-3fa2fa57.security_groups.sg-223b755a.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.eu-west-3.vpcs.vpc-87d3fdee.security_groups.sg-4cc9d827.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.sa-east-1.vpcs.vpc-b14fa4d7.security_groups.sg-3965844c.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.us-east-1.vpcs.vpc-ba1cbdc7.security_groups.sg-4574a94e.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.us-east-2.vpcs.vpc-e429ad8f.security_groups.sg-a81474db.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.us-west-1.vpcs.vpc-6e6fa508.security_groups.sg-778f4e3e.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.us-west-2.vpcs.vpc-d45709ac.security_groups.sg-a9b5628e.rules.ingress.protocols.ALL.ports.1-65535"],"level": "warning","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id","rationale": "It was detected that all ports in the security group are open, which creates a wider attack surface for resources assigned to it. Open ports should be reduced to the minimum needed to correctly operate.","references": null,"remediation": null,"service": "EC2"},"ec2-security-group-opens-all-ports-to-all": {"checked_items": 26,"compliance": null,"dashboard_name": "Rules","description": "Security Group Opens All Ports to All","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "It was detected that all ports in the security group are open, and any source IP address could send traffic to these ports, which creates a wider attack surface for resources assigned to it. Open ports should be reduced to the minimum needed to correctly operate and, when possible, source address restrictions should be implemented.","references": null,"remediation": null,"service": "EC2"},"ec2-security-group-opens-all-ports-to-self": {"checked_items": 29,"compliance": null,"dashboard_name": "Rules","description": "Unrestricted Network Traffic within Security Group","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 21,"items": ["ec2.regions.ap-northeast-1.vpcs.vpc-0cbc506a.security_groups.sg-6569b32b.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0","ec2.regions.ap-northeast-2.vpcs.vpc-73f44e18.security_groups.sg-854e9bfe.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0","ec2.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.security_groups.sg-9be71df6.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0","ec2.regions.ap-south-1.vpcs.vpc-2651a14d.security_groups.sg-3e983346.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0","ec2.regions.ap-southeast-1.vpcs.vpc-04ed1062.security_groups.sg-71eb4839.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0","ec2.regions.ap-southeast-2.vpcs.vpc-5d22c33b.security_groups.sg-8a48ccc0.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0","ec2.regions.ca-central-1.vpcs.vpc-b5113ddd.security_groups.sg-62215504.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0","ec2.regions.eu-central-1.vpcs.vpc-78b43312.security_groups.sg-c1194bbf.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0","ec2.regions.eu-north-1.vpcs.vpc-fa259d93.security_groups.sg-09c1e96a.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-02063087593480392.rules.ingress.protocols.TCP.ports.0-65535.security_groups.0","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-02063087593480392.rules.ingress.protocols.UDP.ports.0-65535.security_groups.1","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.0-65535.security_groups.1","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.UDP.ports.0-65535.security_groups.0","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-186a6a69.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0","ec2.regions.eu-west-2.vpcs.vpc-3fa2fa57.security_groups.sg-223b755a.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0","ec2.regions.eu-west-3.vpcs.vpc-87d3fdee.security_groups.sg-4cc9d827.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0","ec2.regions.sa-east-1.vpcs.vpc-b14fa4d7.security_groups.sg-3965844c.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0","ec2.regions.us-east-1.vpcs.vpc-ba1cbdc7.security_groups.sg-4574a94e.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0","ec2.regions.us-east-2.vpcs.vpc-e429ad8f.security_groups.sg-a81474db.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0","ec2.regions.us-west-1.vpcs.vpc-6e6fa508.security_groups.sg-778f4e3e.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0","ec2.regions.us-west-2.vpcs.vpc-d45709ac.security_groups.sg-a9b5628e.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0"],"level": "warning","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.security_groups.id","rationale": "This configuration goes against organizational policies.","references": null,"remediation": null,"service": "EC2"},"ec2-security-group-opens-icmp-to-all": {"checked_items": 26,"compliance": null,"dashboard_name": "Rules","description": "Security Group Allows ICMP Traffic to All","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "warning","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "ICMP traffic was allowed to the resources assigned to this security group without restriction of the source address. This could potentially be leveraged by an attacker trying to perform an attack or gather information about the deployed infrastructure.","references": null,"remediation": null,"service": "EC2"},"ec2-security-group-opens-plaintext-port-FTP": {"checked_items": 45,"compliance": null,"dashboard_name": "Rules","description": "Security Group Opens FTP Port","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id","rationale": "Ports associated with plaintext protocols have been found to be open in this security group. Plaintext protocols should be replaced with more secure alternatives, as the data in transit may be monitored and could, potentially, be subject to tampering.","references": null,"remediation": null,"service": "EC2"},"ec2-security-group-opens-plaintext-port-Telnet": {"checked_items": 45,"compliance": null,"dashboard_name": "Rules","description": "Security Group Opens Telnet Port","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id","rationale": "Ports associated with plaintext protocols have been found to be open in this security group. Plaintext protocols should be replaced with more secure alternatives, as the data in transit may be monitored and could, potentially, be subject to tampering.","references": null,"remediation": null,"service": "EC2"},"ec2-security-group-opens-port-range": {"checked_items": 45,"compliance": null,"dashboard_name": "Rules","description": "Security Group Uses Port Range","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 17,"items": ["ec2.regions.ap-northeast-1.vpcs.vpc-0cbc506a.security_groups.sg-6569b32b.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.ap-northeast-2.vpcs.vpc-73f44e18.security_groups.sg-854e9bfe.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.security_groups.sg-9be71df6.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.ap-south-1.vpcs.vpc-2651a14d.security_groups.sg-3e983346.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.ap-southeast-1.vpcs.vpc-04ed1062.security_groups.sg-71eb4839.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.ap-southeast-2.vpcs.vpc-5d22c33b.security_groups.sg-8a48ccc0.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.ca-central-1.vpcs.vpc-b5113ddd.security_groups.sg-62215504.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.eu-central-1.vpcs.vpc-78b43312.security_groups.sg-c1194bbf.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.eu-north-1.vpcs.vpc-fa259d93.security_groups.sg-09c1e96a.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-186a6a69.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.eu-west-2.vpcs.vpc-3fa2fa57.security_groups.sg-223b755a.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.eu-west-3.vpcs.vpc-87d3fdee.security_groups.sg-4cc9d827.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.sa-east-1.vpcs.vpc-b14fa4d7.security_groups.sg-3965844c.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.us-east-1.vpcs.vpc-ba1cbdc7.security_groups.sg-4574a94e.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.us-east-2.vpcs.vpc-e429ad8f.security_groups.sg-a81474db.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.us-west-1.vpcs.vpc-6e6fa508.security_groups.sg-778f4e3e.rules.ingress.protocols.ALL.ports.1-65535","ec2.regions.us-west-2.vpcs.vpc-d45709ac.security_groups.sg-a9b5628e.rules.ingress.protocols.ALL.ports.1-65535"],"level": "warning","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id","rationale": "It was found that the security group was using port ranges. Sometimes, ranges could include unintended ports that should not be exposed. As a result, when possible, explicit port lists should be used instead","references": null,"remediation": null,"service": "EC2"},"ec2-security-group-whitelists-aws": {"checked_items": 26,"compliance": null,"dashboard_name": "Rules","description": "Security Group Whitelists AWS CIDRs","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 4,"items": ["ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.0.CIDR","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.1.CIDR","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.2.CIDR","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.3.CIDR"],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "The AWS IP ranges contain addresses which can be assigned to EC2 instances in any AWS account, as well as services which can be used to interact with any AWS account. Consequently, allowing these ranges potentially exposes your AWS account to external interactions.","references": null,"remediation": null,"service": "EC2"},"ec2-unused-security-group": {"checked_items": 20,"compliance": null,"dashboard_name": "Security groups","description": "Unused Security Group","flagged_items": 3,"items": ["ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-02063087593480392","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171","ec2.regions.eu-west-3.vpcs.vpc-87d3fdee.security_groups.sg-000c4c21c24f75b85"],"level": "warning","path": "ec2.regions.id.vpcs.id.security_groups.id","rationale": " Non-default security groups were defined which were unused and may not be required. This being the case, their existence in the configuration increases the risk that they may be inappropriately assigned. The unused security groups should be reviewed and removed if no longer required.","references": ["https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html"],"remediation": null,"service": "EC2"}},"images_count": 0,"instances_count": 0,"network_interfaces_count": 0,"number_of_regions_with_instances": 0,"regions": {"ap-northeast-1": {"id": "ap-northeast-1","images": {},"images_count": 0,"instances_availability_zones": 0,"instances_count": 0,"name": "ap-northeast-1","network_interfaces_count": 0,"region": "ap-northeast-1","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpcs": {"vpc-0cbc506a": {"arn": "arn:aws:vpc:ap-northeast-1:430150006394:virtual-private-cloud/vpc-0cbc506a","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-0cbc506a","instances": {},"instances_count": 0,"name": "vpc-0cbc506a","network_interfaces": {},"network_interfaces_count": 0,"security_groups": {"sg-6569b32b": {"arn": "arn:aws:ec2:ap-northeast-1:430150006394:security-group/sg-6569b32b","description": "default VPC security group","id": "sg-6569b32b","is_default_configuration": true,"name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"security_groups": [{"GroupId": "sg-6569b32b","GroupName": "default","UserId": "430150006394"}]}}}}}}}},"security_groups_count": 1,"state": "available"}},"vpcs_count": 1},"ap-northeast-2": {"id": "ap-northeast-2","images": {},"images_count": 0,"instances_availability_zones": 0,"instances_count": 0,"name": "ap-northeast-2","network_interfaces_count": 0,"region": "ap-northeast-2","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpcs": {"vpc-73f44e18": {"arn": "arn:aws:vpc:ap-northeast-2:430150006394:virtual-private-cloud/vpc-73f44e18","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-73f44e18","instances": {},"instances_count": 0,"name": "vpc-73f44e18","network_interfaces": {},"network_interfaces_count": 0,"security_groups": {"sg-854e9bfe": {"arn": "arn:aws:ec2:ap-northeast-2:430150006394:security-group/sg-854e9bfe","description": "default VPC security group","id": "sg-854e9bfe","is_default_configuration": true,"name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"security_groups": [{"GroupId": "sg-854e9bfe","GroupName": "default","UserId": "430150006394"}]}}}}}}}},"security_groups_count": 1,"state": "available"}},"vpcs_count": 1},"ap-northeast-3": {"id": "ap-northeast-3","images": {},"images_count": 0,"instances_availability_zones": 0,"instances_count": 0,"name": "ap-northeast-3","network_interfaces_count": 0,"region": "ap-northeast-3","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpcs": {"vpc-47b7dd2e": {"arn": "arn:aws:vpc:ap-northeast-3:430150006394:virtual-private-cloud/vpc-47b7dd2e","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-47b7dd2e","instances": {},"instances_count": 0,"name": "vpc-47b7dd2e","network_interfaces": {},"network_interfaces_count": 0,"security_groups": {"sg-9be71df6": {"arn": "arn:aws:ec2:ap-northeast-3:430150006394:security-group/sg-9be71df6","description": "default VPC security group","id": "sg-9be71df6","is_default_configuration": true,"name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"security_groups": [{"GroupId": "sg-9be71df6","GroupName": "default","UserId": "430150006394"}]}}}}}}}},"security_groups_count": 1,"state": "available"}},"vpcs_count": 1},"ap-south-1": {"id": "ap-south-1","images": {},"images_count": 0,"instances_availability_zones": 0,"instances_count": 0,"name": "ap-south-1","network_interfaces_count": 0,"region": "ap-south-1","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpcs": {"vpc-2651a14d": {"arn": "arn:aws:vpc:ap-south-1:430150006394:virtual-private-cloud/vpc-2651a14d","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-2651a14d","instances": {},"instances_count": 0,"name": "vpc-2651a14d","network_interfaces": {},"network_interfaces_count": 0,"security_groups": {"sg-3e983346": {"arn": "arn:aws:ec2:ap-south-1:430150006394:security-group/sg-3e983346","description": "default VPC security group","id": "sg-3e983346","is_default_configuration": true,"name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"security_groups": [{"GroupId": "sg-3e983346","GroupName": "default","UserId": "430150006394"}]}}}}}}}},"security_groups_count": 1,"state": "available"}},"vpcs_count": 1},"ap-southeast-1": {"id": "ap-southeast-1","images": {},"images_count": 0,"instances_availability_zones": 0,"instances_count": 0,"name": "ap-southeast-1","network_interfaces_count": 0,"region": "ap-southeast-1","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpcs": {"vpc-04ed1062": {"arn": "arn:aws:vpc:ap-southeast-1:430150006394:virtual-private-cloud/vpc-04ed1062","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-04ed1062","instances": {},"instances_count": 0,"name": "vpc-04ed1062","network_interfaces": {},"network_interfaces_count": 0,"security_groups": {"sg-71eb4839": {"arn": "arn:aws:ec2:ap-southeast-1:430150006394:security-group/sg-71eb4839","description": "default VPC security group","id": "sg-71eb4839","is_default_configuration": true,"name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"security_groups": [{"GroupId": "sg-71eb4839","GroupName": "default","UserId": "430150006394"}]}}}}}}}},"security_groups_count": 1,"state": "available"}},"vpcs_count": 1},"ap-southeast-2": {"id": "ap-southeast-2","images": {},"images_count": 0,"instances_availability_zones": 0,"instances_count": 0,"name": "ap-southeast-2","network_interfaces_count": 0,"region": "ap-southeast-2","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpcs": {"vpc-5d22c33b": {"arn": "arn:aws:vpc:ap-southeast-2:430150006394:virtual-private-cloud/vpc-5d22c33b","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-5d22c33b","instances": {},"instances_count": 0,"name": "vpc-5d22c33b","network_interfaces": {},"network_interfaces_count": 0,"security_groups": {"sg-8a48ccc0": {"arn": "arn:aws:ec2:ap-southeast-2:430150006394:security-group/sg-8a48ccc0","description": "default VPC security group","id": "sg-8a48ccc0","is_default_configuration": true,"name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"security_groups": [{"GroupId": "sg-8a48ccc0","GroupName": "default","UserId": "430150006394"}]}}}}}}}},"security_groups_count": 1,"state": "available"}},"vpcs_count": 1},"ca-central-1": {"id": "ca-central-1","images": {},"images_count": 0,"instances_availability_zones": 0,"instances_count": 0,"name": "ca-central-1","network_interfaces_count": 0,"region": "ca-central-1","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpcs": {"vpc-b5113ddd": {"arn": "arn:aws:vpc:ca-central-1:430150006394:virtual-private-cloud/vpc-b5113ddd","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-b5113ddd","instances": {},"instances_count": 0,"name": "vpc-b5113ddd","network_interfaces": {},"network_interfaces_count": 0,"security_groups": {"sg-62215504": {"arn": "arn:aws:ec2:ca-central-1:430150006394:security-group/sg-62215504","description": "default VPC security group","id": "sg-62215504","is_default_configuration": true,"name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"security_groups": [{"GroupId": "sg-62215504","GroupName": "default","UserId": "430150006394"}]}}}}}}}},"security_groups_count": 1,"state": "available"}},"vpcs_count": 1},"eu-central-1": {"id": "eu-central-1","images": {},"images_count": 0,"instances_availability_zones": 0,"instances_count": 0,"name": "eu-central-1","network_interfaces_count": 0,"region": "eu-central-1","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpcs": {"vpc-78b43312": {"arn": "arn:aws:vpc:eu-central-1:430150006394:virtual-private-cloud/vpc-78b43312","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-78b43312","instances": {},"instances_count": 0,"name": "vpc-78b43312","network_interfaces": {},"network_interfaces_count": 0,"security_groups": {"sg-c1194bbf": {"arn": "arn:aws:ec2:eu-central-1:430150006394:security-group/sg-c1194bbf","description": "default VPC security group","id": "sg-c1194bbf","is_default_configuration": true,"name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"security_groups": [{"GroupId": "sg-c1194bbf","GroupName": "default","UserId": "430150006394"}]}}}}}}}},"security_groups_count": 1,"state": "available"}},"vpcs_count": 1},"eu-north-1": {"id": "eu-north-1","images": {},"images_count": 0,"instances_availability_zones": 0,"instances_count": 0,"name": "eu-north-1","network_interfaces_count": 0,"region": "eu-north-1","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpcs": {"vpc-fa259d93": {"arn": "arn:aws:vpc:eu-north-1:430150006394:virtual-private-cloud/vpc-fa259d93","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-fa259d93","instances": {},"instances_count": 0,"name": "vpc-fa259d93","network_interfaces": {},"network_interfaces_count": 0,"security_groups": {"sg-09c1e96a": {"arn": "arn:aws:ec2:eu-north-1:430150006394:security-group/sg-09c1e96a","description": "default VPC security group","id": "sg-09c1e96a","is_default_configuration": true,"name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"security_groups": [{"GroupId": "sg-09c1e96a","GroupName": "default","UserId": "430150006394"}]}}}}}}}},"security_groups_count": 1,"state": "available"}},"vpcs_count": 1},"eu-west-1": {"id": "eu-west-1","images": {},"images_count": 0,"instances_availability_zones": 0,"instances_count": 0,"name": "eu-west-1","network_interfaces_count": 0,"region": "eu-west-1","security_groups_count": 3,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpcs": {"vpc-f24c7994": {"arn": "arn:aws:vpc:eu-west-1:430150006394:virtual-private-cloud/vpc-f24c7994","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-f24c7994","instances": {},"instances_count": 0,"name": "vpc-f24c7994","network_interfaces": {},"network_interfaces_count": 0,"security_groups": {"sg-02063087593480392": {"arn": "arn:aws:ec2:eu-west-1:430150006394:security-group/sg-02063087593480392","description": "Slave group for Elastic MapReduce created on 2019-01-26T08:00:38.387Z","id": "sg-02063087593480392","is_default_configuration": false,"name": "ElasticMapReduce-slave","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 6,"protocols": {"ICMP": {"ports": {"ALL": {"security_groups": [{"GroupId": "sg-0c59ae38c42100171","GroupName": "ElasticMapReduce-master","UserId": "430150006394"},{"GroupId": "sg-02063087593480392","GroupName": "ElasticMapReduce-slave","UserId": "430150006394"}]}}},"TCP": {"ports": {"0-65535": {"security_groups": [{"GroupId": "sg-02063087593480392","GroupName": "ElasticMapReduce-slave","UserId": "430150006394"},{"GroupId": "sg-0c59ae38c42100171","GroupName": "ElasticMapReduce-master","UserId": "430150006394"}]}}},"UDP": {"ports": {"0-65535": {"security_groups": [{"GroupId": "sg-0c59ae38c42100171","GroupName": "ElasticMapReduce-master","UserId": "430150006394"},{"GroupId": "sg-02063087593480392","GroupName": "ElasticMapReduce-slave","UserId": "430150006394"}]}}}}}}},"sg-0c59ae38c42100171": {"arn": "arn:aws:ec2:eu-west-1:430150006394:security-group/sg-0c59ae38c42100171","description": "Master group for Elastic MapReduce created on 2019-01-26T08:00:38.387Z","id": "sg-0c59ae38c42100171","is_default_configuration": false,"name": "ElasticMapReduce-master","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 11,"protocols": {"ICMP": {"ports": {"ALL": {"security_groups": [{"GroupId": "sg-0c59ae38c42100171","GroupName": "ElasticMapReduce-master","UserId": "430150006394"},{"GroupId": "sg-02063087593480392","GroupName": "ElasticMapReduce-slave","UserId": "430150006394"}]}}},"TCP": {"ports": {"0-65535": {"cidrs": [{"CIDR": "88.171.207.128/30"}],"security_groups": [{"GroupId": "sg-02063087593480392","GroupName": "ElasticMapReduce-slave","UserId": "430150006394"},{"GroupId": "sg-0c59ae38c42100171","GroupName": "ElasticMapReduce-master","UserId": "430150006394"}]},"8443": {"cidrs": [{"CIDR": "54.239.99.0/24"},{"CIDR": "54.240.197.0/24"},{"CIDR": "87.238.80.64/29"},{"CIDR": "87.238.84.64/29"}]}}},"UDP": {"ports": {"0-65535": {"security_groups": [{"GroupId": "sg-0c59ae38c42100171","GroupName": "ElasticMapReduce-master","UserId": "430150006394"},{"GroupId": "sg-02063087593480392","GroupName": "ElasticMapReduce-slave","UserId": "430150006394"}]}}}}}}},"sg-186a6a69": {"arn": "arn:aws:ec2:eu-west-1:430150006394:security-group/sg-186a6a69","description": "default VPC security group","id": "sg-186a6a69","is_default_configuration": true,"name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"security_groups": [{"GroupId": "sg-186a6a69","GroupName": "default","UserId": "430150006394"}]}}}}}}}},"security_groups_count": 3,"state": "available"}},"vpcs_count": 1},"eu-west-2": {"id": "eu-west-2","images": {},"images_count": 0,"instances_availability_zones": 0,"instances_count": 0,"name": "eu-west-2","network_interfaces_count": 0,"region": "eu-west-2","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpcs": {"vpc-3fa2fa57": {"arn": "arn:aws:vpc:eu-west-2:430150006394:virtual-private-cloud/vpc-3fa2fa57","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-3fa2fa57","instances": {},"instances_count": 0,"name": "vpc-3fa2fa57","network_interfaces": {},"network_interfaces_count": 0,"security_groups": {"sg-223b755a": {"arn": "arn:aws:ec2:eu-west-2:430150006394:security-group/sg-223b755a","description": "default VPC security group","id": "sg-223b755a","is_default_configuration": true,"name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"security_groups": [{"GroupId": "sg-223b755a","GroupName": "default","UserId": "430150006394"}]}}}}}}}},"security_groups_count": 1,"state": "available"}},"vpcs_count": 1},"eu-west-3": {"id": "eu-west-3","images": {},"images_count": 0,"instances_availability_zones": 0,"instances_count": 0,"name": "eu-west-3","network_interfaces_count": 0,"region": "eu-west-3","security_groups_count": 2,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpcs": {"vpc-87d3fdee": {"arn": "arn:aws:vpc:eu-west-3:430150006394:virtual-private-cloud/vpc-87d3fdee","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-87d3fdee","instances": {},"instances_count": 0,"name": "vpc-87d3fdee","network_interfaces": {},"network_interfaces_count": 0,"security_groups": {"sg-000c4c21c24f75b85": {"arn": "arn:aws:ec2:eu-west-3:430150006394:security-group/sg-000c4c21c24f75b85","description": "launch-wizard-1 created 2019-12-23T12:17:14.882+01:00","id": "sg-000c4c21c24f75b85","is_default_configuration": false,"name": "launch-wizard-1","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"TCP": {"ports": {"22": {"cidrs": [{"CIDR": "86.250.138.62/32"}]}}}}}}},"sg-4cc9d827": {"arn": "arn:aws:ec2:eu-west-3:430150006394:security-group/sg-4cc9d827","description": "default VPC security group","id": "sg-4cc9d827","is_default_configuration": true,"name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"security_groups": [{"GroupId": "sg-4cc9d827","GroupName": "default","UserId": "430150006394"}]}}}}}}}},"security_groups_count": 2,"state": "available"}},"vpcs_count": 1},"sa-east-1": {"id": "sa-east-1","images": {},"images_count": 0,"instances_availability_zones": 0,"instances_count": 0,"name": "sa-east-1","network_interfaces_count": 0,"region": "sa-east-1","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpcs": {"vpc-b14fa4d7": {"arn": "arn:aws:vpc:sa-east-1:430150006394:virtual-private-cloud/vpc-b14fa4d7","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-b14fa4d7","instances": {},"instances_count": 0,"name": "vpc-b14fa4d7","network_interfaces": {},"network_interfaces_count": 0,"security_groups": {"sg-3965844c": {"arn": "arn:aws:ec2:sa-east-1:430150006394:security-group/sg-3965844c","description": "default VPC security group","id": "sg-3965844c","is_default_configuration": true,"name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"security_groups": [{"GroupId": "sg-3965844c","GroupName": "default","UserId": "430150006394"}]}}}}}}}},"security_groups_count": 1,"state": "available"}},"vpcs_count": 1},"us-east-1": {"id": "us-east-1","images": {},"images_count": 0,"instances_availability_zones": 0,"instances_count": 0,"name": "us-east-1","network_interfaces_count": 0,"region": "us-east-1","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpcs": {"vpc-ba1cbdc7": {"arn": "arn:aws:vpc:us-east-1:430150006394:virtual-private-cloud/vpc-ba1cbdc7","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-ba1cbdc7","instances": {},"instances_count": 0,"name": "vpc-ba1cbdc7","network_interfaces": {},"network_interfaces_count": 0,"security_groups": {"sg-4574a94e": {"arn": "arn:aws:ec2:us-east-1:430150006394:security-group/sg-4574a94e","description": "default VPC security group","id": "sg-4574a94e","is_default_configuration": true,"name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"security_groups": [{"GroupId": "sg-4574a94e","GroupName": "default","UserId": "430150006394"}]}}}}}}}},"security_groups_count": 1,"state": "available"}},"vpcs_count": 1},"us-east-2": {"id": "us-east-2","images": {},"images_count": 0,"instances_availability_zones": 0,"instances_count": 0,"name": "us-east-2","network_interfaces_count": 0,"region": "us-east-2","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpcs": {"vpc-e429ad8f": {"arn": "arn:aws:vpc:us-east-2:430150006394:virtual-private-cloud/vpc-e429ad8f","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-e429ad8f","instances": {},"instances_count": 0,"name": "vpc-e429ad8f","network_interfaces": {},"network_interfaces_count": 0,"security_groups": {"sg-a81474db": {"arn": "arn:aws:ec2:us-east-2:430150006394:security-group/sg-a81474db","description": "default VPC security group","id": "sg-a81474db","is_default_configuration": true,"name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"security_groups": [{"GroupId": "sg-a81474db","GroupName": "default","UserId": "430150006394"}]}}}}}}}},"security_groups_count": 1,"state": "available"}},"vpcs_count": 1},"us-west-1": {"id": "us-west-1","images": {},"images_count": 0,"instances_availability_zones": 0,"instances_count": 0,"name": "us-west-1","network_interfaces_count": 0,"region": "us-west-1","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpcs": {"vpc-6e6fa508": {"arn": "arn:aws:vpc:us-west-1:430150006394:virtual-private-cloud/vpc-6e6fa508","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-6e6fa508","instances": {},"instances_count": 0,"name": "vpc-6e6fa508","network_interfaces": {},"network_interfaces_count": 0,"security_groups": {"sg-778f4e3e": {"arn": "arn:aws:ec2:us-west-1:430150006394:security-group/sg-778f4e3e","description": "default VPC security group","id": "sg-778f4e3e","is_default_configuration": true,"name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"security_groups": [{"GroupId": "sg-778f4e3e","GroupName": "default","UserId": "430150006394"}]}}}}}}}},"security_groups_count": 1,"state": "available"}},"vpcs_count": 1},"us-west-2": {"id": "us-west-2","images": {},"images_count": 0,"instances_availability_zones": 0,"instances_count": 0,"name": "us-west-2","network_interfaces_count": 0,"region": "us-west-2","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpcs": {"vpc-d45709ac": {"arn": "arn:aws:vpc:us-west-2:430150006394:virtual-private-cloud/vpc-d45709ac","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-d45709ac","instances": {},"instances_count": 0,"name": "vpc-d45709ac","network_interfaces": {},"network_interfaces_count": 0,"security_groups": {"sg-a9b5628e": {"arn": "arn:aws:ec2:us-west-2:430150006394:security-group/sg-a9b5628e","description": "default VPC security group","id": "sg-a9b5628e","is_default_configuration": true,"name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"1-65535": {"security_groups": [{"GroupId": "sg-a9b5628e","GroupName": "default","UserId": "430150006394"}]}}}}}}}},"security_groups_count": 1,"state": "available"}},"vpcs_count": 1}},"regions_count": 17,"security_groups_count": 20,"snapshots_count": 0,"volumes_count": 0},"efs": {"filesystems_count": 0,"filters": {},"findings": {},"regions": {"ap-northeast-1": {"filesystems": {},"filesystems_count": 0,"id": "ap-northeast-1","name": "ap-northeast-1","region": "ap-northeast-1"},"ap-northeast-2": {"filesystems": {},"filesystems_count": 0,"id": "ap-northeast-2","name": "ap-northeast-2","region": "ap-northeast-2"},"ap-northeast-3": {"filesystems": {},"filesystems_count": 0,"id": "ap-northeast-3","name": "ap-northeast-3","region": "ap-northeast-3"},"ap-south-1": {"filesystems": {},"filesystems_count": 0,"id": "ap-south-1","name": "ap-south-1","region": "ap-south-1"},"ap-southeast-1": {"filesystems": {},"filesystems_count": 0,"id": "ap-southeast-1","name": "ap-southeast-1","region": "ap-southeast-1"},"ap-southeast-2": {"filesystems": {},"filesystems_count": 0,"id": "ap-southeast-2","name": "ap-southeast-2","region": "ap-southeast-2"},"ca-central-1": {"filesystems": {},"filesystems_count": 0,"id": "ca-central-1","name": "ca-central-1","region": "ca-central-1"},"eu-central-1": {"filesystems": {},"filesystems_count": 0,"id": "eu-central-1","name": "eu-central-1","region": "eu-central-1"},"eu-north-1": {"filesystems": {},"filesystems_count": 0,"id": "eu-north-1","name": "eu-north-1","region": "eu-north-1"},"eu-west-1": {"filesystems": {},"filesystems_count": 0,"id": "eu-west-1","name": "eu-west-1","region": "eu-west-1"},"eu-west-2": {"filesystems": {},"filesystems_count": 0,"id": "eu-west-2","name": "eu-west-2","region": "eu-west-2"},"eu-west-3": {"filesystems": {},"filesystems_count": 0,"id": "eu-west-3","name": "eu-west-3","region": "eu-west-3"},"sa-east-1": {"filesystems": {},"filesystems_count": 0,"id": "sa-east-1","name": "sa-east-1","region": "sa-east-1"},"us-east-1": {"filesystems": {},"filesystems_count": 0,"id": "us-east-1","name": "us-east-1","region": "us-east-1"},"us-east-2": {"filesystems": {},"filesystems_count": 0,"id": "us-east-2","name": "us-east-2","region": "us-east-2"},"us-west-1": {"filesystems": {},"filesystems_count": 0,"id": "us-west-1","name": "us-west-1","region": "us-west-1"},"us-west-2": {"filesystems": {},"filesystems_count": 0,"id": "us-west-2","name": "us-west-2","region": "us-west-2"}},"regions_count": 17},"elasticache": {"clusters_count": 0,"filters": {},"findings": {},"regions": {"ap-northeast-1": {"clusters_count": 0,"id": "ap-northeast-1","name": "ap-northeast-1","parameter_groups": {"02e3d792a7e00a39f3c9fa0bb0445e86d7644525": {"ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.redis3.2.cluster.on","CacheParameterGroupFamily": "redis3.2","Description": "Customized default parameter group for redis3.2 with cluster mode on","IsGlobal": false,"id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525","name": "default.redis3.2.cluster.on"},"156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": {"ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.memcached1.4","CacheParameterGroupFamily": "memcached1.4","Description": "Default parameter group for memcached1.4","IsGlobal": false,"id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124","name": "default.memcached1.4"},"1a65eec91cd66eb16ba40e781620d9320ec1733f": {"ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.redis6.x.cluster.on","CacheParameterGroupFamily": "redis6.x","Description": "Customized default parameter group for redis6.x with cluster mode on","IsGlobal": false,"id": "1a65eec91cd66eb16ba40e781620d9320ec1733f","name": "default.redis6.x.cluster.on"},"3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": {"ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.redis2.8","CacheParameterGroupFamily": "redis2.8","Description": "Default parameter group for redis2.8","IsGlobal": false,"id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e","name": "default.redis2.8"},"51584be5be0c6c6af057229afd341d592a55bf0e": {"ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.memcached1.6","CacheParameterGroupFamily": "memcached1.6","Description": "Default parameter group for memcached1.6","IsGlobal": false,"id": "51584be5be0c6c6af057229afd341d592a55bf0e","name": "default.memcached1.6"},"533bd3e057f46120794828b5c797b3fe8aab1336": {"ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.redis2.6","CacheParameterGroupFamily": "redis2.6","Description": "Default parameter group for redis2.6","IsGlobal": false,"id": "533bd3e057f46120794828b5c797b3fe8aab1336","name": "default.redis2.6"},"579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": {"ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.redis3.2","CacheParameterGroupFamily": "redis3.2","Description": "Default parameter group for redis3.2","IsGlobal": false,"id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3","name": "default.redis3.2"},"6e3786a6f55135ca99b9432b0059a35deb2ae908": {"ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.redis5.0","CacheParameterGroupFamily": "redis5.0","Description": "Default parameter group for redis5.0","IsGlobal": false,"id": "6e3786a6f55135ca99b9432b0059a35deb2ae908","name": "default.redis5.0"},"89dee6407112ff413de0345de376d45c799f0028": {"ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.redis4.0.cluster.on","CacheParameterGroupFamily": "redis4.0","Description": "Customized default parameter group for redis4.0 with cluster mode on","IsGlobal": false,"id": "89dee6407112ff413de0345de376d45c799f0028","name": "default.redis4.0.cluster.on"},"92d124b9a74567482361fe34e367ac8bf5c02e0b": {"ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.redis6.x","CacheParameterGroupFamily": "redis6.x","Description": "Default parameter group for redis6.x","IsGlobal": false,"id": "92d124b9a74567482361fe34e367ac8bf5c02e0b","name": "default.redis6.x"},"a64a576f220009cfa7c322c46fc92d32a85a4978": {"ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.redis5.0.cluster.on","CacheParameterGroupFamily": "redis5.0","Description": "Customized default parameter group for redis5.0 with cluster mode on","IsGlobal": false,"id": "a64a576f220009cfa7c322c46fc92d32a85a4978","name": "default.redis5.0.cluster.on"},"c954e04f298cd030c6fde9c32c8365d1b9f76fb4": {"ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.redis4.0","CacheParameterGroupFamily": "redis4.0","Description": "Default parameter group for redis4.0","IsGlobal": false,"id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4","name": "default.redis4.0"},"e0934919fe4741105df762ae57b738fea22ebc40": {"ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.memcached1.5","CacheParameterGroupFamily": "memcached1.5","Description": "Default parameter group for memcached1.5","IsGlobal": false,"id": "e0934919fe4741105df762ae57b738fea22ebc40","name": "default.memcached1.5"}},"parameter_groups_count": 13,"region": "ap-northeast-1","security_groups": {},"security_groups_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-0cbc506a": {"arn": "arn:aws:vpc:ap-northeast-1:430150006394:virtual-private-cloud/vpc-0cbc506a","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-0cbc506a","name": "vpc-0cbc506a","state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"ap-northeast-2": {"clusters_count": 0,"id": "ap-northeast-2","name": "ap-northeast-2","parameter_groups": {"02e3d792a7e00a39f3c9fa0bb0445e86d7644525": {"ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.redis3.2.cluster.on","CacheParameterGroupFamily": "redis3.2","Description": "Customized default parameter group for redis3.2 with cluster mode on","IsGlobal": false,"id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525","name": "default.redis3.2.cluster.on"},"156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": {"ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.memcached1.4","CacheParameterGroupFamily": "memcached1.4","Description": "Default parameter group for memcached1.4","IsGlobal": false,"id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124","name": "default.memcached1.4"},"1a65eec91cd66eb16ba40e781620d9320ec1733f": {"ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.redis6.x.cluster.on","CacheParameterGroupFamily": "redis6.x","Description": "Customized default parameter group for redis6.x with cluster mode on","IsGlobal": false,"id": "1a65eec91cd66eb16ba40e781620d9320ec1733f","name": "default.redis6.x.cluster.on"},"3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": {"ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.redis2.8","CacheParameterGroupFamily": "redis2.8","Description": "Default parameter group for redis2.8","IsGlobal": false,"id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e","name": "default.redis2.8"},"51584be5be0c6c6af057229afd341d592a55bf0e": {"ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.memcached1.6","CacheParameterGroupFamily": "memcached1.6","Description": "Default parameter group for memcached1.6","IsGlobal": false,"id": "51584be5be0c6c6af057229afd341d592a55bf0e","name": "default.memcached1.6"},"533bd3e057f46120794828b5c797b3fe8aab1336": {"ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.redis2.6","CacheParameterGroupFamily": "redis2.6","Description": "Default parameter group for redis2.6","IsGlobal": false,"id": "533bd3e057f46120794828b5c797b3fe8aab1336","name": "default.redis2.6"},"579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": {"ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.redis3.2","CacheParameterGroupFamily": "redis3.2","Description": "Default parameter group for redis3.2","IsGlobal": false,"id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3","name": "default.redis3.2"},"6e3786a6f55135ca99b9432b0059a35deb2ae908": {"ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.redis5.0","CacheParameterGroupFamily": "redis5.0","Description": "Default parameter group for redis5.0","IsGlobal": false,"id": "6e3786a6f55135ca99b9432b0059a35deb2ae908","name": "default.redis5.0"},"89dee6407112ff413de0345de376d45c799f0028": {"ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.redis4.0.cluster.on","CacheParameterGroupFamily": "redis4.0","Description": "Customized default parameter group for redis4.0 with cluster mode on","IsGlobal": false,"id": "89dee6407112ff413de0345de376d45c799f0028","name": "default.redis4.0.cluster.on"},"92d124b9a74567482361fe34e367ac8bf5c02e0b": {"ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.redis6.x","CacheParameterGroupFamily": "redis6.x","Description": "Default parameter group for redis6.x","IsGlobal": false,"id": "92d124b9a74567482361fe34e367ac8bf5c02e0b","name": "default.redis6.x"},"a64a576f220009cfa7c322c46fc92d32a85a4978": {"ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.redis5.0.cluster.on","CacheParameterGroupFamily": "redis5.0","Description": "Customized default parameter group for redis5.0 with cluster mode on","IsGlobal": false,"id": "a64a576f220009cfa7c322c46fc92d32a85a4978","name": "default.redis5.0.cluster.on"},"c954e04f298cd030c6fde9c32c8365d1b9f76fb4": {"ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.redis4.0","CacheParameterGroupFamily": "redis4.0","Description": "Default parameter group for redis4.0","IsGlobal": false,"id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4","name": "default.redis4.0"},"e0934919fe4741105df762ae57b738fea22ebc40": {"ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.memcached1.5","CacheParameterGroupFamily": "memcached1.5","Description": "Default parameter group for memcached1.5","IsGlobal": false,"id": "e0934919fe4741105df762ae57b738fea22ebc40","name": "default.memcached1.5"}},"parameter_groups_count": 13,"region": "ap-northeast-2","security_groups": {},"security_groups_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-73f44e18": {"arn": "arn:aws:vpc:ap-northeast-2:430150006394:virtual-private-cloud/vpc-73f44e18","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-73f44e18","name": "vpc-73f44e18","state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"ap-northeast-3": {"clusters_count": 0,"id": "ap-northeast-3","name": "ap-northeast-3","parameter_groups": {"02e3d792a7e00a39f3c9fa0bb0445e86d7644525": {"ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.redis3.2.cluster.on","CacheParameterGroupFamily": "redis3.2","Description": "Customized default parameter group for redis3.2 with cluster mode on","IsGlobal": false,"id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525","name": "default.redis3.2.cluster.on"},"156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": {"ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.memcached1.4","CacheParameterGroupFamily": "memcached1.4","Description": "Default parameter group for memcached1.4","IsGlobal": false,"id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124","name": "default.memcached1.4"},"1a65eec91cd66eb16ba40e781620d9320ec1733f": {"ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.redis6.x.cluster.on","CacheParameterGroupFamily": "redis6.x","Description": "Customized default parameter group for redis6.x with cluster mode on","IsGlobal": false,"id": "1a65eec91cd66eb16ba40e781620d9320ec1733f","name": "default.redis6.x.cluster.on"},"3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": {"ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.redis2.8","CacheParameterGroupFamily": "redis2.8","Description": "Default parameter group for redis2.8","IsGlobal": false,"id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e","name": "default.redis2.8"},"51584be5be0c6c6af057229afd341d592a55bf0e": {"ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.memcached1.6","CacheParameterGroupFamily": "memcached1.6","Description": "Default parameter group for memcached1.6","IsGlobal": false,"id": "51584be5be0c6c6af057229afd341d592a55bf0e","name": "default.memcached1.6"},"533bd3e057f46120794828b5c797b3fe8aab1336": {"ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.redis2.6","CacheParameterGroupFamily": "redis2.6","Description": "Default parameter group for redis2.6","IsGlobal": false,"id": "533bd3e057f46120794828b5c797b3fe8aab1336","name": "default.redis2.6"},"579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": {"ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.redis3.2","CacheParameterGroupFamily": "redis3.2","Description": "Default parameter group for redis3.2","IsGlobal": false,"id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3","name": "default.redis3.2"},"6e3786a6f55135ca99b9432b0059a35deb2ae908": {"ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.redis5.0","CacheParameterGroupFamily": "redis5.0","Description": "Default parameter group for redis5.0","IsGlobal": false,"id": "6e3786a6f55135ca99b9432b0059a35deb2ae908","name": "default.redis5.0"},"89dee6407112ff413de0345de376d45c799f0028": {"ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.redis4.0.cluster.on","CacheParameterGroupFamily": "redis4.0","Description": "Customized default parameter group for redis4.0 with cluster mode on","IsGlobal": false,"id": "89dee6407112ff413de0345de376d45c799f0028","name": "default.redis4.0.cluster.on"},"92d124b9a74567482361fe34e367ac8bf5c02e0b": {"ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.redis6.x","CacheParameterGroupFamily": "redis6.x","Description": "Default parameter group for redis6.x","IsGlobal": false,"id": "92d124b9a74567482361fe34e367ac8bf5c02e0b","name": "default.redis6.x"},"a64a576f220009cfa7c322c46fc92d32a85a4978": {"ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.redis5.0.cluster.on","CacheParameterGroupFamily": "redis5.0","Description": "Customized default parameter group for redis5.0 with cluster mode on","IsGlobal": false,"id": "a64a576f220009cfa7c322c46fc92d32a85a4978","name": "default.redis5.0.cluster.on"},"c954e04f298cd030c6fde9c32c8365d1b9f76fb4": {"ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.redis4.0","CacheParameterGroupFamily": "redis4.0","Description": "Default parameter group for redis4.0","IsGlobal": false,"id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4","name": "default.redis4.0"},"e0934919fe4741105df762ae57b738fea22ebc40": {"ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.memcached1.5","CacheParameterGroupFamily": "memcached1.5","Description": "Default parameter group for memcached1.5","IsGlobal": false,"id": "e0934919fe4741105df762ae57b738fea22ebc40","name": "default.memcached1.5"}},"parameter_groups_count": 13,"region": "ap-northeast-3","security_groups": {},"security_groups_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-47b7dd2e": {"arn": "arn:aws:vpc:ap-northeast-3:430150006394:virtual-private-cloud/vpc-47b7dd2e","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-47b7dd2e","name": "vpc-47b7dd2e","state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"ap-south-1": {"clusters_count": 0,"id": "ap-south-1","name": "ap-south-1","parameter_groups": {"02e3d792a7e00a39f3c9fa0bb0445e86d7644525": {"ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.redis3.2.cluster.on","CacheParameterGroupFamily": "redis3.2","Description": "Customized default parameter group for redis3.2 with cluster mode on","IsGlobal": false,"id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525","name": "default.redis3.2.cluster.on"},"156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": {"ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.memcached1.4","CacheParameterGroupFamily": "memcached1.4","Description": "Default parameter group for memcached1.4","IsGlobal": false,"id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124","name": "default.memcached1.4"},"1a65eec91cd66eb16ba40e781620d9320ec1733f": {"ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.redis6.x.cluster.on","CacheParameterGroupFamily": "redis6.x","Description": "Customized default parameter group for redis6.x with cluster mode on","IsGlobal": false,"id": "1a65eec91cd66eb16ba40e781620d9320ec1733f","name": "default.redis6.x.cluster.on"},"3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": {"ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.redis2.8","CacheParameterGroupFamily": "redis2.8","Description": "Default parameter group for redis2.8","IsGlobal": false,"id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e","name": "default.redis2.8"},"51584be5be0c6c6af057229afd341d592a55bf0e": {"ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.memcached1.6","CacheParameterGroupFamily": "memcached1.6","Description": "Default parameter group for memcached1.6","IsGlobal": false,"id": "51584be5be0c6c6af057229afd341d592a55bf0e","name": "default.memcached1.6"},"579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": {"ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.redis3.2","CacheParameterGroupFamily": "redis3.2","Description": "Default parameter group for redis3.2","IsGlobal": false,"id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3","name": "default.redis3.2"},"6e3786a6f55135ca99b9432b0059a35deb2ae908": {"ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.redis5.0","CacheParameterGroupFamily": "redis5.0","Description": "Default parameter group for redis5.0","IsGlobal": false,"id": "6e3786a6f55135ca99b9432b0059a35deb2ae908","name": "default.redis5.0"},"89dee6407112ff413de0345de376d45c799f0028": {"ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.redis4.0.cluster.on","CacheParameterGroupFamily": "redis4.0","Description": "Customized default parameter group for redis4.0 with cluster mode on","IsGlobal": false,"id": "89dee6407112ff413de0345de376d45c799f0028","name": "default.redis4.0.cluster.on"},"92d124b9a74567482361fe34e367ac8bf5c02e0b": {"ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.redis6.x","CacheParameterGroupFamily": "redis6.x","Description": "Default parameter group for redis6.x","IsGlobal": false,"id": "92d124b9a74567482361fe34e367ac8bf5c02e0b","name": "default.redis6.x"},"a64a576f220009cfa7c322c46fc92d32a85a4978": {"ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.redis5.0.cluster.on","CacheParameterGroupFamily": "redis5.0","Description": "Customized default parameter group for redis5.0 with cluster mode on","IsGlobal": false,"id": "a64a576f220009cfa7c322c46fc92d32a85a4978","name": "default.redis5.0.cluster.on"},"c954e04f298cd030c6fde9c32c8365d1b9f76fb4": {"ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.redis4.0","CacheParameterGroupFamily": "redis4.0","Description": "Default parameter group for redis4.0","IsGlobal": false,"id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4","name": "default.redis4.0"},"e0934919fe4741105df762ae57b738fea22ebc40": {"ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.memcached1.5","CacheParameterGroupFamily": "memcached1.5","Description": "Default parameter group for memcached1.5","IsGlobal": false,"id": "e0934919fe4741105df762ae57b738fea22ebc40","name": "default.memcached1.5"}},"parameter_groups_count": 12,"region": "ap-south-1","security_groups": {},"security_groups_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-2651a14d": {"arn": "arn:aws:vpc:ap-south-1:430150006394:virtual-private-cloud/vpc-2651a14d","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-2651a14d","name": "vpc-2651a14d","state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"ap-southeast-1": {"clusters_count": 0,"id": "ap-southeast-1","name": "ap-southeast-1","parameter_groups": {"02e3d792a7e00a39f3c9fa0bb0445e86d7644525": {"ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.redis3.2.cluster.on","CacheParameterGroupFamily": "redis3.2","Description": "Customized default parameter group for redis3.2 with cluster mode on","IsGlobal": false,"id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525","name": "default.redis3.2.cluster.on"},"156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": {"ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.memcached1.4","CacheParameterGroupFamily": "memcached1.4","Description": "Default parameter group for memcached1.4","IsGlobal": false,"id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124","name": "default.memcached1.4"},"1a65eec91cd66eb16ba40e781620d9320ec1733f": {"ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.redis6.x.cluster.on","CacheParameterGroupFamily": "redis6.x","Description": "Customized default parameter group for redis6.x with cluster mode on","IsGlobal": false,"id": "1a65eec91cd66eb16ba40e781620d9320ec1733f","name": "default.redis6.x.cluster.on"},"3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": {"ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.redis2.8","CacheParameterGroupFamily": "redis2.8","Description": "Default parameter group for redis2.8","IsGlobal": false,"id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e","name": "default.redis2.8"},"51584be5be0c6c6af057229afd341d592a55bf0e": {"ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.memcached1.6","CacheParameterGroupFamily": "memcached1.6","Description": "Default parameter group for memcached1.6","IsGlobal": false,"id": "51584be5be0c6c6af057229afd341d592a55bf0e","name": "default.memcached1.6"},"533bd3e057f46120794828b5c797b3fe8aab1336": {"ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.redis2.6","CacheParameterGroupFamily": "redis2.6","Description": "Default parameter group for redis2.6","IsGlobal": false,"id": "533bd3e057f46120794828b5c797b3fe8aab1336","name": "default.redis2.6"},"579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": {"ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.redis3.2","CacheParameterGroupFamily": "redis3.2","Description": "Default parameter group for redis3.2","IsGlobal": false,"id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3","name": "default.redis3.2"},"6e3786a6f55135ca99b9432b0059a35deb2ae908": {"ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.redis5.0","CacheParameterGroupFamily": "redis5.0","Description": "Default parameter group for redis5.0","IsGlobal": false,"id": "6e3786a6f55135ca99b9432b0059a35deb2ae908","name": "default.redis5.0"},"89dee6407112ff413de0345de376d45c799f0028": {"ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.redis4.0.cluster.on","CacheParameterGroupFamily": "redis4.0","Description": "Customized default parameter group for redis4.0 with cluster mode on","IsGlobal": false,"id": "89dee6407112ff413de0345de376d45c799f0028","name": "default.redis4.0.cluster.on"},"92d124b9a74567482361fe34e367ac8bf5c02e0b": {"ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.redis6.x","CacheParameterGroupFamily": "redis6.x","Description": "Default parameter group for redis6.x","IsGlobal": false,"id": "92d124b9a74567482361fe34e367ac8bf5c02e0b","name": "default.redis6.x"},"a64a576f220009cfa7c322c46fc92d32a85a4978": {"ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.redis5.0.cluster.on","CacheParameterGroupFamily": "redis5.0","Description": "Customized default parameter group for redis5.0 with cluster mode on","IsGlobal": false,"id": "a64a576f220009cfa7c322c46fc92d32a85a4978","name": "default.redis5.0.cluster.on"},"c954e04f298cd030c6fde9c32c8365d1b9f76fb4": {"ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.redis4.0","CacheParameterGroupFamily": "redis4.0","Description": "Default parameter group for redis4.0","IsGlobal": false,"id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4","name": "default.redis4.0"},"e0934919fe4741105df762ae57b738fea22ebc40": {"ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.memcached1.5","CacheParameterGroupFamily": "memcached1.5","Description": "Default parameter group for memcached1.5","IsGlobal": false,"id": "e0934919fe4741105df762ae57b738fea22ebc40","name": "default.memcached1.5"}},"parameter_groups_count": 13,"region": "ap-southeast-1","security_groups": {},"security_groups_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-04ed1062": {"arn": "arn:aws:vpc:ap-southeast-1:430150006394:virtual-private-cloud/vpc-04ed1062","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-04ed1062","name": "vpc-04ed1062","state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"ap-southeast-2": {"clusters_count": 0,"id": "ap-southeast-2","name": "ap-southeast-2","parameter_groups": {"02e3d792a7e00a39f3c9fa0bb0445e86d7644525": {"ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.redis3.2.cluster.on","CacheParameterGroupFamily": "redis3.2","Description": "Customized default parameter group for redis3.2 with cluster mode on","IsGlobal": false,"id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525","name": "default.redis3.2.cluster.on"},"156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": {"ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.memcached1.4","CacheParameterGroupFamily": "memcached1.4","Description": "Default parameter group for memcached1.4","IsGlobal": false,"id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124","name": "default.memcached1.4"},"1a65eec91cd66eb16ba40e781620d9320ec1733f": {"ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.redis6.x.cluster.on","CacheParameterGroupFamily": "redis6.x","Description": "Customized default parameter group for redis6.x with cluster mode on","IsGlobal": false,"id": "1a65eec91cd66eb16ba40e781620d9320ec1733f","name": "default.redis6.x.cluster.on"},"3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": {"ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.redis2.8","CacheParameterGroupFamily": "redis2.8","Description": "Default parameter group for redis2.8","IsGlobal": false,"id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e","name": "default.redis2.8"},"51584be5be0c6c6af057229afd341d592a55bf0e": {"ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.memcached1.6","CacheParameterGroupFamily": "memcached1.6","Description": "Default parameter group for memcached1.6","IsGlobal": false,"id": "51584be5be0c6c6af057229afd341d592a55bf0e","name": "default.memcached1.6"},"533bd3e057f46120794828b5c797b3fe8aab1336": {"ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.redis2.6","CacheParameterGroupFamily": "redis2.6","Description": "Default parameter group for redis2.6","IsGlobal": false,"id": "533bd3e057f46120794828b5c797b3fe8aab1336","name": "default.redis2.6"},"579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": {"ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.redis3.2","CacheParameterGroupFamily": "redis3.2","Description": "Default parameter group for redis3.2","IsGlobal": false,"id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3","name": "default.redis3.2"},"6e3786a6f55135ca99b9432b0059a35deb2ae908": {"ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.redis5.0","CacheParameterGroupFamily": "redis5.0","Description": "Default parameter group for redis5.0","IsGlobal": false,"id": "6e3786a6f55135ca99b9432b0059a35deb2ae908","name": "default.redis5.0"},"89dee6407112ff413de0345de376d45c799f0028": {"ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.redis4.0.cluster.on","CacheParameterGroupFamily": "redis4.0","Description": "Customized default parameter group for redis4.0 with cluster mode on","IsGlobal": false,"id": "89dee6407112ff413de0345de376d45c799f0028","name": "default.redis4.0.cluster.on"},"92d124b9a74567482361fe34e367ac8bf5c02e0b": {"ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.redis6.x","CacheParameterGroupFamily": "redis6.x","Description": "Default parameter group for redis6.x","IsGlobal": false,"id": "92d124b9a74567482361fe34e367ac8bf5c02e0b","name": "default.redis6.x"},"a64a576f220009cfa7c322c46fc92d32a85a4978": {"ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.redis5.0.cluster.on","CacheParameterGroupFamily": "redis5.0","Description": "Customized default parameter group for redis5.0 with cluster mode on","IsGlobal": false,"id": "a64a576f220009cfa7c322c46fc92d32a85a4978","name": "default.redis5.0.cluster.on"},"c954e04f298cd030c6fde9c32c8365d1b9f76fb4": {"ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.redis4.0","CacheParameterGroupFamily": "redis4.0","Description": "Default parameter group for redis4.0","IsGlobal": false,"id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4","name": "default.redis4.0"},"e0934919fe4741105df762ae57b738fea22ebc40": {"ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.memcached1.5","CacheParameterGroupFamily": "memcached1.5","Description": "Default parameter group for memcached1.5","IsGlobal": false,"id": "e0934919fe4741105df762ae57b738fea22ebc40","name": "default.memcached1.5"}},"parameter_groups_count": 13,"region": "ap-southeast-2","security_groups": {},"security_groups_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-5d22c33b": {"arn": "arn:aws:vpc:ap-southeast-2:430150006394:virtual-private-cloud/vpc-5d22c33b","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-5d22c33b","name": "vpc-5d22c33b","state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"ca-central-1": {"clusters_count": 0,"id": "ca-central-1","name": "ca-central-1","parameter_groups": {"02e3d792a7e00a39f3c9fa0bb0445e86d7644525": {"ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.redis3.2.cluster.on","CacheParameterGroupFamily": "redis3.2","Description": "Customized default parameter group for redis3.2 with cluster mode on","IsGlobal": false,"id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525","name": "default.redis3.2.cluster.on"},"156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": {"ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.memcached1.4","CacheParameterGroupFamily": "memcached1.4","Description": "Default parameter group for memcached1.4","IsGlobal": false,"id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124","name": "default.memcached1.4"},"1a65eec91cd66eb16ba40e781620d9320ec1733f": {"ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.redis6.x.cluster.on","CacheParameterGroupFamily": "redis6.x","Description": "Customized default parameter group for redis6.x with cluster mode on","IsGlobal": false,"id": "1a65eec91cd66eb16ba40e781620d9320ec1733f","name": "default.redis6.x.cluster.on"},"3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": {"ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.redis2.8","CacheParameterGroupFamily": "redis2.8","Description": "Default parameter group for redis2.8","IsGlobal": false,"id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e","name": "default.redis2.8"},"51584be5be0c6c6af057229afd341d592a55bf0e": {"ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.memcached1.6","CacheParameterGroupFamily": "memcached1.6","Description": "Default parameter group for memcached1.6","IsGlobal": false,"id": "51584be5be0c6c6af057229afd341d592a55bf0e","name": "default.memcached1.6"},"533bd3e057f46120794828b5c797b3fe8aab1336": {"ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.redis2.6","CacheParameterGroupFamily": "redis2.6","Description": "Default parameter group for redis2.6","IsGlobal": false,"id": "533bd3e057f46120794828b5c797b3fe8aab1336","name": "default.redis2.6"},"579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": {"ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.redis3.2","CacheParameterGroupFamily": "redis3.2","Description": "Default parameter group for redis3.2","IsGlobal": false,"id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3","name": "default.redis3.2"},"6e3786a6f55135ca99b9432b0059a35deb2ae908": {"ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.redis5.0","CacheParameterGroupFamily": "redis5.0","Description": "Default parameter group for redis5.0","IsGlobal": false,"id": "6e3786a6f55135ca99b9432b0059a35deb2ae908","name": "default.redis5.0"},"89dee6407112ff413de0345de376d45c799f0028": {"ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.redis4.0.cluster.on","CacheParameterGroupFamily": "redis4.0","Description": "Customized default parameter group for redis4.0 with cluster mode on","IsGlobal": false,"id": "89dee6407112ff413de0345de376d45c799f0028","name": "default.redis4.0.cluster.on"},"92d124b9a74567482361fe34e367ac8bf5c02e0b": {"ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.redis6.x","CacheParameterGroupFamily": "redis6.x","Description": "Default parameter group for redis6.x","IsGlobal": false,"id": "92d124b9a74567482361fe34e367ac8bf5c02e0b","name": "default.redis6.x"},"a64a576f220009cfa7c322c46fc92d32a85a4978": {"ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.redis5.0.cluster.on","CacheParameterGroupFamily": "redis5.0","Description": "Customized default parameter group for redis5.0 with cluster mode on","IsGlobal": false,"id": "a64a576f220009cfa7c322c46fc92d32a85a4978","name": "default.redis5.0.cluster.on"},"c954e04f298cd030c6fde9c32c8365d1b9f76fb4": {"ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.redis4.0","CacheParameterGroupFamily": "redis4.0","Description": "Default parameter group for redis4.0","IsGlobal": false,"id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4","name": "default.redis4.0"},"e0934919fe4741105df762ae57b738fea22ebc40": {"ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.memcached1.5","CacheParameterGroupFamily": "memcached1.5","Description": "Default parameter group for memcached1.5","IsGlobal": false,"id": "e0934919fe4741105df762ae57b738fea22ebc40","name": "default.memcached1.5"}},"parameter_groups_count": 13,"region": "ca-central-1","security_groups": {},"security_groups_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-b5113ddd": {"arn": "arn:aws:vpc:ca-central-1:430150006394:virtual-private-cloud/vpc-b5113ddd","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-b5113ddd","name": "vpc-b5113ddd","state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"eu-central-1": {"clusters_count": 0,"id": "eu-central-1","name": "eu-central-1","parameter_groups": {"02e3d792a7e00a39f3c9fa0bb0445e86d7644525": {"ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.redis3.2.cluster.on","CacheParameterGroupFamily": "redis3.2","Description": "Customized default parameter group for redis3.2 with cluster mode on","IsGlobal": false,"id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525","name": "default.redis3.2.cluster.on"},"156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": {"ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.memcached1.4","CacheParameterGroupFamily": "memcached1.4","Description": "Default parameter group for memcached1.4","IsGlobal": false,"id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124","name": "default.memcached1.4"},"1a65eec91cd66eb16ba40e781620d9320ec1733f": {"ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.redis6.x.cluster.on","CacheParameterGroupFamily": "redis6.x","Description": "Customized default parameter group for redis6.x with cluster mode on","IsGlobal": false,"id": "1a65eec91cd66eb16ba40e781620d9320ec1733f","name": "default.redis6.x.cluster.on"},"3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": {"ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.redis2.8","CacheParameterGroupFamily": "redis2.8","Description": "Default parameter group for redis2.8","IsGlobal": false,"id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e","name": "default.redis2.8"},"51584be5be0c6c6af057229afd341d592a55bf0e": {"ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.memcached1.6","CacheParameterGroupFamily": "memcached1.6","Description": "Default parameter group for memcached1.6","IsGlobal": false,"id": "51584be5be0c6c6af057229afd341d592a55bf0e","name": "default.memcached1.6"},"533bd3e057f46120794828b5c797b3fe8aab1336": {"ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.redis2.6","CacheParameterGroupFamily": "redis2.6","Description": "Default parameter group for redis2.6","IsGlobal": false,"id": "533bd3e057f46120794828b5c797b3fe8aab1336","name": "default.redis2.6"},"579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": {"ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.redis3.2","CacheParameterGroupFamily": "redis3.2","Description": "Default parameter group for redis3.2","IsGlobal": false,"id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3","name": "default.redis3.2"},"6e3786a6f55135ca99b9432b0059a35deb2ae908": {"ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.redis5.0","CacheParameterGroupFamily": "redis5.0","Description": "Default parameter group for redis5.0","IsGlobal": false,"id": "6e3786a6f55135ca99b9432b0059a35deb2ae908","name": "default.redis5.0"},"89dee6407112ff413de0345de376d45c799f0028": {"ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.redis4.0.cluster.on","CacheParameterGroupFamily": "redis4.0","Description": "Customized default parameter group for redis4.0 with cluster mode on","IsGlobal": false,"id": "89dee6407112ff413de0345de376d45c799f0028","name": "default.redis4.0.cluster.on"},"92d124b9a74567482361fe34e367ac8bf5c02e0b": {"ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.redis6.x","CacheParameterGroupFamily": "redis6.x","Description": "Default parameter group for redis6.x","IsGlobal": false,"id": "92d124b9a74567482361fe34e367ac8bf5c02e0b","name": "default.redis6.x"},"a64a576f220009cfa7c322c46fc92d32a85a4978": {"ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.redis5.0.cluster.on","CacheParameterGroupFamily": "redis5.0","Description": "Customized default parameter group for redis5.0 with cluster mode on","IsGlobal": false,"id": "a64a576f220009cfa7c322c46fc92d32a85a4978","name": "default.redis5.0.cluster.on"},"c954e04f298cd030c6fde9c32c8365d1b9f76fb4": {"ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.redis4.0","CacheParameterGroupFamily": "redis4.0","Description": "Default parameter group for redis4.0","IsGlobal": false,"id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4","name": "default.redis4.0"},"e0934919fe4741105df762ae57b738fea22ebc40": {"ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.memcached1.5","CacheParameterGroupFamily": "memcached1.5","Description": "Default parameter group for memcached1.5","IsGlobal": false,"id": "e0934919fe4741105df762ae57b738fea22ebc40","name": "default.memcached1.5"}},"parameter_groups_count": 13,"region": "eu-central-1","security_groups": {},"security_groups_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-78b43312": {"arn": "arn:aws:vpc:eu-central-1:430150006394:virtual-private-cloud/vpc-78b43312","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-78b43312","name": "vpc-78b43312","state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"eu-north-1": {"clusters_count": 0,"id": "eu-north-1","name": "eu-north-1","parameter_groups": {"02e3d792a7e00a39f3c9fa0bb0445e86d7644525": {"ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.redis3.2.cluster.on","CacheParameterGroupFamily": "redis3.2","Description": "Customized default parameter group for redis3.2 with cluster mode on","IsGlobal": false,"id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525","name": "default.redis3.2.cluster.on"},"156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": {"ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.memcached1.4","CacheParameterGroupFamily": "memcached1.4","Description": "Default parameter group for memcached1.4","IsGlobal": false,"id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124","name": "default.memcached1.4"},"1a65eec91cd66eb16ba40e781620d9320ec1733f": {"ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.redis6.x.cluster.on","CacheParameterGroupFamily": "redis6.x","Description": "Customized default parameter group for redis6.x with cluster mode on","IsGlobal": false,"id": "1a65eec91cd66eb16ba40e781620d9320ec1733f","name": "default.redis6.x.cluster.on"},"51584be5be0c6c6af057229afd341d592a55bf0e": {"ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.memcached1.6","CacheParameterGroupFamily": "memcached1.6","Description": "Default parameter group for memcached1.6","IsGlobal": false,"id": "51584be5be0c6c6af057229afd341d592a55bf0e","name": "default.memcached1.6"},"579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": {"ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.redis3.2","CacheParameterGroupFamily": "redis3.2","Description": "Default parameter group for redis3.2","IsGlobal": false,"id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3","name": "default.redis3.2"},"6e3786a6f55135ca99b9432b0059a35deb2ae908": {"ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.redis5.0","CacheParameterGroupFamily": "redis5.0","Description": "Default parameter group for redis5.0","IsGlobal": false,"id": "6e3786a6f55135ca99b9432b0059a35deb2ae908","name": "default.redis5.0"},"89dee6407112ff413de0345de376d45c799f0028": {"ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.redis4.0.cluster.on","CacheParameterGroupFamily": "redis4.0","Description": "Customized default parameter group for redis4.0 with cluster mode on","IsGlobal": false,"id": "89dee6407112ff413de0345de376d45c799f0028","name": "default.redis4.0.cluster.on"},"92d124b9a74567482361fe34e367ac8bf5c02e0b": {"ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.redis6.x","CacheParameterGroupFamily": "redis6.x","Description": "Default parameter group for redis6.x","IsGlobal": false,"id": "92d124b9a74567482361fe34e367ac8bf5c02e0b","name": "default.redis6.x"},"a64a576f220009cfa7c322c46fc92d32a85a4978": {"ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.redis5.0.cluster.on","CacheParameterGroupFamily": "redis5.0","Description": "Customized default parameter group for redis5.0 with cluster mode on","IsGlobal": false,"id": "a64a576f220009cfa7c322c46fc92d32a85a4978","name": "default.redis5.0.cluster.on"},"c954e04f298cd030c6fde9c32c8365d1b9f76fb4": {"ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.redis4.0","CacheParameterGroupFamily": "redis4.0","Description": "Default parameter group for redis4.0","IsGlobal": false,"id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4","name": "default.redis4.0"},"e0934919fe4741105df762ae57b738fea22ebc40": {"ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.memcached1.5","CacheParameterGroupFamily": "memcached1.5","Description": "Default parameter group for memcached1.5","IsGlobal": false,"id": "e0934919fe4741105df762ae57b738fea22ebc40","name": "default.memcached1.5"}},"parameter_groups_count": 11,"region": "eu-north-1","security_groups": {},"security_groups_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-fa259d93": {"arn": "arn:aws:vpc:eu-north-1:430150006394:virtual-private-cloud/vpc-fa259d93","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-fa259d93","name": "vpc-fa259d93","state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"eu-west-1": {"clusters_count": 0,"id": "eu-west-1","name": "eu-west-1","parameter_groups": {"02e3d792a7e00a39f3c9fa0bb0445e86d7644525": {"ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.redis3.2.cluster.on","CacheParameterGroupFamily": "redis3.2","Description": "Customized default parameter group for redis3.2 with cluster mode on","IsGlobal": false,"id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525","name": "default.redis3.2.cluster.on"},"156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": {"ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.memcached1.4","CacheParameterGroupFamily": "memcached1.4","Description": "Default parameter group for memcached1.4","IsGlobal": false,"id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124","name": "default.memcached1.4"},"1a65eec91cd66eb16ba40e781620d9320ec1733f": {"ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.redis6.x.cluster.on","CacheParameterGroupFamily": "redis6.x","Description": "Customized default parameter group for redis6.x with cluster mode on","IsGlobal": false,"id": "1a65eec91cd66eb16ba40e781620d9320ec1733f","name": "default.redis6.x.cluster.on"},"3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": {"ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.redis2.8","CacheParameterGroupFamily": "redis2.8","Description": "Default parameter group for redis2.8","IsGlobal": false,"id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e","name": "default.redis2.8"},"51584be5be0c6c6af057229afd341d592a55bf0e": {"ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.memcached1.6","CacheParameterGroupFamily": "memcached1.6","Description": "Default parameter group for memcached1.6","IsGlobal": false,"id": "51584be5be0c6c6af057229afd341d592a55bf0e","name": "default.memcached1.6"},"533bd3e057f46120794828b5c797b3fe8aab1336": {"ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.redis2.6","CacheParameterGroupFamily": "redis2.6","Description": "Default parameter group for redis2.6","IsGlobal": false,"id": "533bd3e057f46120794828b5c797b3fe8aab1336","name": "default.redis2.6"},"579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": {"ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.redis3.2","CacheParameterGroupFamily": "redis3.2","Description": "Default parameter group for redis3.2","IsGlobal": false,"id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3","name": "default.redis3.2"},"6e3786a6f55135ca99b9432b0059a35deb2ae908": {"ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.redis5.0","CacheParameterGroupFamily": "redis5.0","Description": "Default parameter group for redis5.0","IsGlobal": false,"id": "6e3786a6f55135ca99b9432b0059a35deb2ae908","name": "default.redis5.0"},"89dee6407112ff413de0345de376d45c799f0028": {"ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.redis4.0.cluster.on","CacheParameterGroupFamily": "redis4.0","Description": "Customized default parameter group for redis4.0 with cluster mode on","IsGlobal": false,"id": "89dee6407112ff413de0345de376d45c799f0028","name": "default.redis4.0.cluster.on"},"92d124b9a74567482361fe34e367ac8bf5c02e0b": {"ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.redis6.x","CacheParameterGroupFamily": "redis6.x","Description": "Default parameter group for redis6.x","IsGlobal": false,"id": "92d124b9a74567482361fe34e367ac8bf5c02e0b","name": "default.redis6.x"},"a64a576f220009cfa7c322c46fc92d32a85a4978": {"ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.redis5.0.cluster.on","CacheParameterGroupFamily": "redis5.0","Description": "Customized default parameter group for redis5.0 with cluster mode on","IsGlobal": false,"id": "a64a576f220009cfa7c322c46fc92d32a85a4978","name": "default.redis5.0.cluster.on"},"c954e04f298cd030c6fde9c32c8365d1b9f76fb4": {"ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.redis4.0","CacheParameterGroupFamily": "redis4.0","Description": "Default parameter group for redis4.0","IsGlobal": false,"id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4","name": "default.redis4.0"},"e0934919fe4741105df762ae57b738fea22ebc40": {"ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.memcached1.5","CacheParameterGroupFamily": "memcached1.5","Description": "Default parameter group for memcached1.5","IsGlobal": false,"id": "e0934919fe4741105df762ae57b738fea22ebc40","name": "default.memcached1.5"}},"parameter_groups_count": 13,"region": "eu-west-1","security_groups": {},"security_groups_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-f24c7994": {"arn": "arn:aws:vpc:eu-west-1:430150006394:virtual-private-cloud/vpc-f24c7994","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-f24c7994","name": "vpc-f24c7994","state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"eu-west-2": {"clusters_count": 0,"id": "eu-west-2","name": "eu-west-2","parameter_groups": {"02e3d792a7e00a39f3c9fa0bb0445e86d7644525": {"ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.redis3.2.cluster.on","CacheParameterGroupFamily": "redis3.2","Description": "Customized default parameter group for redis3.2 with cluster mode on","IsGlobal": false,"id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525","name": "default.redis3.2.cluster.on"},"156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": {"ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.memcached1.4","CacheParameterGroupFamily": "memcached1.4","Description": "Default parameter group for memcached1.4","IsGlobal": false,"id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124","name": "default.memcached1.4"},"1a65eec91cd66eb16ba40e781620d9320ec1733f": {"ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.redis6.x.cluster.on","CacheParameterGroupFamily": "redis6.x","Description": "Customized default parameter group for redis6.x with cluster mode on","IsGlobal": false,"id": "1a65eec91cd66eb16ba40e781620d9320ec1733f","name": "default.redis6.x.cluster.on"},"3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": {"ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.redis2.8","CacheParameterGroupFamily": "redis2.8","Description": "Default parameter group for redis2.8","IsGlobal": false,"id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e","name": "default.redis2.8"},"51584be5be0c6c6af057229afd341d592a55bf0e": {"ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.memcached1.6","CacheParameterGroupFamily": "memcached1.6","Description": "Default parameter group for memcached1.6","IsGlobal": false,"id": "51584be5be0c6c6af057229afd341d592a55bf0e","name": "default.memcached1.6"},"579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": {"ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.redis3.2","CacheParameterGroupFamily": "redis3.2","Description": "Default parameter group for redis3.2","IsGlobal": false,"id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3","name": "default.redis3.2"},"6e3786a6f55135ca99b9432b0059a35deb2ae908": {"ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.redis5.0","CacheParameterGroupFamily": "redis5.0","Description": "Default parameter group for redis5.0","IsGlobal": false,"id": "6e3786a6f55135ca99b9432b0059a35deb2ae908","name": "default.redis5.0"},"89dee6407112ff413de0345de376d45c799f0028": {"ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.redis4.0.cluster.on","CacheParameterGroupFamily": "redis4.0","Description": "Customized default parameter group for redis4.0 with cluster mode on","IsGlobal": false,"id": "89dee6407112ff413de0345de376d45c799f0028","name": "default.redis4.0.cluster.on"},"92d124b9a74567482361fe34e367ac8bf5c02e0b": {"ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.redis6.x","CacheParameterGroupFamily": "redis6.x","Description": "Default parameter group for redis6.x","IsGlobal": false,"id": "92d124b9a74567482361fe34e367ac8bf5c02e0b","name": "default.redis6.x"},"a64a576f220009cfa7c322c46fc92d32a85a4978": {"ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.redis5.0.cluster.on","CacheParameterGroupFamily": "redis5.0","Description": "Customized default parameter group for redis5.0 with cluster mode on","IsGlobal": false,"id": "a64a576f220009cfa7c322c46fc92d32a85a4978","name": "default.redis5.0.cluster.on"},"c954e04f298cd030c6fde9c32c8365d1b9f76fb4": {"ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.redis4.0","CacheParameterGroupFamily": "redis4.0","Description": "Default parameter group for redis4.0","IsGlobal": false,"id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4","name": "default.redis4.0"},"e0934919fe4741105df762ae57b738fea22ebc40": {"ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.memcached1.5","CacheParameterGroupFamily": "memcached1.5","Description": "Default parameter group for memcached1.5","IsGlobal": false,"id": "e0934919fe4741105df762ae57b738fea22ebc40","name": "default.memcached1.5"}},"parameter_groups_count": 12,"region": "eu-west-2","security_groups": {},"security_groups_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-3fa2fa57": {"arn": "arn:aws:vpc:eu-west-2:430150006394:virtual-private-cloud/vpc-3fa2fa57","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-3fa2fa57","name": "vpc-3fa2fa57","state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"eu-west-3": {"clusters_count": 0,"id": "eu-west-3","name": "eu-west-3","parameter_groups": {"02e3d792a7e00a39f3c9fa0bb0445e86d7644525": {"ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.redis3.2.cluster.on","CacheParameterGroupFamily": "redis3.2","Description": "Customized default parameter group for redis3.2 with cluster mode on","IsGlobal": false,"id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525","name": "default.redis3.2.cluster.on"},"156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": {"ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.memcached1.4","CacheParameterGroupFamily": "memcached1.4","Description": "Default parameter group for memcached1.4","IsGlobal": false,"id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124","name": "default.memcached1.4"},"1a65eec91cd66eb16ba40e781620d9320ec1733f": {"ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.redis6.x.cluster.on","CacheParameterGroupFamily": "redis6.x","Description": "Customized default parameter group for redis6.x with cluster mode on","IsGlobal": false,"id": "1a65eec91cd66eb16ba40e781620d9320ec1733f","name": "default.redis6.x.cluster.on"},"3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": {"ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.redis2.8","CacheParameterGroupFamily": "redis2.8","Description": "Default parameter group for redis2.8","IsGlobal": false,"id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e","name": "default.redis2.8"},"51584be5be0c6c6af057229afd341d592a55bf0e": {"ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.memcached1.6","CacheParameterGroupFamily": "memcached1.6","Description": "Default parameter group for memcached1.6","IsGlobal": false,"id": "51584be5be0c6c6af057229afd341d592a55bf0e","name": "default.memcached1.6"},"533bd3e057f46120794828b5c797b3fe8aab1336": {"ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.redis2.6","CacheParameterGroupFamily": "redis2.6","Description": "Default parameter group for redis2.6","IsGlobal": false,"id": "533bd3e057f46120794828b5c797b3fe8aab1336","name": "default.redis2.6"},"579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": {"ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.redis3.2","CacheParameterGroupFamily": "redis3.2","Description": "Default parameter group for redis3.2","IsGlobal": false,"id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3","name": "default.redis3.2"},"6e3786a6f55135ca99b9432b0059a35deb2ae908": {"ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.redis5.0","CacheParameterGroupFamily": "redis5.0","Description": "Default parameter group for redis5.0","IsGlobal": false,"id": "6e3786a6f55135ca99b9432b0059a35deb2ae908","name": "default.redis5.0"},"89dee6407112ff413de0345de376d45c799f0028": {"ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.redis4.0.cluster.on","CacheParameterGroupFamily": "redis4.0","Description": "Customized default parameter group for redis4.0 with cluster mode on","IsGlobal": false,"id": "89dee6407112ff413de0345de376d45c799f0028","name": "default.redis4.0.cluster.on"},"92d124b9a74567482361fe34e367ac8bf5c02e0b": {"ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.redis6.x","CacheParameterGroupFamily": "redis6.x","Description": "Default parameter group for redis6.x","IsGlobal": false,"id": "92d124b9a74567482361fe34e367ac8bf5c02e0b","name": "default.redis6.x"},"a64a576f220009cfa7c322c46fc92d32a85a4978": {"ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.redis5.0.cluster.on","CacheParameterGroupFamily": "redis5.0","Description": "Customized default parameter group for redis5.0 with cluster mode on","IsGlobal": false,"id": "a64a576f220009cfa7c322c46fc92d32a85a4978","name": "default.redis5.0.cluster.on"},"c954e04f298cd030c6fde9c32c8365d1b9f76fb4": {"ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.redis4.0","CacheParameterGroupFamily": "redis4.0","Description": "Default parameter group for redis4.0","IsGlobal": false,"id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4","name": "default.redis4.0"},"e0934919fe4741105df762ae57b738fea22ebc40": {"ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.memcached1.5","CacheParameterGroupFamily": "memcached1.5","Description": "Default parameter group for memcached1.5","IsGlobal": false,"id": "e0934919fe4741105df762ae57b738fea22ebc40","name": "default.memcached1.5"}},"parameter_groups_count": 13,"region": "eu-west-3","security_groups": {},"security_groups_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-87d3fdee": {"arn": "arn:aws:vpc:eu-west-3:430150006394:virtual-private-cloud/vpc-87d3fdee","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-87d3fdee","name": "vpc-87d3fdee","state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"sa-east-1": {"clusters_count": 0,"id": "sa-east-1","name": "sa-east-1","parameter_groups": {"02e3d792a7e00a39f3c9fa0bb0445e86d7644525": {"ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.redis3.2.cluster.on","CacheParameterGroupFamily": "redis3.2","Description": "Customized default parameter group for redis3.2 with cluster mode on","IsGlobal": false,"id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525","name": "default.redis3.2.cluster.on"},"156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": {"ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.memcached1.4","CacheParameterGroupFamily": "memcached1.4","Description": "Default parameter group for memcached1.4","IsGlobal": false,"id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124","name": "default.memcached1.4"},"1a65eec91cd66eb16ba40e781620d9320ec1733f": {"ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.redis6.x.cluster.on","CacheParameterGroupFamily": "redis6.x","Description": "Customized default parameter group for redis6.x with cluster mode on","IsGlobal": false,"id": "1a65eec91cd66eb16ba40e781620d9320ec1733f","name": "default.redis6.x.cluster.on"},"3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": {"ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.redis2.8","CacheParameterGroupFamily": "redis2.8","Description": "Default parameter group for redis2.8","IsGlobal": false,"id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e","name": "default.redis2.8"},"51584be5be0c6c6af057229afd341d592a55bf0e": {"ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.memcached1.6","CacheParameterGroupFamily": "memcached1.6","Description": "Default parameter group for memcached1.6","IsGlobal": false,"id": "51584be5be0c6c6af057229afd341d592a55bf0e","name": "default.memcached1.6"},"533bd3e057f46120794828b5c797b3fe8aab1336": {"ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.redis2.6","CacheParameterGroupFamily": "redis2.6","Description": "Default parameter group for redis2.6","IsGlobal": false,"id": "533bd3e057f46120794828b5c797b3fe8aab1336","name": "default.redis2.6"},"579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": {"ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.redis3.2","CacheParameterGroupFamily": "redis3.2","Description": "Default parameter group for redis3.2","IsGlobal": false,"id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3","name": "default.redis3.2"},"6e3786a6f55135ca99b9432b0059a35deb2ae908": {"ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.redis5.0","CacheParameterGroupFamily": "redis5.0","Description": "Default parameter group for redis5.0","IsGlobal": false,"id": "6e3786a6f55135ca99b9432b0059a35deb2ae908","name": "default.redis5.0"},"89dee6407112ff413de0345de376d45c799f0028": {"ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.redis4.0.cluster.on","CacheParameterGroupFamily": "redis4.0","Description": "Customized default parameter group for redis4.0 with cluster mode on","IsGlobal": false,"id": "89dee6407112ff413de0345de376d45c799f0028","name": "default.redis4.0.cluster.on"},"92d124b9a74567482361fe34e367ac8bf5c02e0b": {"ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.redis6.x","CacheParameterGroupFamily": "redis6.x","Description": "Default parameter group for redis6.x","IsGlobal": false,"id": "92d124b9a74567482361fe34e367ac8bf5c02e0b","name": "default.redis6.x"},"a64a576f220009cfa7c322c46fc92d32a85a4978": {"ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.redis5.0.cluster.on","CacheParameterGroupFamily": "redis5.0","Description": "Customized default parameter group for redis5.0 with cluster mode on","IsGlobal": false,"id": "a64a576f220009cfa7c322c46fc92d32a85a4978","name": "default.redis5.0.cluster.on"},"c954e04f298cd030c6fde9c32c8365d1b9f76fb4": {"ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.redis4.0","CacheParameterGroupFamily": "redis4.0","Description": "Default parameter group for redis4.0","IsGlobal": false,"id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4","name": "default.redis4.0"},"e0934919fe4741105df762ae57b738fea22ebc40": {"ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.memcached1.5","CacheParameterGroupFamily": "memcached1.5","Description": "Default parameter group for memcached1.5","IsGlobal": false,"id": "e0934919fe4741105df762ae57b738fea22ebc40","name": "default.memcached1.5"}},"parameter_groups_count": 13,"region": "sa-east-1","security_groups": {},"security_groups_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-b14fa4d7": {"arn": "arn:aws:vpc:sa-east-1:430150006394:virtual-private-cloud/vpc-b14fa4d7","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-b14fa4d7","name": "vpc-b14fa4d7","state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"us-east-1": {"clusters_count": 0,"id": "us-east-1","name": "us-east-1","parameter_groups": {"02e3d792a7e00a39f3c9fa0bb0445e86d7644525": {"ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.redis3.2.cluster.on","CacheParameterGroupFamily": "redis3.2","Description": "Customized default parameter group for redis3.2 with cluster mode on","IsGlobal": false,"id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525","name": "default.redis3.2.cluster.on"},"156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": {"ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.memcached1.4","CacheParameterGroupFamily": "memcached1.4","Description": "Default parameter group for memcached1.4","IsGlobal": false,"id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124","name": "default.memcached1.4"},"1a65eec91cd66eb16ba40e781620d9320ec1733f": {"ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.redis6.x.cluster.on","CacheParameterGroupFamily": "redis6.x","Description": "Customized default parameter group for redis6.x with cluster mode on","IsGlobal": false,"id": "1a65eec91cd66eb16ba40e781620d9320ec1733f","name": "default.redis6.x.cluster.on"},"3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": {"ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.redis2.8","CacheParameterGroupFamily": "redis2.8","Description": "Default parameter group for redis2.8","IsGlobal": false,"id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e","name": "default.redis2.8"},"51584be5be0c6c6af057229afd341d592a55bf0e": {"ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.memcached1.6","CacheParameterGroupFamily": "memcached1.6","Description": "Default parameter group for memcached1.6","IsGlobal": false,"id": "51584be5be0c6c6af057229afd341d592a55bf0e","name": "default.memcached1.6"},"533bd3e057f46120794828b5c797b3fe8aab1336": {"ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.redis2.6","CacheParameterGroupFamily": "redis2.6","Description": "Default parameter group for redis2.6","IsGlobal": false,"id": "533bd3e057f46120794828b5c797b3fe8aab1336","name": "default.redis2.6"},"579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": {"ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.redis3.2","CacheParameterGroupFamily": "redis3.2","Description": "Default parameter group for redis3.2","IsGlobal": false,"id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3","name": "default.redis3.2"},"6e3786a6f55135ca99b9432b0059a35deb2ae908": {"ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.redis5.0","CacheParameterGroupFamily": "redis5.0","Description": "Default parameter group for redis5.0","IsGlobal": false,"id": "6e3786a6f55135ca99b9432b0059a35deb2ae908","name": "default.redis5.0"},"89dee6407112ff413de0345de376d45c799f0028": {"ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.redis4.0.cluster.on","CacheParameterGroupFamily": "redis4.0","Description": "Customized default parameter group for redis4.0 with cluster mode on","IsGlobal": false,"id": "89dee6407112ff413de0345de376d45c799f0028","name": "default.redis4.0.cluster.on"},"92d124b9a74567482361fe34e367ac8bf5c02e0b": {"ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.redis6.x","CacheParameterGroupFamily": "redis6.x","Description": "Default parameter group for redis6.x","IsGlobal": false,"id": "92d124b9a74567482361fe34e367ac8bf5c02e0b","name": "default.redis6.x"},"a64a576f220009cfa7c322c46fc92d32a85a4978": {"ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.redis5.0.cluster.on","CacheParameterGroupFamily": "redis5.0","Description": "Customized default parameter group for redis5.0 with cluster mode on","IsGlobal": false,"id": "a64a576f220009cfa7c322c46fc92d32a85a4978","name": "default.redis5.0.cluster.on"},"c954e04f298cd030c6fde9c32c8365d1b9f76fb4": {"ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.redis4.0","CacheParameterGroupFamily": "redis4.0","Description": "Default parameter group for redis4.0","IsGlobal": false,"id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4","name": "default.redis4.0"},"e0934919fe4741105df762ae57b738fea22ebc40": {"ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.memcached1.5","CacheParameterGroupFamily": "memcached1.5","Description": "Default parameter group for memcached1.5","IsGlobal": false,"id": "e0934919fe4741105df762ae57b738fea22ebc40","name": "default.memcached1.5"}},"parameter_groups_count": 13,"region": "us-east-1","security_groups": {},"security_groups_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-ba1cbdc7": {"arn": "arn:aws:vpc:us-east-1:430150006394:virtual-private-cloud/vpc-ba1cbdc7","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-ba1cbdc7","name": "vpc-ba1cbdc7","state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"us-east-2": {"clusters_count": 0,"id": "us-east-2","name": "us-east-2","parameter_groups": {"02e3d792a7e00a39f3c9fa0bb0445e86d7644525": {"ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.redis3.2.cluster.on","CacheParameterGroupFamily": "redis3.2","Description": "Customized default parameter group for redis3.2 with cluster mode on","IsGlobal": false,"id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525","name": "default.redis3.2.cluster.on"},"156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": {"ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.memcached1.4","CacheParameterGroupFamily": "memcached1.4","Description": "Default parameter group for memcached1.4","IsGlobal": false,"id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124","name": "default.memcached1.4"},"1a65eec91cd66eb16ba40e781620d9320ec1733f": {"ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.redis6.x.cluster.on","CacheParameterGroupFamily": "redis6.x","Description": "Customized default parameter group for redis6.x with cluster mode on","IsGlobal": false,"id": "1a65eec91cd66eb16ba40e781620d9320ec1733f","name": "default.redis6.x.cluster.on"},"3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": {"ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.redis2.8","CacheParameterGroupFamily": "redis2.8","Description": "Default parameter group for redis2.8","IsGlobal": false,"id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e","name": "default.redis2.8"},"51584be5be0c6c6af057229afd341d592a55bf0e": {"ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.memcached1.6","CacheParameterGroupFamily": "memcached1.6","Description": "Default parameter group for memcached1.6","IsGlobal": false,"id": "51584be5be0c6c6af057229afd341d592a55bf0e","name": "default.memcached1.6"},"579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": {"ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.redis3.2","CacheParameterGroupFamily": "redis3.2","Description": "Default parameter group for redis3.2","IsGlobal": false,"id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3","name": "default.redis3.2"},"6e3786a6f55135ca99b9432b0059a35deb2ae908": {"ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.redis5.0","CacheParameterGroupFamily": "redis5.0","Description": "Default parameter group for redis5.0","IsGlobal": false,"id": "6e3786a6f55135ca99b9432b0059a35deb2ae908","name": "default.redis5.0"},"89dee6407112ff413de0345de376d45c799f0028": {"ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.redis4.0.cluster.on","CacheParameterGroupFamily": "redis4.0","Description": "Customized default parameter group for redis4.0 with cluster mode on","IsGlobal": false,"id": "89dee6407112ff413de0345de376d45c799f0028","name": "default.redis4.0.cluster.on"},"92d124b9a74567482361fe34e367ac8bf5c02e0b": {"ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.redis6.x","CacheParameterGroupFamily": "redis6.x","Description": "Default parameter group for redis6.x","IsGlobal": false,"id": "92d124b9a74567482361fe34e367ac8bf5c02e0b","name": "default.redis6.x"},"a64a576f220009cfa7c322c46fc92d32a85a4978": {"ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.redis5.0.cluster.on","CacheParameterGroupFamily": "redis5.0","Description": "Customized default parameter group for redis5.0 with cluster mode on","IsGlobal": false,"id": "a64a576f220009cfa7c322c46fc92d32a85a4978","name": "default.redis5.0.cluster.on"},"c954e04f298cd030c6fde9c32c8365d1b9f76fb4": {"ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.redis4.0","CacheParameterGroupFamily": "redis4.0","Description": "Default parameter group for redis4.0","IsGlobal": false,"id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4","name": "default.redis4.0"},"e0934919fe4741105df762ae57b738fea22ebc40": {"ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.memcached1.5","CacheParameterGroupFamily": "memcached1.5","Description": "Default parameter group for memcached1.5","IsGlobal": false,"id": "e0934919fe4741105df762ae57b738fea22ebc40","name": "default.memcached1.5"}},"parameter_groups_count": 12,"region": "us-east-2","security_groups": {},"security_groups_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-e429ad8f": {"arn": "arn:aws:vpc:us-east-2:430150006394:virtual-private-cloud/vpc-e429ad8f","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-e429ad8f","name": "vpc-e429ad8f","state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"us-west-1": {"clusters_count": 0,"id": "us-west-1","name": "us-west-1","parameter_groups": {"02e3d792a7e00a39f3c9fa0bb0445e86d7644525": {"ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.redis3.2.cluster.on","CacheParameterGroupFamily": "redis3.2","Description": "Customized default parameter group for redis3.2 with cluster mode on","IsGlobal": false,"id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525","name": "default.redis3.2.cluster.on"},"156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": {"ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.memcached1.4","CacheParameterGroupFamily": "memcached1.4","Description": "Default parameter group for memcached1.4","IsGlobal": false,"id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124","name": "default.memcached1.4"},"1a65eec91cd66eb16ba40e781620d9320ec1733f": {"ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.redis6.x.cluster.on","CacheParameterGroupFamily": "redis6.x","Description": "Customized default parameter group for redis6.x with cluster mode on","IsGlobal": false,"id": "1a65eec91cd66eb16ba40e781620d9320ec1733f","name": "default.redis6.x.cluster.on"},"3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": {"ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.redis2.8","CacheParameterGroupFamily": "redis2.8","Description": "Default parameter group for redis2.8","IsGlobal": false,"id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e","name": "default.redis2.8"},"51584be5be0c6c6af057229afd341d592a55bf0e": {"ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.memcached1.6","CacheParameterGroupFamily": "memcached1.6","Description": "Default parameter group for memcached1.6","IsGlobal": false,"id": "51584be5be0c6c6af057229afd341d592a55bf0e","name": "default.memcached1.6"},"533bd3e057f46120794828b5c797b3fe8aab1336": {"ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.redis2.6","CacheParameterGroupFamily": "redis2.6","Description": "Default parameter group for redis2.6","IsGlobal": false,"id": "533bd3e057f46120794828b5c797b3fe8aab1336","name": "default.redis2.6"},"579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": {"ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.redis3.2","CacheParameterGroupFamily": "redis3.2","Description": "Default parameter group for redis3.2","IsGlobal": false,"id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3","name": "default.redis3.2"},"6e3786a6f55135ca99b9432b0059a35deb2ae908": {"ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.redis5.0","CacheParameterGroupFamily": "redis5.0","Description": "Default parameter group for redis5.0","IsGlobal": false,"id": "6e3786a6f55135ca99b9432b0059a35deb2ae908","name": "default.redis5.0"},"89dee6407112ff413de0345de376d45c799f0028": {"ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.redis4.0.cluster.on","CacheParameterGroupFamily": "redis4.0","Description": "Customized default parameter group for redis4.0 with cluster mode on","IsGlobal": false,"id": "89dee6407112ff413de0345de376d45c799f0028","name": "default.redis4.0.cluster.on"},"92d124b9a74567482361fe34e367ac8bf5c02e0b": {"ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.redis6.x","CacheParameterGroupFamily": "redis6.x","Description": "Default parameter group for redis6.x","IsGlobal": false,"id": "92d124b9a74567482361fe34e367ac8bf5c02e0b","name": "default.redis6.x"},"a64a576f220009cfa7c322c46fc92d32a85a4978": {"ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.redis5.0.cluster.on","CacheParameterGroupFamily": "redis5.0","Description": "Customized default parameter group for redis5.0 with cluster mode on","IsGlobal": false,"id": "a64a576f220009cfa7c322c46fc92d32a85a4978","name": "default.redis5.0.cluster.on"},"c954e04f298cd030c6fde9c32c8365d1b9f76fb4": {"ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.redis4.0","CacheParameterGroupFamily": "redis4.0","Description": "Default parameter group for redis4.0","IsGlobal": false,"id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4","name": "default.redis4.0"},"e0934919fe4741105df762ae57b738fea22ebc40": {"ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.memcached1.5","CacheParameterGroupFamily": "memcached1.5","Description": "Default parameter group for memcached1.5","IsGlobal": false,"id": "e0934919fe4741105df762ae57b738fea22ebc40","name": "default.memcached1.5"}},"parameter_groups_count": 13,"region": "us-west-1","security_groups": {},"security_groups_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-6e6fa508": {"arn": "arn:aws:vpc:us-west-1:430150006394:virtual-private-cloud/vpc-6e6fa508","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-6e6fa508","name": "vpc-6e6fa508","state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"us-west-2": {"clusters_count": 0,"id": "us-west-2","name": "us-west-2","parameter_groups": {"02e3d792a7e00a39f3c9fa0bb0445e86d7644525": {"ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.redis3.2.cluster.on","CacheParameterGroupFamily": "redis3.2","Description": "Customized default parameter group for redis3.2 with cluster mode on","IsGlobal": false,"id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525","name": "default.redis3.2.cluster.on"},"156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": {"ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.memcached1.4","CacheParameterGroupFamily": "memcached1.4","Description": "Default parameter group for memcached1.4","IsGlobal": false,"id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124","name": "default.memcached1.4"},"1a65eec91cd66eb16ba40e781620d9320ec1733f": {"ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.redis6.x.cluster.on","CacheParameterGroupFamily": "redis6.x","Description": "Customized default parameter group for redis6.x with cluster mode on","IsGlobal": false,"id": "1a65eec91cd66eb16ba40e781620d9320ec1733f","name": "default.redis6.x.cluster.on"},"3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": {"ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.redis2.8","CacheParameterGroupFamily": "redis2.8","Description": "Default parameter group for redis2.8","IsGlobal": false,"id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e","name": "default.redis2.8"},"51584be5be0c6c6af057229afd341d592a55bf0e": {"ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.memcached1.6","CacheParameterGroupFamily": "memcached1.6","Description": "Default parameter group for memcached1.6","IsGlobal": false,"id": "51584be5be0c6c6af057229afd341d592a55bf0e","name": "default.memcached1.6"},"533bd3e057f46120794828b5c797b3fe8aab1336": {"ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.redis2.6","CacheParameterGroupFamily": "redis2.6","Description": "Default parameter group for redis2.6","IsGlobal": false,"id": "533bd3e057f46120794828b5c797b3fe8aab1336","name": "default.redis2.6"},"579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": {"ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.redis3.2","CacheParameterGroupFamily": "redis3.2","Description": "Default parameter group for redis3.2","IsGlobal": false,"id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3","name": "default.redis3.2"},"6e3786a6f55135ca99b9432b0059a35deb2ae908": {"ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.redis5.0","CacheParameterGroupFamily": "redis5.0","Description": "Default parameter group for redis5.0","IsGlobal": false,"id": "6e3786a6f55135ca99b9432b0059a35deb2ae908","name": "default.redis5.0"},"89dee6407112ff413de0345de376d45c799f0028": {"ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.redis4.0.cluster.on","CacheParameterGroupFamily": "redis4.0","Description": "Customized default parameter group for redis4.0 with cluster mode on","IsGlobal": false,"id": "89dee6407112ff413de0345de376d45c799f0028","name": "default.redis4.0.cluster.on"},"92d124b9a74567482361fe34e367ac8bf5c02e0b": {"ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.redis6.x","CacheParameterGroupFamily": "redis6.x","Description": "Default parameter group for redis6.x","IsGlobal": false,"id": "92d124b9a74567482361fe34e367ac8bf5c02e0b","name": "default.redis6.x"},"a64a576f220009cfa7c322c46fc92d32a85a4978": {"ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.redis5.0.cluster.on","CacheParameterGroupFamily": "redis5.0","Description": "Customized default parameter group for redis5.0 with cluster mode on","IsGlobal": false,"id": "a64a576f220009cfa7c322c46fc92d32a85a4978","name": "default.redis5.0.cluster.on"},"c954e04f298cd030c6fde9c32c8365d1b9f76fb4": {"ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.redis4.0","CacheParameterGroupFamily": "redis4.0","Description": "Default parameter group for redis4.0","IsGlobal": false,"id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4","name": "default.redis4.0"},"e0934919fe4741105df762ae57b738fea22ebc40": {"ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.memcached1.5","CacheParameterGroupFamily": "memcached1.5","Description": "Default parameter group for memcached1.5","IsGlobal": false,"id": "e0934919fe4741105df762ae57b738fea22ebc40","name": "default.memcached1.5"}},"parameter_groups_count": 13,"region": "us-west-2","security_groups": {},"security_groups_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-d45709ac": {"arn": "arn:aws:vpc:us-west-2:430150006394:virtual-private-cloud/vpc-d45709ac","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-d45709ac","name": "vpc-d45709ac","state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1}},"regions_count": 17,"security_groups_count": 0},"elb": {"elb_policies_count": 0,"filters": {},"findings": {"elb-listener-allowing-cleartext": {"checked_items": 0,"compliance": null,"dashboard_name": "Load Balancer Listeners","description": "Load Balancer Allowing Clear Text (HTTP) Communication","display_path": "elb.regions.id.vpcs.id.elbs.id","flagged_items": 0,"items": [],"level": "danger","path": "elb.regions.id.vpcs.id.elbs.id.listeners.id","rationale": "Use of a secure protocol (HTTPS or SSL) is best practice for encrypted communication. A load balancer without a listener using an encrypted protocol can be vulnerable to eavesdropping and man-in-the-middle attacks.","references": ["https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-listener-config.html"],"remediation": null,"service": "ELB"},"elb-no-access-logs": {"checked_items": 0,"compliance": null,"dashboard_name": "Load Balancers","description": "Lack of ELB Access Logs","flagged_items": 0,"items": [],"level": "warning","path": "elb.regions.id.vpcs.id.elbs.id","rationale": "Elastic Load Balancing provides access logs that capture detailed information about requests sent to your load balancer. Each log contains information such as the time the request was received, the client's IP address, latencies, request paths, and server responses. You can use these access logs to analyze traffic patterns and identify security issues.","references": ["https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/access-log-collection.html"],"remediation": null,"service": "ELB"},"elb-older-ssl-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Load Balancer Listeners Security Policy","description": "Older SSL/TLS Policy","display_path": "elb.regions.id.elb_policies.id.reference_security_policy","flagged_items": 0,"items": [],"level": "danger","path": "elb.regions.id.elb_policies.id.reference_security_policy","rationale": "Use of the latest TLS policies is best practice. The recommended predefined security policies are:
  • ELBSecurityPolicy-2016-08
  • ELBSecurityPolicy-FS-2018-06
  • ELBSecurityPolicy-TLS-1-1-2017-01
  • ELBSecurityPolicy-TLS-1-2-2017-01
  • ELBSecurityPolicy-TLS-1-2-Ext-2018-06
  • ELBSecurityPolicy-FS-1-1-2019-08
  • ELBSecurityPolicy-FS-1-2-2019-08
  • ELBSecurityPolicy-FS-1-2-Res-2019-08
","references": ["https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-policy-table.html"],"remediation": null,"service": "ELB"}},"regions": {"ap-northeast-1": {"elb_policies": {},"elb_policies_count": 0,"id": "ap-northeast-1","name": "ap-northeast-1","region": "ap-northeast-1","vpcs": {"vpc-0cbc506a": {"arn": "arn:aws:vpc:ap-northeast-1:430150006394:virtual-private-cloud/vpc-0cbc506a","cidr_block": "172.31.0.0/16","default": true,"elbs": {},"elbs_count": 0,"id": "vpc-0cbc506a","name": "vpc-0cbc506a","state": "available"}},"vpcs_count": 1},"ap-northeast-2": {"elb_policies": {},"elb_policies_count": 0,"id": "ap-northeast-2","name": "ap-northeast-2","region": "ap-northeast-2","vpcs": {"vpc-73f44e18": {"arn": "arn:aws:vpc:ap-northeast-2:430150006394:virtual-private-cloud/vpc-73f44e18","cidr_block": "172.31.0.0/16","default": true,"elbs": {},"elbs_count": 0,"id": "vpc-73f44e18","name": "vpc-73f44e18","state": "available"}},"vpcs_count": 1},"ap-northeast-3": {"elb_policies": {},"elb_policies_count": 0,"id": "ap-northeast-3","name": "ap-northeast-3","region": "ap-northeast-3","vpcs": {"vpc-47b7dd2e": {"arn": "arn:aws:vpc:ap-northeast-3:430150006394:virtual-private-cloud/vpc-47b7dd2e","cidr_block": "172.31.0.0/16","default": true,"elbs": {},"elbs_count": 0,"id": "vpc-47b7dd2e","name": "vpc-47b7dd2e","state": "available"}},"vpcs_count": 1},"ap-south-1": {"elb_policies": {},"elb_policies_count": 0,"id": "ap-south-1","name": "ap-south-1","region": "ap-south-1","vpcs": {"vpc-2651a14d": {"arn": "arn:aws:vpc:ap-south-1:430150006394:virtual-private-cloud/vpc-2651a14d","cidr_block": "172.31.0.0/16","default": true,"elbs": {},"elbs_count": 0,"id": "vpc-2651a14d","name": "vpc-2651a14d","state": "available"}},"vpcs_count": 1},"ap-southeast-1": {"elb_policies": {},"elb_policies_count": 0,"id": "ap-southeast-1","name": "ap-southeast-1","region": "ap-southeast-1","vpcs": {"vpc-04ed1062": {"arn": "arn:aws:vpc:ap-southeast-1:430150006394:virtual-private-cloud/vpc-04ed1062","cidr_block": "172.31.0.0/16","default": true,"elbs": {},"elbs_count": 0,"id": "vpc-04ed1062","name": "vpc-04ed1062","state": "available"}},"vpcs_count": 1},"ap-southeast-2": {"elb_policies": {},"elb_policies_count": 0,"id": "ap-southeast-2","name": "ap-southeast-2","region": "ap-southeast-2","vpcs": {"vpc-5d22c33b": {"arn": "arn:aws:vpc:ap-southeast-2:430150006394:virtual-private-cloud/vpc-5d22c33b","cidr_block": "172.31.0.0/16","default": true,"elbs": {},"elbs_count": 0,"id": "vpc-5d22c33b","name": "vpc-5d22c33b","state": "available"}},"vpcs_count": 1},"ca-central-1": {"elb_policies": {},"elb_policies_count": 0,"id": "ca-central-1","name": "ca-central-1","region": "ca-central-1","vpcs": {"vpc-b5113ddd": {"arn": "arn:aws:vpc:ca-central-1:430150006394:virtual-private-cloud/vpc-b5113ddd","cidr_block": "172.31.0.0/16","default": true,"elbs": {},"elbs_count": 0,"id": "vpc-b5113ddd","name": "vpc-b5113ddd","state": "available"}},"vpcs_count": 1},"eu-central-1": {"elb_policies": {},"elb_policies_count": 0,"id": "eu-central-1","name": "eu-central-1","region": "eu-central-1","vpcs": {"vpc-78b43312": {"arn": "arn:aws:vpc:eu-central-1:430150006394:virtual-private-cloud/vpc-78b43312","cidr_block": "172.31.0.0/16","default": true,"elbs": {},"elbs_count": 0,"id": "vpc-78b43312","name": "vpc-78b43312","state": "available"}},"vpcs_count": 1},"eu-north-1": {"elb_policies": {},"elb_policies_count": 0,"id": "eu-north-1","name": "eu-north-1","region": "eu-north-1","vpcs": {"vpc-fa259d93": {"arn": "arn:aws:vpc:eu-north-1:430150006394:virtual-private-cloud/vpc-fa259d93","cidr_block": "172.31.0.0/16","default": true,"elbs": {},"elbs_count": 0,"id": "vpc-fa259d93","name": "vpc-fa259d93","state": "available"}},"vpcs_count": 1},"eu-west-1": {"elb_policies": {},"elb_policies_count": 0,"id": "eu-west-1","name": "eu-west-1","region": "eu-west-1","vpcs": {"vpc-f24c7994": {"arn": "arn:aws:vpc:eu-west-1:430150006394:virtual-private-cloud/vpc-f24c7994","cidr_block": "172.31.0.0/16","default": true,"elbs": {},"elbs_count": 0,"id": "vpc-f24c7994","name": "vpc-f24c7994","state": "available"}},"vpcs_count": 1},"eu-west-2": {"elb_policies": {},"elb_policies_count": 0,"id": "eu-west-2","name": "eu-west-2","region": "eu-west-2","vpcs": {"vpc-3fa2fa57": {"arn": "arn:aws:vpc:eu-west-2:430150006394:virtual-private-cloud/vpc-3fa2fa57","cidr_block": "172.31.0.0/16","default": true,"elbs": {},"elbs_count": 0,"id": "vpc-3fa2fa57","name": "vpc-3fa2fa57","state": "available"}},"vpcs_count": 1},"eu-west-3": {"elb_policies": {},"elb_policies_count": 0,"id": "eu-west-3","name": "eu-west-3","region": "eu-west-3","vpcs": {"vpc-87d3fdee": {"arn": "arn:aws:vpc:eu-west-3:430150006394:virtual-private-cloud/vpc-87d3fdee","cidr_block": "172.31.0.0/16","default": true,"elbs": {},"elbs_count": 0,"id": "vpc-87d3fdee","name": "vpc-87d3fdee","state": "available"}},"vpcs_count": 1},"sa-east-1": {"elb_policies": {},"elb_policies_count": 0,"id": "sa-east-1","name": "sa-east-1","region": "sa-east-1","vpcs": {"vpc-b14fa4d7": {"arn": "arn:aws:vpc:sa-east-1:430150006394:virtual-private-cloud/vpc-b14fa4d7","cidr_block": "172.31.0.0/16","default": true,"elbs": {},"elbs_count": 0,"id": "vpc-b14fa4d7","name": "vpc-b14fa4d7","state": "available"}},"vpcs_count": 1},"us-east-1": {"elb_policies": {},"elb_policies_count": 0,"id": "us-east-1","name": "us-east-1","region": "us-east-1","vpcs": {"vpc-ba1cbdc7": {"arn": "arn:aws:vpc:us-east-1:430150006394:virtual-private-cloud/vpc-ba1cbdc7","cidr_block": "172.31.0.0/16","default": true,"elbs": {},"elbs_count": 0,"id": "vpc-ba1cbdc7","name": "vpc-ba1cbdc7","state": "available"}},"vpcs_count": 1},"us-east-2": {"elb_policies": {},"elb_policies_count": 0,"id": "us-east-2","name": "us-east-2","region": "us-east-2","vpcs": {"vpc-e429ad8f": {"arn": "arn:aws:vpc:us-east-2:430150006394:virtual-private-cloud/vpc-e429ad8f","cidr_block": "172.31.0.0/16","default": true,"elbs": {},"elbs_count": 0,"id": "vpc-e429ad8f","name": "vpc-e429ad8f","state": "available"}},"vpcs_count": 1},"us-west-1": {"elb_policies": {},"elb_policies_count": 0,"id": "us-west-1","name": "us-west-1","region": "us-west-1","vpcs": {"vpc-6e6fa508": {"arn": "arn:aws:vpc:us-west-1:430150006394:virtual-private-cloud/vpc-6e6fa508","cidr_block": "172.31.0.0/16","default": true,"elbs": {},"elbs_count": 0,"id": "vpc-6e6fa508","name": "vpc-6e6fa508","state": "available"}},"vpcs_count": 1},"us-west-2": {"elb_policies": {},"elb_policies_count": 0,"id": "us-west-2","name": "us-west-2","region": "us-west-2","vpcs": {"vpc-d45709ac": {"arn": "arn:aws:vpc:us-west-2:430150006394:virtual-private-cloud/vpc-d45709ac","cidr_block": "172.31.0.0/16","default": true,"elbs": {},"elbs_count": 0,"id": "vpc-d45709ac","name": "vpc-d45709ac","state": "available"}},"vpcs_count": 1}},"regions_count": 17},"elbv2": {"filters": {},"findings": {"elbv2-http-request-smuggling": {"checked_items": 0,"compliance": null,"dashboard_name": "Load Balancer Attributes","description": "Drop Invalid Header Fields Disabled","display_path": "elbv2.regions.id.vpcs.id.lbs.id","flagged_items": 0,"items": [],"level": "danger","path": "elbv2.regions.id.vpcs.id.lbs.id.attributes.id","rationale": "Dropping invalid header fields should be enabled in order to mitigate the risk of request smuggling attacks.","references": ["https://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/API_LoadBalancerAttribute.html","https://medium.com/@emilefugulin/http-desync-attacks-with-python-and-aws-1ba07d2c860f","https://99designs.com/blog/engineering/request-smuggling/","https://portswigger.net/web-security/request-smuggling"],"remediation": null,"service": "ELBv2"},"elbv2-listener-allowing-cleartext": {"checked_items": 0,"compliance": null,"dashboard_name": "Load Balancer Listeners","description": "Load Balancer Allowing Clear Text (HTTP) Communication","display_path": "elbv2.regions.id.vpcs.id.lbs.id","flagged_items": 0,"items": [],"level": "danger","path": "elbv2.regions.id.vpcs.id.lbs.id.listeners.id.Protocol","rationale": "Use of a secure protocol (HTTPS or SSL) is best practice for encrypted communication. A load balancer without a listener using an encrypted protocol can be vulnerable to eavesdropping and man-in-the-middle attacks.","references": ["https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-https-load-balancers.html","https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html","https://docs.aws.amazon.com/elasticloadbalancing/latest/network/create-tls-listener.html"],"remediation": null,"service": "ELBv2"},"elbv2-no-access-logs": {"checked_items": 0,"compliance": null,"dashboard_name": "Load Balancer Attributes","description": "Lack of ELBv2 Access Logs","display_path": "elbv2.regions.id.vpcs.id.lbs.id","flagged_items": 0,"items": [],"level": "warning","path": "elbv2.regions.id.vpcs.id.lbs.id.attributes.id","rationale": "Elastic Load Balancing provides access logs that capture detailed information about requests sent to your load balancer. Each log contains information such as the time the request was received, the client's IP address, latencies, request paths, and server responses. You can use these access logs to analyze traffic patterns and identify security issues.

Note that for Network Load Balancers, access logs are created only if the load balancer has a TLS listener.","references": ["https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html","https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-access-logs.html"],"remediation": null,"service": "ELBv2"},"elbv2-no-deletion-protection": {"checked_items": 0,"compliance": null,"dashboard_name": "Load Balancer Attributes","description": "Lack of Deletion Protection","display_path": "elbv2.regions.id.vpcs.id.lbs.id","flagged_items": 0,"items": [],"level": "warning","path": "elbv2.regions.id.vpcs.id.lbs.id.attributes.id","rationale": "Enabling deletion protection on load balancers mitigates risks of accidental deletion.","references": ["https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#deletion-protection"],"remediation": null,"service": "ELBv2"},"elbv2-older-ssl-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Load Balancer Listeners","description": "Older SSL/TLS Policy","display_path": "elbv2.regions.id.vpcs.id.lbs.id","flagged_items": 0,"items": [],"level": "warning","path": "elbv2.regions.id.vpcs.id.lbs.id.listeners.id.SslPolicy","rationale": "Use of the latest TLS policies is best practice. The recommended predefined security policies are:
  • ELBSecurityPolicy-2016-08
  • ELBSecurityPolicy-FS-2018-06
  • ELBSecurityPolicy-TLS-1-1-2017-01
  • ELBSecurityPolicy-TLS-1-2-2017-01
  • ELBSecurityPolicy-TLS-1-2-Ext-2018-06
  • ELBSecurityPolicy-FS-1-1-2019-08
  • ELBSecurityPolicy-FS-1-2-2019-08
  • ELBSecurityPolicy-FS-1-2-Res-2019-08
","references": ["https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html#describe-ssl-policies"],"remediation": null,"service": "ELBv2"}},"regions": {"ap-northeast-1": {"id": "ap-northeast-1","name": "ap-northeast-1","region": "ap-northeast-1","vpcs": {"vpc-0cbc506a": {"arn": "arn:aws:vpc:ap-northeast-1:430150006394:virtual-private-cloud/vpc-0cbc506a","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-0cbc506a","lbs": {},"lbs_count": 0,"name": "vpc-0cbc506a","state": "available"}},"vpcs_count": 1},"ap-northeast-2": {"id": "ap-northeast-2","name": "ap-northeast-2","region": "ap-northeast-2","vpcs": {"vpc-73f44e18": {"arn": "arn:aws:vpc:ap-northeast-2:430150006394:virtual-private-cloud/vpc-73f44e18","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-73f44e18","lbs": {},"lbs_count": 0,"name": "vpc-73f44e18","state": "available"}},"vpcs_count": 1},"ap-northeast-3": {"id": "ap-northeast-3","name": "ap-northeast-3","region": "ap-northeast-3","vpcs": {"vpc-47b7dd2e": {"arn": "arn:aws:vpc:ap-northeast-3:430150006394:virtual-private-cloud/vpc-47b7dd2e","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-47b7dd2e","lbs": {},"lbs_count": 0,"name": "vpc-47b7dd2e","state": "available"}},"vpcs_count": 1},"ap-south-1": {"id": "ap-south-1","name": "ap-south-1","region": "ap-south-1","vpcs": {"vpc-2651a14d": {"arn": "arn:aws:vpc:ap-south-1:430150006394:virtual-private-cloud/vpc-2651a14d","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-2651a14d","lbs": {},"lbs_count": 0,"name": "vpc-2651a14d","state": "available"}},"vpcs_count": 1},"ap-southeast-1": {"id": "ap-southeast-1","name": "ap-southeast-1","region": "ap-southeast-1","vpcs": {"vpc-04ed1062": {"arn": "arn:aws:vpc:ap-southeast-1:430150006394:virtual-private-cloud/vpc-04ed1062","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-04ed1062","lbs": {},"lbs_count": 0,"name": "vpc-04ed1062","state": "available"}},"vpcs_count": 1},"ap-southeast-2": {"id": "ap-southeast-2","name": "ap-southeast-2","region": "ap-southeast-2","vpcs": {"vpc-5d22c33b": {"arn": "arn:aws:vpc:ap-southeast-2:430150006394:virtual-private-cloud/vpc-5d22c33b","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-5d22c33b","lbs": {},"lbs_count": 0,"name": "vpc-5d22c33b","state": "available"}},"vpcs_count": 1},"ca-central-1": {"id": "ca-central-1","name": "ca-central-1","region": "ca-central-1","vpcs": {"vpc-b5113ddd": {"arn": "arn:aws:vpc:ca-central-1:430150006394:virtual-private-cloud/vpc-b5113ddd","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-b5113ddd","lbs": {},"lbs_count": 0,"name": "vpc-b5113ddd","state": "available"}},"vpcs_count": 1},"eu-central-1": {"id": "eu-central-1","name": "eu-central-1","region": "eu-central-1","vpcs": {"vpc-78b43312": {"arn": "arn:aws:vpc:eu-central-1:430150006394:virtual-private-cloud/vpc-78b43312","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-78b43312","lbs": {},"lbs_count": 0,"name": "vpc-78b43312","state": "available"}},"vpcs_count": 1},"eu-north-1": {"id": "eu-north-1","name": "eu-north-1","region": "eu-north-1","vpcs": {"vpc-fa259d93": {"arn": "arn:aws:vpc:eu-north-1:430150006394:virtual-private-cloud/vpc-fa259d93","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-fa259d93","lbs": {},"lbs_count": 0,"name": "vpc-fa259d93","state": "available"}},"vpcs_count": 1},"eu-west-1": {"id": "eu-west-1","name": "eu-west-1","region": "eu-west-1","vpcs": {"vpc-f24c7994": {"arn": "arn:aws:vpc:eu-west-1:430150006394:virtual-private-cloud/vpc-f24c7994","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-f24c7994","lbs": {},"lbs_count": 0,"name": "vpc-f24c7994","state": "available"}},"vpcs_count": 1},"eu-west-2": {"id": "eu-west-2","name": "eu-west-2","region": "eu-west-2","vpcs": {"vpc-3fa2fa57": {"arn": "arn:aws:vpc:eu-west-2:430150006394:virtual-private-cloud/vpc-3fa2fa57","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-3fa2fa57","lbs": {},"lbs_count": 0,"name": "vpc-3fa2fa57","state": "available"}},"vpcs_count": 1},"eu-west-3": {"id": "eu-west-3","name": "eu-west-3","region": "eu-west-3","vpcs": {"vpc-87d3fdee": {"arn": "arn:aws:vpc:eu-west-3:430150006394:virtual-private-cloud/vpc-87d3fdee","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-87d3fdee","lbs": {},"lbs_count": 0,"name": "vpc-87d3fdee","state": "available"}},"vpcs_count": 1},"sa-east-1": {"id": "sa-east-1","name": "sa-east-1","region": "sa-east-1","vpcs": {"vpc-b14fa4d7": {"arn": "arn:aws:vpc:sa-east-1:430150006394:virtual-private-cloud/vpc-b14fa4d7","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-b14fa4d7","lbs": {},"lbs_count": 0,"name": "vpc-b14fa4d7","state": "available"}},"vpcs_count": 1},"us-east-1": {"id": "us-east-1","name": "us-east-1","region": "us-east-1","vpcs": {"vpc-ba1cbdc7": {"arn": "arn:aws:vpc:us-east-1:430150006394:virtual-private-cloud/vpc-ba1cbdc7","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-ba1cbdc7","lbs": {},"lbs_count": 0,"name": "vpc-ba1cbdc7","state": "available"}},"vpcs_count": 1},"us-east-2": {"id": "us-east-2","name": "us-east-2","region": "us-east-2","vpcs": {"vpc-e429ad8f": {"arn": "arn:aws:vpc:us-east-2:430150006394:virtual-private-cloud/vpc-e429ad8f","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-e429ad8f","lbs": {},"lbs_count": 0,"name": "vpc-e429ad8f","state": "available"}},"vpcs_count": 1},"us-west-1": {"id": "us-west-1","name": "us-west-1","region": "us-west-1","vpcs": {"vpc-6e6fa508": {"arn": "arn:aws:vpc:us-west-1:430150006394:virtual-private-cloud/vpc-6e6fa508","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-6e6fa508","lbs": {},"lbs_count": 0,"name": "vpc-6e6fa508","state": "available"}},"vpcs_count": 1},"us-west-2": {"id": "us-west-2","name": "us-west-2","region": "us-west-2","vpcs": {"vpc-d45709ac": {"arn": "arn:aws:vpc:us-west-2:430150006394:virtual-private-cloud/vpc-d45709ac","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-d45709ac","lbs": {},"lbs_count": 0,"name": "vpc-d45709ac","state": "available"}},"vpcs_count": 1}},"regions_count": 17},"emr": {"clusters_count": 0,"filters": {},"findings": {},"regions": {"ap-northeast-1": {"clusters_count": 0,"id": "ap-northeast-1","name": "ap-northeast-1","region": "ap-northeast-1","vpcs": {},"vpcs_count": 1},"ap-northeast-2": {"clusters_count": 0,"id": "ap-northeast-2","name": "ap-northeast-2","region": "ap-northeast-2","vpcs": {},"vpcs_count": 1},"ap-northeast-3": {"clusters_count": 0,"id": "ap-northeast-3","name": "ap-northeast-3","region": "ap-northeast-3","vpcs": {},"vpcs_count": 1},"ap-south-1": {"clusters_count": 0,"id": "ap-south-1","name": "ap-south-1","region": "ap-south-1","vpcs": {},"vpcs_count": 1},"ap-southeast-1": {"clusters_count": 0,"id": "ap-southeast-1","name": "ap-southeast-1","region": "ap-southeast-1","vpcs": {},"vpcs_count": 1},"ap-southeast-2": {"clusters_count": 0,"id": "ap-southeast-2","name": "ap-southeast-2","region": "ap-southeast-2","vpcs": {},"vpcs_count": 1},"ca-central-1": {"clusters_count": 0,"id": "ca-central-1","name": "ca-central-1","region": "ca-central-1","vpcs": {},"vpcs_count": 1},"eu-central-1": {"clusters_count": 0,"id": "eu-central-1","name": "eu-central-1","region": "eu-central-1","vpcs": {},"vpcs_count": 1},"eu-north-1": {"clusters_count": 0,"id": "eu-north-1","name": "eu-north-1","region": "eu-north-1","vpcs": {},"vpcs_count": 1},"eu-west-1": {"clusters_count": 0,"id": "eu-west-1","name": "eu-west-1","region": "eu-west-1","vpcs": {},"vpcs_count": 1},"eu-west-2": {"clusters_count": 0,"id": "eu-west-2","name": "eu-west-2","region": "eu-west-2","vpcs": {},"vpcs_count": 1},"eu-west-3": {"clusters_count": 0,"id": "eu-west-3","name": "eu-west-3","region": "eu-west-3","vpcs": {},"vpcs_count": 1},"sa-east-1": {"clusters_count": 0,"id": "sa-east-1","name": "sa-east-1","region": "sa-east-1","vpcs": {},"vpcs_count": 1},"us-east-1": {"clusters_count": 0,"id": "us-east-1","name": "us-east-1","region": "us-east-1","vpcs": {},"vpcs_count": 1},"us-east-2": {"clusters_count": 0,"id": "us-east-2","name": "us-east-2","region": "us-east-2","vpcs": {},"vpcs_count": 1},"us-west-1": {"clusters_count": 0,"id": "us-west-1","name": "us-west-1","region": "us-west-1","vpcs": {},"vpcs_count": 1},"us-west-2": {"clusters_count": 0,"id": "us-west-2","name": "us-west-2","region": "us-west-2","vpcs": {},"vpcs_count": 1}},"regions_count": 17},"iam": {"credential_reports": {"06f47b690457429238adabc75e53fc0c93bf6c77": {"access_key_1_active": "true","access_key_1_last_rotated": "2013-12-19T09:13:40+00:00","access_key_1_last_used_date": null,"access_key_1_last_used_region": "N/A","access_key_1_last_used_service": "N/A","access_key_2_active": "true","access_key_2_last_rotated": "2019-01-25T17:58:41+00:00","access_key_2_last_used_date": "2021-03-19T12:26:00+00:00","access_key_2_last_used_region": "ca-central-1","access_key_2_last_used_service": "cloudwatch","arn": "arn:aws:iam::430150006394:user/dams","cert_1_active": "false","cert_1_last_rotated": "N/A","cert_2_active": "false","cert_2_last_rotated": "N/A","id": "06f47b690457429238adabc75e53fc0c93bf6c77","last_used": "2021-03-19T12:26:00+00:00","mfa_active": "false","mfa_active_hardware": false,"name": "dams","password_enabled": "false","password_last_changed": null,"password_last_used": null,"password_next_rotation": "N/A","user": "dams","user_creation_time": "2013-12-19T09:13:40+00:00"},"68dcc047c3da5bbbc3f3e9d54000b7357f0e507e": {"access_key_1_active": "true","access_key_1_last_rotated": "2021-03-19T12:29:26+00:00","access_key_1_last_used_date": "2021-03-19T12:33:00+00:00","access_key_1_last_used_region": "eu-north-1","access_key_1_last_used_service": "ec2","access_key_2_active": "false","access_key_2_last_rotated": null,"access_key_2_last_used_date": null,"access_key_2_last_used_region": "N/A","access_key_2_last_used_service": "N/A","arn": "arn:aws:iam::430150006394:root","cert_1_active": "false","cert_1_last_rotated": "N/A","cert_2_active": "false","cert_2_last_rotated": "N/A","id": "68dcc047c3da5bbbc3f3e9d54000b7357f0e507e","last_used": "2021-04-28T10:51:19+00:00","mfa_active": "false","mfa_active_hardware": false,"name": "","password_enabled": "not_supported","password_last_changed": "not_supported","password_last_used": "2021-04-28T10:51:19+00:00","password_next_rotation": "not_supported","user": "","user_creation_time": "2013-12-19T08:57:25+00:00"}},"credential_reports_count": 2,"filters": {"iam-role-for-EC2": {"checked_items": 9,"compliance": null,"dashboard_name": "Roles","description": "Role for EC2","display_path": "iam.roles.id","flagged_items": 1,"items": ["iam.roles.AROAI265GPNVMDZAKJPPA.assume_role_policy.PolicyDocument.Statement.0"],"level": "","path": "iam.roles.id.assume_role_policy.PolicyDocument.Statement.id","rationale": null,"references": null,"remediation": null,"service": "IAM"},"iam-role-for-Lambda": {"checked_items": 9,"compliance": null,"dashboard_name": "Roles","description": "Role for Lambda","display_path": "iam.roles.id","flagged_items": 1,"items": ["iam.roles.AROAJY5MNJYDKGD2UIATQ.assume_role_policy.PolicyDocument.Statement.0"],"level": "","path": "iam.roles.id.assume_role_policy.PolicyDocument.Statement.id","rationale": null,"references": null,"remediation": null,"service": "IAM"},"iam-role-for-cross-account": {"checked_items": 9,"compliance": null,"dashboard_name": "Roles","description": "Role for cross account","display_path": "iam.roles.id","flagged_items": 0,"items": [],"level": "","path": "iam.roles.id.assume_role_policy.PolicyDocument.Statement.id","rationale": null,"references": null,"remediation": null,"service": "IAM"},"iam-role-for-same-account": {"checked_items": 9,"compliance": null,"dashboard_name": "Roles","description": "Role for same account","display_path": "iam.roles.id","flagged_items": 0,"items": [],"level": "","path": "iam.roles.id.assume_role_policy.PolicyDocument.Statement.id","rationale": null,"references": null,"remediation": null,"service": "IAM"}},"findings": {"iam-assume-role-lacks-external-id-and-mfa": {"checked_items": 9,"compliance": null,"dashboard_name": "Roles","description": "Cross-Account AssumeRole Policy Lacks External ID and MFA","display_path": "iam.roles.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.roles.id.assume_role_policy.PolicyDocument.Statement.id","rationale": "When authorizing cross-account role assumption, either an External ID or MFA should be required. If the role is intended for use by a service, an External ID can prevent \"confused deputy\" attacks. If the role is intended for use by an external user, then MFA will strengthen the authentication by requiring a second factor.","references": ["https://research.nccgroup.com/2019/12/18/demystifying-aws-assumerole-and-stsexternalid/","https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html"],"remediation": null,"service": "IAM"},"iam-assume-role-policy-allows-all": {"checked_items": 9,"compliance": null,"dashboard_name": "Roles","description": "AssumeRole Policy Allows All Principals","display_path": "iam.roles.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.roles.id.assume_role_policy.PolicyDocument.Statement.id","rationale": "Setting the AssumeRole policy's principal attribute to \"AWS:*\" means that anyone is authorized to assume the role and access the AWS account.","references": ["https://research.nccgroup.com/2019/12/18/demystifying-aws-assumerole-and-stsexternalid/"],"remediation": null,"service": "IAM"},"iam-ec2-role-without-instances": {"checked_items": 0,"compliance": null,"dashboard_name": "Roles","description": "Unused Role for EC2 Service","display_path": "iam.roles.id","flagged_items": 0,"id_suffix": "instances","items": [],"level": "warning","path": "iam.roles.id.assume_role_policy.Statement.id.Principal","rationale": "An EC2 role is defined which is unused and may not be required. This being the case, its existence in the configuration increases the risk that it may be inappropriately assigned. The unused role should be reviewed and removed if no longer required.","references": ["https://aws.amazon.com/about-aws/whats-new/2019/11/identify-unused-iam-roles-easily-and-remove-them-confidently-by-using-the-last-used-timestamp/"],"remediation": null,"service": "IAM"},"iam-group-with-inline-policies": {"checked_items": 1,"compliance": null,"dashboard_name": "Groups","description": "Group with Inline Policies","flagged_items": 1,"id_suffix": "inline_policies","items": ["iam.groups.AGPAIW3P3726RZDVZBZL2.inline_policies"],"level": "warning","path": "iam.groups.id","rationale": "An inline policy is a policy that's embedded in an IAM identity (a user, group, or role). These policies are harder to audit and manage, and should be deprecated in favor of managed policies.","references": ["https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#best-practice-managed-vs-inline","https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html"],"remediation": null,"service": "IAM"},"iam-group-with-no-users": {"checked_items": 1,"compliance": null,"dashboard_name": "groups","description": "Group with No Users","flagged_items": 0,"items": [],"level": "warning","path": "iam.groups.id","rationale": "Groups with no users should be reviewed and deleted if not necessary.","references": ["https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#use-groups-for-permissions"],"remediation": null,"service": "IAM"},"iam-inline-group-policy-allows-NotActions": {"checked_items": 1,"compliance": null,"dashboard_name": "Statements","description": "Inline group Policy Allows \"NotActions\"","display_path": "iam.groups.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.groups.id.inline_policies.id.PolicyDocument.Statement.id","rationale": "The combination of \"effect = allow\" and \"NotAction\" results in the policy allowing every action except those listed in the statement. The target policy does not follow the principle of least privilege because thousands of actions exist in AWS and because this policy automatically authorizes users to perform new actions created, regardless of their nature.","references": ["https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html","https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notaction.html","https://aws.amazon.com/blogs/security/back-to-school-understanding-the-iam-policy-grammar/"],"remediation": null,"service": "IAM"},"iam-inline-group-policy-allows-iam-PassRole": {"checked_items": 1,"compliance": null,"dashboard_name": "Policies","description": "Inline group Policy Allows \"iam:PassRole\" For All Resources","display_path": "iam.groups.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.groups.id.inline_policies.id.PolicyDocument.Statement.id","rationale": "Using \"*\" for the resource field might grant permissions to more resources than necessary, potentially introducing privilege escalation scenarios.","references": ["https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html"],"remediation": null,"service": "IAM"},"iam-inline-group-policy-allows-sts-AssumeRole": {"checked_items": 1,"compliance": null,"dashboard_name": "Policies","description": "Inline group Policy Allows \"sts:AssumeRole\" For All Resources","display_path": "iam.groups.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.groups.id.inline_policies.id.PolicyDocument.Statement.id","rationale": "Using \"*\" for the resource field might grant permissions to more resources than necessary, potentially introducing privilege escalation scenarios.","references": ["https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html"],"remediation": null,"service": "IAM"},"iam-inline-role-policy-allows-NotActions": {"checked_items": 0,"compliance": null,"dashboard_name": "Statements","description": "Inline role Policy Allows \"NotActions\"","display_path": "iam.roles.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.roles.id.inline_policies.id.PolicyDocument.Statement.id","rationale": "The combination of \"effect = allow\" and \"NotAction\" results in the policy allowing every action except those listed in the statement. The target policy does not follow the principle of least privilege because thousands of actions exist in AWS and because this policy automatically authorizes users to perform new actions created, regardless of their nature.","references": ["https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html","https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notaction.html","https://aws.amazon.com/blogs/security/back-to-school-understanding-the-iam-policy-grammar/"],"remediation": null,"service": "IAM"},"iam-inline-role-policy-allows-iam-PassRole": {"checked_items": 0,"compliance": null,"dashboard_name": "Policies","description": "Inline role Policy Allows \"iam:PassRole\" For All Resources","display_path": "iam.roles.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.roles.id.inline_policies.id.PolicyDocument.Statement.id","rationale": "Using \"*\" for the resource field might grant permissions to more resources than necessary, potentially introducing privilege escalation scenarios.","references": ["https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html"],"remediation": null,"service": "IAM"},"iam-inline-role-policy-allows-sts-AssumeRole": {"checked_items": 0,"compliance": null,"dashboard_name": "Policies","description": "Inline role Policy Allows \"sts:AssumeRole\" For All Resources","display_path": "iam.roles.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.roles.id.inline_policies.id.PolicyDocument.Statement.id","rationale": "Using \"*\" for the resource field might grant permissions to more resources than necessary, potentially introducing privilege escalation scenarios.","references": ["https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html"],"remediation": null,"service": "IAM"},"iam-inline-user-policy-allows-NotActions": {"checked_items": 0,"compliance": null,"dashboard_name": "Statements","description": "Inline user Policy Allows \"NotActions\"","display_path": "iam.users.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.users.id.inline_policies.id.PolicyDocument.Statement.id","rationale": "The combination of \"effect = allow\" and \"NotAction\" results in the policy allowing every action except those listed in the statement. The target policy does not follow the principle of least privilege because thousands of actions exist in AWS and because this policy automatically authorizes users to perform new actions created, regardless of their nature.","references": ["https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html","https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notaction.html","https://aws.amazon.com/blogs/security/back-to-school-understanding-the-iam-policy-grammar/"],"remediation": null,"service": "IAM"},"iam-inline-user-policy-allows-iam-PassRole": {"checked_items": 0,"compliance": null,"dashboard_name": "Policies","description": "Inline user Policy Allows \"iam:PassRole\" For All Resources","display_path": "iam.users.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.users.id.inline_policies.id.PolicyDocument.Statement.id","rationale": "Using \"*\" for the resource field might grant permissions to more resources than necessary, potentially introducing privilege escalation scenarios.","references": ["https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html"],"remediation": null,"service": "IAM"},"iam-inline-user-policy-allows-sts-AssumeRole": {"checked_items": 0,"compliance": null,"dashboard_name": "Policies","description": "Inline user Policy Allows \"sts:AssumeRole\" For All Resources","display_path": "iam.users.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.users.id.inline_policies.id.PolicyDocument.Statement.id","rationale": "Using \"*\" for the resource field might grant permissions to more resources than necessary, potentially introducing privilege escalation scenarios.","references": ["https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html"],"remediation": null,"service": "IAM"},"iam-managed-policy-allows-NotActions": {"checked_items": 14,"compliance": null,"dashboard_name": "Statements","description": "Managed Policy Allows \"NotActions\"","display_path": "iam.policies.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.policies.id.PolicyDocument.Statement.id","rationale": "The combination of \"effect = allow\" and \"NotAction\" results in the policy allowing every action except those listed in the statement. The target policy does not follow the principle of least privilege because thousands of actions exist in AWS and because this policy automatically authorizes users to perform new actions created, regardless of their nature.","references": ["https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notaction.html","https://aws.amazon.com/blogs/security/back-to-school-understanding-the-iam-policy-grammar/"],"remediation": null,"service": "IAM"},"iam-managed-policy-allows-full-privileges": {"checked_items": 14,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "1.24","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.22","version": "1.2.0"}],"dashboard_name": "Statements","description": "Managed Policy Allows All Actions","display_path": "iam.policies.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.policies.id.PolicyDocument.Statement.id","rationale": "Providing full privileges instead of restricting to the minimum set of permissions that the principal requires exposes the resources to potentially unwanted actions.","references": ["https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html","https://aws.amazon.com/blogs/security/back-to-school-understanding-the-iam-policy-grammar/"],"remediation": "Ensure no managed policies are configured with Effect: Allow, Action: * and Resource: *","service": "IAM"},"iam-managed-policy-allows-iam-PassRole": {"checked_items": 14,"compliance": null,"dashboard_name": "Statements","description": "Managed Policy Allows \"iam:PassRole\" For All Resources","display_path": "iam.policies.id","flagged_items": 1,"items": ["iam.policies.ANPAIDI2BQT2LKXZG36TW.PolicyDocument.Statement.0"],"level": "danger","path": "iam.policies.id.PolicyDocument.Statement.id","rationale": "Using \"*\" for the resource field might grant permissions to more resources than necessary, potentially introducing privilege escalation scenarios.","references": ["https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html"],"remediation": null,"service": "IAM"},"iam-managed-policy-allows-sts-AssumeRole": {"checked_items": 14,"compliance": null,"dashboard_name": "Statements","description": "Managed Policy Allows \"sts:AssumeRole\" For All Resources","display_path": "iam.policies.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.policies.id.PolicyDocument.Statement.id","rationale": "Using \"*\" for the resource field might grant permissions to more resources than necessary, potentially introducing privilege escalation scenarios.","references": ["https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html"],"remediation": null,"service": "IAM"},"iam-managed-policy-no-attachments": {"checked_items": 9,"compliance": null,"dashboard_name": "Policies","description": "Managed Policy Not Attached to Any Entity","display_path": "iam.policies.id","flagged_items": 0,"items": [],"level": "warning","path": "iam.policies.id","rationale": "Customer Managed policies should be reviewed and deleted if not necessary.","references": ["https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#customer-managed-policies"],"remediation": null,"service": "IAM"},"iam-password-policy-expiration-threshold": {"checked_items": 1,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "1.11","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.11","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.11","version": "1.2.0"}],"dashboard_name": "Password policy","description": "Passwords Expire after 90 Days","display_path": "iam.password_policy.MaxPasswordAge","flagged_items": 1,"id_suffix": "MaxPasswordAge","items": ["iam.password_policy.MaxPasswordAge"],"level": "danger","path": "iam.password_policy","rationale": "Password expiration is disabled, or expiration time is set to a too high value. As a result, compromised credentials could be used by potential attackers for a larger period of time. Periodic password change enforced with an appropriate password expiration policy could help to mitigate this issue.","references": ["https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-cis-controls-1.11"],"remediation": "Enable password expiration and set the expiration period to 90 days or less","service": "IAM"},"iam-password-policy-minimum-length": {"checked_items": 1,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "1.9","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.9","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.9","version": "1.2.0"}],"dashboard_name": "Password policy","description": "Minimum Password Length Too Short","flagged_items": 1,"items": ["iam.password_policy.MinimumPasswordLength"],"level": "danger","path": "iam.password_policy.MinimumPasswordLength","rationale": "The password policy did not enforce a minimum of 14 characters. As a result, password complexity requirements were not in line with security best practice.","references": ["https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-cis-controls-1.9"],"remediation": "Ensure the password policy is configured to require a minimum length","service": "IAM"},"iam-password-policy-no-expiration": {"checked_items": 1,"compliance": null,"dashboard_name": "Password policy","description": "Password Expiration Disabled","flagged_items": 1,"items": ["iam.password_policy.ExpirePasswords"],"level": "danger","path": "iam.password_policy.ExpirePasswords","rationale": "Password expiration is disabled. As a result, compromised credentials could be used by potential attackers for a indefinite amount of time. Periodic password change enforced with an appropriate password expiration policy could help to mitigate this issue.","references": ["https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-cis-controls-1.11"],"remediation": null,"service": "IAM"},"iam-password-policy-reuse-enabled": {"checked_items": 1,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "1.10","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.10","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.10","version": "1.2.0"}],"dashboard_name": "Password policy","description": "Password Policy Allows the Reuse of Passwords","flagged_items": 1,"items": ["iam.password_policy.PasswordReusePrevention"],"level": "danger","path": "iam.password_policy.PasswordReusePrevention","rationale": "The password policy allowed password reuse. As a result, password complexity requirements were not in line with security best practice.","references": ["https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-cis-controls-1.10"],"remediation": "Ensure the password policy is configured to prevent password reuse","service": "IAM"},"iam-role-with-inline-policies": {"checked_items": 9,"compliance": null,"dashboard_name": "Roles","description": "Role with Inline Policies","flagged_items": 0,"id_suffix": "inline_policies","items": [],"level": "warning","path": "iam.roles.id","rationale": "An inline policy is a policy that's embedded in an IAM identity (a user, group, or role). These policies are harder to audit and manage, and should be deprecated in favor of managed policies.","references": ["https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#best-practice-managed-vs-inline","https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html"],"remediation": null,"service": "IAM"},"iam-root-account-no-hardware-mfa": {"checked_items": 2,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "1.13","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.14","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.14","version": "1.2.0"}],"dashboard_name": "Accounts","description": "Root Account without Hardware MFA","flagged_items": 1,"id_suffix": "mfa_active_hardware","items": ["iam.credential_reports.68dcc047c3da5bbbc3f3e9d54000b7357f0e507e.mfa_active_hardware"],"level": "danger","path": "iam.credential_reports.id","rationale": "The root account is the most privileged user in an account. MFA adds an extra layer of protection on top of a user name and password. With MFA enabled, when a user signs in to an AWS website, they're prompted for their user name and password and for an authentication code from their AWS MFA device.","references": ["https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-cis-controls-1.13"],"remediation": "Enable MFA for the root account","service": "IAM"},"iam-root-account-no-mfa": {"checked_items": 2,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "1.13","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.13","version": "1.2.0"}],"dashboard_name": "Accounts","description": "Root Account without MFA","flagged_items": 1,"id_suffix": "mfa_active","items": ["iam.credential_reports.68dcc047c3da5bbbc3f3e9d54000b7357f0e507e.mfa_active"],"level": "danger","path": "iam.credential_reports.id","rationale": "The root account is the most privileged user in an account. MFA adds an extra layer of protection on top of a user name and password. With MFA enabled, when a user signs in to an AWS website, they're prompted for their user name and password and for an authentication code from their AWS MFA device.","references": ["https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-cis-controls-1.13"],"remediation": "Enable MFA for the root account","service": "IAM"},"iam-root-account-used-recently": {"checked_items": 2,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "1.1","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.1","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.1","version": "1.2.0"}],"dashboard_name": "Root account","description": "Root Account Used Recently","flagged_items": 0,"id_suffix": "password_last_used","items": [],"level": "danger","path": "iam.credential_reports.id","rationale": "The root account is the most privileged user in an account. As a best practice, the root account should only be used when required for root-only tasks.","references": ["https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-standards-cis-controls-1.1","https://docs.aws.amazon.com/general/latest/gr/aws_tasks-that-require-root.html"],"remediation": "Follow the remediation instructions of the Ensure IAM policies are attached only to groups or roles recommendation","service": "IAM"},"iam-root-account-with-active-certs": {"checked_items": 2,"compliance": null,"dashboard_name": "Root account","description": "Root Account Has Active X.509 Certs","flagged_items": 0,"items": [],"level": "danger","path": "iam.credential_reports.id","rationale": "Root account X.509 certificates should be deleted as they may be used to make SOAP-protocol requests in the context of the root account.","references": ["https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-standards-cis-controls-1.1"],"remediation": null,"service": "IAM"},"iam-root-account-with-active-keys": {"checked_items": 2,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "1.12","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.12","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.12","version": "1.2.0"}],"dashboard_name": "Root account","description": "Root Account Has Active Keys","flagged_items": 1,"items": ["iam.credential_reports.68dcc047c3da5bbbc3f3e9d54000b7357f0e507e"],"level": "danger","path": "iam.credential_reports.id","rationale": "AWS root account access keys should be deleted as they provide unrestricted access to the AWS Account.","references": ["https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-standards-cis-controls-1.1"],"remediation": "Delete or disable active root account access keys","service": "IAM"},"iam-unused-credentials-not-disabled": {"checked_items": 2,"class_suffix": "unused_credentials","compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "1.3","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.3","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.3","version": "1.2.0"}],"dashboard_name": "Users","description": "Credentials Unused for 90 Days or Greater Are Not Disabled","flagged_items": 2,"items": ["iam.credential_reports.68dcc047c3da5bbbc3f3e9d54000b7357f0e507e.unused_credentials","iam.credential_reports.06f47b690457429238adabc75e53fc0c93bf6c77.unused_credentials"],"level": "danger","path": "iam.credential_reports.id","rationale": "Disabling or removing unnecessary credentials will reduce the window of opportunity for compromised accounts to be used.","references": null,"remediation": "Ensure that all credentials (including passwords and access keys) have been used and changed in the last 90 days","service": "IAM"},"iam-user-no-Active-key-rotation": {"checked_items": 2,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "1.4","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.4","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.4","version": "1.2.0"}],"dashboard_name": "Access keys","description": "Lack of Key Rotation for (Active) Days","display_path": "iam.users.id","flagged_items": 2,"items": ["iam.users.AIDAJUK77MEJCW5J3DWZU.AccessKeys.0","iam.users.AIDAJUK77MEJCW5J3DWZU.AccessKeys.1"],"level": "danger","path": "iam.users.id.AccessKeys.id","rationale": "In case of access key compromise, the lack of credential rotation increases the period during which an attacker has access to the AWS account.","references": ["https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#rotate-credentials"],"remediation": "Rotate access keys that have not been changed recently","service": "IAM"},"iam-user-no-Inactive-key-rotation": {"checked_items": 2,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "1.4","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.4","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.4","version": "1.2.0"}],"dashboard_name": "Access keys","description": "Lack of Key Rotation for (Inactive) Days","display_path": "iam.users.id","flagged_items": 0,"items": [],"level": "warning","path": "iam.users.id.AccessKeys.id","rationale": "In case of access key compromise, the lack of credential rotation increases the period during which an attacker has access to the AWS account.","references": ["https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#rotate-credentials"],"remediation": "Rotate access keys that have not been changed recently","service": "IAM"},"iam-user-with-inline-policies": {"checked_items": 1,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "1.15","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.16","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.16","version": "1.2.0"}],"dashboard_name": "Users","description": "User with inline Policies","flagged_items": 0,"id_suffix": "inline_policies","items": [],"level": "warning","path": "iam.users.id","rationale": "The user was found to be attached to inline policies. This can increase the complexity in user and policy management, and increase the risk of the user being assigned or retaining excessive permissions.","references": null,"remediation": "Ensure IAM policies are only attached to groups or roles","service": "IAM"},"iam-user-with-multiple-access-keys": {"checked_items": 1,"compliance": null,"dashboard_name": "Users","description": "User with Multiple API Keys","flagged_items": 1,"id_suffix": "multiple_api_keys","items": ["iam.users.AIDAJUK77MEJCW5J3DWZU.multiple_api_keys"],"level": "warning","path": "iam.users.id","rationale": "The user was configured to have more than one active API keys associated with the account. Redundant or unused API keys should be removed.","references": ["https://docs.aws.amazon.com/general/latest/gr/aws-access-keys-best-practices.html"],"remediation": null,"service": "IAM"},"iam-user-with-password-and-key": {"checked_items": 1,"compliance": null,"dashboard_name": "Users","description": "User with Password and Keys Enabled","flagged_items": 0,"id_suffix": "password_and_keys","items": [],"level": "warning","path": "iam.users.id","rationale": "The user was found to have configured with both password and API keys for authentication. This is considered against security best practice.","references": ["https://docs.aws.amazon.com/general/latest/gr/aws-access-keys-best-practices.html","https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_admin-change-user.html"],"remediation": null,"service": "IAM"},"iam-user-without-mfa": {"checked_items": 1,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "1.2","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.2","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "1.2","version": "1.2.0"}],"dashboard_name": "Users","description": "User without MFA","flagged_items": 0,"id_suffix": "mfa_enabled","items": [],"level": "danger","path": "iam.users.id","rationale": "All IAM users should have MFA. MFA adds an extra layer of protection on top of a user name and password. With MFA enabled, when a user signs in to an AWS website, they're prompted for their user name and password and for an authentication code from their AWS MFA device.","references": ["https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#enable-mfa-for-privileged-users"],"remediation": "Enable MFA for all users in the AWS account","service": "IAM"}},"groups": {"AGPAIW3P3726RZDVZBZL2": {"CreateDate": "2013-12-19 09:13:40+00:00","Path": "/","arn": "arn:aws:iam::430150006394:group/devs","id": "AGPAIW3P3726RZDVZBZL2","inline_policies": {"58cd3df92811df89e93933e00cd5a76813cf6258": {"PolicyDocument": {"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version": "2012-10-17"},"name": "AdministratorAccess-201312191013"}},"inline_policies_count": 1,"name": "devs","users": ["AIDAJUK77MEJCW5J3DWZU"]}},"groups_count": 1,"password_policy": {"AllowUsersToChangePassword": true,"ExpirePasswords": false,"MinimumPasswordLength": 6,"PasswordReusePrevention": false,"RequireLowercaseCharacters": false,"RequireNumbers": false,"RequireSymbols": false,"RequireUppercaseCharacters": false},"password_policy_count": 0,"permissions": {"Action": {"*": {"groups": {"Allow": {"AGPAIW3P3726RZDVZBZL2": {"Resource": {"*": {"inline_policies": {"58cd3df92811df89e93933e00cd5a76813cf6258": {"condition": null}}}}}}}},"a4b:getDevice": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"a4b:getProfile": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"a4b:getRoom": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"a4b:getRoomSkillParameter": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"a4b:getSkillGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"a4b:searchDevices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"a4b:searchProfiles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"a4b:searchRooms": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"a4b:searchSkillGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"access-analyzer:getFinding": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"access-analyzer:listAnalyzers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"access-analyzer:listArchiveRules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"access-analyzer:listFindings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm-pca:describeCertificateAuthority": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm-pca:describeCertificateAuthorityAuditReport": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm-pca:getCertificate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm-pca:getCertificateAuthorityCertificate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm-pca:getCertificateAuthorityCsr": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm-pca:listCertificateAuthorities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm-pca:listTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm:describeCertificate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm:getCertificate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm:listCertificates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm:listTagsForCertificate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"airflow:getEnvironment": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"airflow:listEnvironments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"airflow:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"amplify:getApp": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"amplify:getBranch": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"amplify:getDomainAssociation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"amplify:getJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"amplify:getWebhook": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"amplify:listApps": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"amplify:listWebhooks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"apigateway:GET": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"arn:aws:apigateway:*::/account": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/authorizers": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/authorizers/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/deployments": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/deployments/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/integrations": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/integrations/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/integrations/*/integrationresponses": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/integrations/*/integrationresponses/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/models": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/models/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/routes": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/routes/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/routes/*/routeresponses": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/routes/*/routeresponses/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/stages": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/stages/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/clientcertificates": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/clientcertificates/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/domainnames": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/domainnames/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/domainnames/*/apimappings": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/domainnames/*/apimappings/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/domainnames/*/basepathmappings": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/domainnames/*/basepathmappings/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/authorizers": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/authorizers/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/deployments": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/deployments/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/models": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/models/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/models/*/default_template": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/resources": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/resources/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/resources/*/methods/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/integration": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/integration/responses/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/responses/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/stages": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/stages/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/stages/*/sdks/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appflow:describeConnectorEntity": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appflow:describeConnectorProfiles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appflow:describeFlow": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appflow:listFlows": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"application-autoscaling:DeleteScalingPolicy": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"application-autoscaling:DeregisterScalableTarget": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"application-autoscaling:Describe*": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"application-autoscaling:PutScalingPolicy": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"application-autoscaling:RegisterScalableTarget": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"application-autoscaling:describeScalableTargets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"application-autoscaling:describeScalingActivities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"application-autoscaling:describeScalingPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"application-autoscaling:describeScheduledActions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"applicationinsights:describeComponentConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"applicationinsights:describeComponentConfigurationRecommendation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"applicationinsights:listApplications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"applicationinsights:listComponents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"applicationinsights:listConfigurationHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"applicationinsights:listLogPatternSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"applicationinsights:listLogPatterns": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:describeGatewayRoute": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:describeMesh": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:describeRoute": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:describeVirtualGateway": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:describeVirtualNode": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:describeVirtualRouter": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:describeVirtualService": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:listGatewayRoutes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:listMeshes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:listRoutes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:listVirtualGateways": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:listVirtualNodes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:listVirtualRouters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:listVirtualServices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"apprunner:describeAutoScalingConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"apprunner:describeCustomDomains": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"apprunner:describeOperation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"apprunner:describeService": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"apprunner:listAutoScalingConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"apprunner:listConnections": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"apprunner:listOperations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"apprunner:listServices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"apprunner:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appstream:describeDirectoryConfigs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appstream:describeFleets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appstream:describeImageBuilders": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appstream:describeImages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appstream:describeSessions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appstream:describeStacks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appstream:listAssociatedFleets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appstream:listAssociatedStacks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appstream:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:getFunction": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:getGraphqlApi": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:getIntrospectionSchema": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:getResolver": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:getSchemaCreationStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:getType": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:listDataSources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:listFunctions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:listGraphqlApis": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:listResolvers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:listTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"athena:batchGetNamedQuery": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"athena:batchGetQueryExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"athena:getNamedQuery": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"athena:getQueryExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"athena:getWorkGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"athena:listNamedQueries": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"athena:listQueryExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"athena:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"athena:listWorkGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"auditmanager:getAccountStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"auditmanager:getDelegations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"auditmanager:listAssessmentFrameworks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"auditmanager:listAssessmentReports": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"auditmanager:listAssessments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"auditmanager:listControls": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"auditmanager:listKeywordsForDataSource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"auditmanager:listNotifications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling-plans:describeScalingPlanResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling-plans:describeScalingPlans": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling-plans:getScalingPlanResourceForecastData": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:DescribeAccountLimits": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"autoscaling:DescribeAutoScalingGroups": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"autoscaling:DescribeLaunchConfigurations": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"autoscaling:describeAccountLimits": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeAdjustmentTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeAutoScalingGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeAutoScalingInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeAutoScalingNotificationTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeInstanceRefreshes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeLaunchConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeLifecycleHookTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeLifecycleHooks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeLoadBalancerTargetGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeLoadBalancers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeMetricCollectionTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeNotificationConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describePolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeScalingActivities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeScalingProcessTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeScheduledActions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeTerminationPolicyTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:describeBackupJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:describeBackupVault": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:describeProtectedResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:describeRecoveryPoint": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:describeRestoreJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:getBackupPlan": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:getBackupPlanFromJSON": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:getBackupPlanFromTemplate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:getBackupSelection": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:getBackupVaultAccessPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:getBackupVaultNotifications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:getRecoveryPointRestoreMetadata": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:getSupportedResourceTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listBackupJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listBackupPlanTemplates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listBackupPlanVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listBackupPlans": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listBackupSelections": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listBackupVaults": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listProtectedResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listRecoveryPointsByBackupVault": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listRecoveryPointsByResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listRestoreJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"batch:describeComputeEnvironments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"batch:describeJobDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"batch:describeJobQueues": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"batch:describeJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"batch:listJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"braket:getDevice": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"braket:getQuantumTask": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"braket:searchDevices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"braket:searchQuantumTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"budgets:viewBudget": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ce:GetReservationPurchaseRecommendation": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ce:GetSavingsPlansPurchaseRecommendation": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ce:getCostAndUsage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ce:getCostAndUsageWithResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ce:getCostForecast": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ce:getDimensionValues": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ce:getReservationCoverage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ce:getReservationPurchaseRecommendation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ce:getReservationUtilization": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ce:getRightsizingRecommendation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ce:getSavingsPlansCoverage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ce:getSavingsPlansPurchaseRecommendation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ce:getSavingsPlansUtilization": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ce:getSavingsPlansUtilizationDetails": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ce:getTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloud9:describeEnvironmentMemberships": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloud9:describeEnvironments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloud9:listEnvironments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"clouddirectory:getDirectory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"clouddirectory:listDirectories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:DescribeAccountLimits": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"cloudformation:DescribeStacks": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"cloudformation:ListStacks": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"cloudformation:describeAccountLimits": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:describeChangeSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:describeStackEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:describeStackInstance": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:describeStackResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:describeStackResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:describeStackSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:describeStackSetOperation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:describeStacks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:estimateTemplateCost": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:getStackPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:getTemplate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:getTemplateSummary": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:listChangeSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:listExports": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:listImports": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:listStackInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:listStackResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:listStackSetOperationResults": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:listStackSetOperations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:listStackSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:listStacks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:ListDistributions": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"cloudfront:getCloudFrontOriginAccessIdentity": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:getCloudFrontOriginAccessIdentityConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:getDistribution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:getDistributionConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:getInvalidation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:getStreamingDistribution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:getStreamingDistributionConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:listCloudFrontOriginAccessIdentities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:listDistributions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:listDistributionsByWebACLId": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:listInvalidations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:listStreamingDistributions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudhsm:describeBackups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudhsm:describeClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudsearch:describeAnalysisSchemes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudsearch:describeAvailabilityOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudsearch:describeDomains": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudsearch:describeExpressions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudsearch:describeIndexFields": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudsearch:describeScalingParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudsearch:describeServiceAccessPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudsearch:describeSuggesters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudsearch:listDomainNames": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudtrail:DescribeTrails": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}},"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}}}}},"cloudtrail:GetEventSelectors": {"roles": {"Allow": {"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}}}}},"cloudtrail:GetTrailStatus": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}},"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}}}}},"cloudtrail:describeTrails": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudtrail:getEventSelectors": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudtrail:getInsightSelectors": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudtrail:getTrail": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudtrail:getTrailStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudtrail:listPublicKeys": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudtrail:listTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudtrail:listTrails": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudtrail:lookupEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudwatch:*": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"cloudwatch:DeleteAlarms": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"cloudwatch:DescribeAlarms": {"roles": {"Allow": {"AROAIH747R37LKSEOZ2MA": {"Resource": {"*": {"policies": {"ANPAJSVXG6QHPE6VHDZ4Q": {"condition": null}}}}},"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}}}}},"cloudwatch:DescribeAlarmsForMetric": {"roles": {"Allow": {"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}}}}},"cloudwatch:GetMetricStatistics": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"cloudwatch:PutMetricAlarm": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"cloudwatch:describeAlarmHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudwatch:describeAlarms": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudwatch:describeAlarmsForMetric": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudwatch:describeAnomalyDetectors": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudwatch:describeInsightRules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudwatch:getDashboard": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudwatch:getInsightRuleReport": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudwatch:getMetricData": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudwatch:getMetricStatistics": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudwatch:listDashboards": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudwatch:listMetrics": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:describeDomain": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:describePackageVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:describeRepository": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:getDomainPermissionsPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:getRepositoryEndPoint": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:getRepositoryPermissionsPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:listDomains": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:listPackageVersionAssets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:listPackageVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:listPackages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:listRepositories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:listRepositoriesInDomain": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codebuild:batchGetBuildBatches": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codebuild:batchGetBuilds": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codebuild:batchGetProjects": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codebuild:listBuildBatches": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codebuild:listBuildBatchesForProject": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codebuild:listBuilds": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codebuild:listBuildsForProject": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codebuild:listCuratedEnvironmentImages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codebuild:listProjects": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codebuild:listSourceCredentials": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codecommit:batchGetRepositories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codecommit:getBranch": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codecommit:getRepository": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codecommit:getRepositoryTriggers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codecommit:listBranches": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codecommit:listRepositories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:batchGetApplicationRevisions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:batchGetApplications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:batchGetDeploymentGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:batchGetDeploymentInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:batchGetDeploymentTargets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:batchGetDeployments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:batchGetOnPremisesInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:getApplication": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:getApplicationRevision": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:getDeployment": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:getDeploymentConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:getDeploymentGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:getDeploymentInstance": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:getDeploymentTarget": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:getOnPremisesInstance": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:listApplicationRevisions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:listApplications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:listDeploymentConfigs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:listDeploymentGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:listDeploymentInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:listDeploymentTargets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:listDeployments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:listGitHubAccountTokenNames": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:listOnPremisesInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codepipeline:getJobDetails": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codepipeline:getPipeline": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codepipeline:getPipelineExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codepipeline:getPipelineState": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codepipeline:listActionExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codepipeline:listActionTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codepipeline:listPipelineExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codepipeline:listPipelines": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codepipeline:listWebhooks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codestar:describeProject": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codestar:listProjects": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codestar:listResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codestar:listTeamMembers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codestar:listUserProfiles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-identity:describeIdentityPool": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-identity:getIdentityPoolRoles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-identity:listIdentities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-identity:listIdentityPools": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:adminGetUser": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:describeIdentityProvider": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:describeResourceServer": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:describeRiskConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:describeUserImportJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:describeUserPool": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:describeUserPoolClient": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:describeUserPoolDomain": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:getGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:getUICustomization": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:getUser": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:getUserPoolMfaConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:listGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:listIdentityProviders": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:listResourceServers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:listUserImportJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:listUserPoolClients": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:listUserPools": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-sync:describeDataset": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-sync:describeIdentityPoolUsage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-sync:describeIdentityUsage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-sync:getCognitoEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-sync:getIdentityPoolConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-sync:listDatasets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-sync:listIdentityPoolUsage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"compute-optimizer:getAutoScalingGroupRecommendations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"compute-optimizer:getEBSVolumeRecommendations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"compute-optimizer:getEC2InstanceRecommendations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"compute-optimizer:getEC2RecommendationProjectedMetrics": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"compute-optimizer:getEnrollmentStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"compute-optimizer:getRecommendationSummaries": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"config:BatchGetResourceConfig": {"roles": {"Allow": {"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}}}}},"config:DeleteConfigRule": {"roles": {"Allow": {"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"arn:aws:config:*:*:config-rule/aws-service-rule/*securityhub*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}}}}},"config:DescribeConfigRuleEvaluationStatus": {"roles": {"Allow": {"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"arn:aws:config:*:*:config-rule/aws-service-rule/*securityhub*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}}}}},"config:DescribeConfigRules": {"roles": {"Allow": {"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}}}}},"config:DescribeConfigurationRecorderStatus": {"roles": {"Allow": {"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}}}}},"config:DescribeConfigurationRecorders": {"roles": {"Allow": {"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}}}}},"config:GetComplianceDetailsByConfigRule": {"roles": {"Allow": {"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"arn:aws:config:*:*:config-rule/aws-service-rule/*securityhub*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}}}}},"config:PutConfigRule": {"roles": {"Allow": {"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"arn:aws:config:*:*:config-rule/aws-service-rule/*securityhub*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}}}}},"config:PutEvaluations": {"roles": {"Allow": {"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}}}}},"config:SelectResourceConfig": {"roles": {"Allow": {"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}}}}},"config:describeConfigRuleEvaluationStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"config:describeConfigRules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"config:describeConfigurationRecorderStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"config:describeConfigurationRecorders": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"config:describeDeliveryChannelStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"config:describeDeliveryChannels": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"config:getResourceConfigHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"config:listDiscoveredResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"connect:describeUser": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"connect:getCurrentMetricData": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"connect:getMetricData": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"connect:listRoutingProfiles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"connect:listSecurityProfiles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"connect:listUsers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:describeAccountFactoryConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:describeCoreService": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:describeGuardrail": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:describeGuardrailForTarget": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:describeManagedAccount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:describeSingleSignOn": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:getAvailableUpdates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:getHomeRegion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:getLandingZoneStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:listDirectoryGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:listGuardrailViolations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:listGuardrailsForTarget": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:listManagedAccounts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:listManagedAccountsForGuardrail": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:listManagedAccountsForParent": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:listManagedOrganizationalUnits": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:listManagedOrganizationalUnitsForGuardrail": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"databrew:describeDataset": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"databrew:describeJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"databrew:describeProject": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"databrew:describeRecipe": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"databrew:listDatasets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"databrew:listJobRuns": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"databrew:listJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"databrew:listProjects": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"databrew:listRecipeVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"databrew:listRecipes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"databrew:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datapipeline:describeObjects": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datapipeline:describePipelines": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datapipeline:getPipelineDefinition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datapipeline:listPipelines": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datapipeline:queryObjects": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:describeAgent": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:describeLocationEfs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:describeLocationFsxWindows": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:describeLocationNfs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:describeLocationObjectStorage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:describeLocationS3": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:describeLocationSmb": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:describeTask": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:describeTaskExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:listAgents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:listLocations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:listTaskExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:listTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dax:describeClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dax:describeDefaultParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dax:describeEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dax:describeParameterGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dax:describeParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dax:describeSubnetGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"detective:getMembers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"detective:listGraphs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"detective:listInvitations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"detective:listMembers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getAccountSettings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getDevice": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getDevicePool": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getDevicePoolCompatibility": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getProject": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getRemoteAccessSession": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getRun": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getSuite": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getTest": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getTestGridProject": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getTestGridSession": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getUpload": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listArtifacts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listDevicePools": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listDevices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listProjects": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listRemoteAccessSessions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listRuns": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listSamples": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listSuites": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listTestGridProjects": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listTestGridSessionActions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listTestGridSessionArtifacts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listTestGridSessions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listTests": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listUniqueProblems": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listUploads": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"directconnect:describeConnections": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"directconnect:describeConnectionsOnInterconnect": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"directconnect:describeInterconnects": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"directconnect:describeLocations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"directconnect:describeVirtualGateways": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"directconnect:describeVirtualInterfaces": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dlm:getLifecyclePolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dlm:getLifecyclePolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dms:describeAccountAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dms:describeConnections": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dms:describeEndpointTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dms:describeEndpoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dms:describeOrderableReplicationInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dms:describeRefreshSchemasStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dms:describeReplicationInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dms:describeReplicationSubnetGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ds:describeConditionalForwarders": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ds:describeDirectories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ds:describeEventTopics": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ds:describeSnapshots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ds:describeTrusts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ds:getDirectoryLimits": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ds:getSnapshotLimits": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ds:listIpRoutes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ds:listSchemaExtensions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ds:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:*": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"dynamodb:DescribeLimits": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"dynamodb:DescribeTable": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"dynamodb:ListTables": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"dynamodb:describeBackup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:describeContinuousBackups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:describeGlobalTable": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:describeLimits": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:describeStream": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:describeTable": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:describeTimeToLive": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:listBackups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:listGlobalTables": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:listStreams": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:listTables": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:listTagsOfResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:AuthorizeSecurityGroupEgress": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:AuthorizeSecurityGroupIngress": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:CancelSpotInstanceRequests": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:CreateFleet": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:CreateLaunchTemplate": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:CreateNetworkInterface": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:CreateSecurityGroup": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:CreateTags": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DeleteLaunchTemplate": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:DeleteNetworkInterface": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:DeletePlacementGroup": {"roles": {"Allow": {"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:DeleteSecurityGroup": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DeleteTags": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DeleteVolume": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:Describe*": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"ec2:DescribeAccountAttributes": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeAddresses": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}},"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"ec2:DescribeAvailabilityZones": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeByoipCidrs": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"ec2:DescribeDhcpOptions": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeImages": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeInstanceAttribute": {"roles": {"Allow": {"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:DescribeInstanceStatus": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeInstances": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}},"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeInternetGateways": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeKeyPairs": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeLaunchTemplateVersions": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeLaunchTemplates": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:DescribeNetworkAcls": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeNetworkInterfaces": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribePlacementGroups": {"roles": {"Allow": {"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:DescribePrefixLists": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeReservedInstances": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeReservedInstancesOfferings": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeRouteTables": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeSecurityGroups": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeSnapshots": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeSpotInstanceRequests": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:DescribeSpotPriceHistory": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeSubnets": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeTags": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeVolumeStatus": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:DescribeVolumes": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}},"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeVpcAttribute": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeVpcEndpointServices": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeVpcEndpoints": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"ec2:DescribeVpcs": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}},"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"ec2:DescribeVpnConnections": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeVpnGateways": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DetachNetworkInterface": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DetachVolume": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:ModifyImageAttribute": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:ModifyInstanceAttribute": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:RequestSpotInstances": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:RevokeSecurityGroupEgress": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:RunInstances": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:TerminateInstances": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:acceptReservedInstancesExchangeQuote": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:cancelReservedInstancesListing": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:createReservedInstancesListing": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeAccountAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeAddresses": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeAvailabilityZones": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeBundleTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeByoipCidrs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeCapacityReservations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeClassicLinkInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeClientVpnAuthorizationRules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeClientVpnConnections": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeClientVpnEndpoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeClientVpnRoutes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeClientVpnTargetNetworks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeCoipPools": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeConversionTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeCustomerGateways": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeDhcpOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeElasticGpus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeExportImageTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeExportTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeFastSnapshotRestores": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeFleetHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeFleetInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeFleets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeFlowLogs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeHostReservationOfferings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeHostReservations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeHosts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeIdFormat": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeIdentityIdFormat": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeImageAttribute": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeImages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeImportImageTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeImportSnapshotTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeInstanceAttribute": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeInstanceStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeInternetGateways": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeKeyPairs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeLaunchTemplateVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeLaunchTemplates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeLocalGatewayRouteTableVirtualInterfaceGroupAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeLocalGatewayRouteTableVpcAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeLocalGatewayRouteTables": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeLocalGatewayVirtualInterfaceGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeLocalGatewayVirtualInterfaces": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeLocalGateways": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeMovingAddresses": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeNatGateways": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeNetworkAcls": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeNetworkInterfaceAttribute": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeNetworkInterfaces": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describePlacementGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describePrefixLists": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describePublicIpv4Pools": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeRegions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeReservedInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeReservedInstancesListings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeReservedInstancesModifications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeReservedInstancesOfferings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeRouteTables": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeScheduledInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeSecurityGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeSnapshotAttribute": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeSnapshots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeSpotDatafeedSubscription": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeSpotFleetInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeSpotFleetRequestHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeSpotFleetRequests": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeSpotInstanceRequests": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeSpotPriceHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeSubnets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeTrafficMirrorFilters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeTrafficMirrorSessions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeTrafficMirrorTargets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeTransitGatewayAttachments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeTransitGatewayRouteTables": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeTransitGatewayVpcAttachments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeTransitGateways": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVolumeAttribute": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVolumeStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVolumes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVolumesModifications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcAttribute": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcClassicLink": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcClassicLinkDnsSupport": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcEndpointConnectionNotifications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcEndpointConnections": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcEndpointServiceConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcEndpointServicePermissions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcEndpointServices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcEndpoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcPeeringConnections": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpnConnections": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpnGateways": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:getCoipPoolUsage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:getConsoleScreenshot": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:getReservedInstancesExchangeQuote": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:getTransitGatewayAttachmentPropagations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:getTransitGatewayRouteTableAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:getTransitGatewayRouteTablePropagations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:modifyReservedInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:purchaseReservedInstancesOffering": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:searchLocalGatewayRoutes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr-public:describeImageTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr-public:describeImages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr-public:describeRegistries": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr-public:describeRepositories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr-public:getRegistryCatalogData": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr-public:getRepositoryCatalogData": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr-public:getRepositoryPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr-public:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr:batchCheckLayerAvailability": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr:describeImageScanFindings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr:describeImages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr:describeRegistry": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr:describeRepositories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr:getLifecyclePolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr:getRegistryPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr:getRepositoryPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr:listImages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:describeCapacityProviders": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:describeClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:describeContainerInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:describeServices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:describeTaskDefinition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:describeTaskSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:describeTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:listAccountSettings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:listAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:listClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:listContainerInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:listServices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:listTaskDefinitionFamilies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:listTaskDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:listTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"eks:describeCluster": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"eks:describeFargateProfile": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"eks:describeNodegroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"eks:describeUpdate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"eks:listClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"eks:listFargateProfiles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"eks:listNodegroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"eks:listUpdates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeCacheClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeCacheEngineVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeCacheParameterGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeCacheParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeCacheSecurityGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeCacheSubnetGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeEngineDefaultParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeReplicationGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeReservedCacheNodes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeReservedCacheNodesOfferings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeSnapshots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:listAllowedNodeTypeModifications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:checkDNSAvailability": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeApplicationVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeApplications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeConfigurationOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeConfigurationSettings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeEnvironmentHealth": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeEnvironmentManagedActionHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeEnvironmentManagedActions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeEnvironmentResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeEnvironments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeInstancesHealth": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describePlatformVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:listAvailableSolutionStacks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:listPlatformVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:validateConfigurationSettings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticfilesystem:describeAccessPoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticfilesystem:describeFileSystemPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticfilesystem:describeFileSystems": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticfilesystem:describeLifecycleConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticfilesystem:describeMountTargetSecurityGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticfilesystem:describeMountTargets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticfilesystem:describeTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticfilesystem:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:DescribeAccountLimits": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"elasticloadbalancing:DescribeInstanceHealth": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"elasticloadbalancing:DescribeLoadBalancerAttributes": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"elasticloadbalancing:DescribeLoadBalancerPolicies": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"elasticloadbalancing:DescribeLoadBalancerPolicyTypes": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"elasticloadbalancing:DescribeLoadBalancers": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"elasticloadbalancing:DescribeTargetGroups": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"elasticloadbalancing:describeInstanceHealth": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeListenerCertificates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeListeners": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeLoadBalancerAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeLoadBalancerPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeLoadBalancerPolicyTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeLoadBalancers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeRules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeSSLPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeTargetGroupAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeTargetGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeTargetHealth": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticmapreduce:Describe*": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"elasticmapreduce:ListBootstrapActions": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"elasticmapreduce:ListClusters": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"elasticmapreduce:ListInstanceGroups": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}},"AROAIH747R37LKSEOZ2MA": {"Resource": {"*": {"policies": {"ANPAJSVXG6QHPE6VHDZ4Q": {"condition": null}}}}}}}},"elasticmapreduce:ListInstances": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"elasticmapreduce:ListSteps": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"elasticmapreduce:ModifyInstanceGroups": {"roles": {"Allow": {"AROAIH747R37LKSEOZ2MA": {"Resource": {"*": {"policies": {"ANPAJSVXG6QHPE6VHDZ4Q": {"condition": null}}}}}}}},"elasticmapreduce:describeCluster": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticmapreduce:describeSecurityConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticmapreduce:describeStep": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticmapreduce:listBootstrapActions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticmapreduce:listClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticmapreduce:listInstanceGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticmapreduce:listInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticmapreduce:listSecurityConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticmapreduce:listSteps": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elastictranscoder:listJobsByPipeline": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elastictranscoder:listJobsByStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elastictranscoder:listPipelines": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elastictranscoder:listPresets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elastictranscoder:readPipeline": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elastictranscoder:readPreset": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"es:describeElasticsearchDomain": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"es:describeElasticsearchDomainConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"es:describeElasticsearchDomains": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"es:listDomainNames": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"es:listTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"events:describeApiDestination": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"events:describeEventBus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"events:describeEventSource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"events:describePartnerEventSource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"events:describeRule": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"events:listApiDestinations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"events:listConnections": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"events:listEventBuses": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"events:listEventSources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"events:listPartnerEventSourceAccounts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"events:listPartnerEventSources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"events:listRuleNamesByTarget": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"events:listRules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"events:listTargetsByRule": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"events:testEventPattern": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"firehose:describeDeliveryStream": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"firehose:listDeliveryStreams": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fms:getAdminAccount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fms:getComplianceDetail": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fms:getNotificationChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fms:getPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fms:getProtectionStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fms:listComplianceStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fms:listMemberAccounts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fms:listPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:describeDataset": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:describeDatasetGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:describeDatasetImportJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:describeForecast": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:describeForecastExportJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:describePredictor": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:getAccuracyMetrics": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:listDatasetGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:listDatasetImportJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:listDatasets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:listForecastExportJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:listForecasts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:listPredictors": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fsx:describeBackups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fsx:describeDataRepositoryTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fsx:describeFileSystems": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fsx:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glacier:describeJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glacier:describeVault": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glacier:getDataRetrievalPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glacier:getVaultAccessPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glacier:getVaultLock": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glacier:getVaultNotifications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glacier:listJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glacier:listTagsForVault": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glacier:listVaults": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"globalaccelerator:describeAccelerator": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"globalaccelerator:describeAcceleratorAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"globalaccelerator:describeEndpointGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"globalaccelerator:describeListener": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"globalaccelerator:listAccelerators": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"globalaccelerator:listEndpointGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"globalaccelerator:listListeners": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:BatchCreatePartition": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:BatchDeletePartition": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:BatchGetPartition": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:CreateDatabase": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:CreatePartition": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:CreateTable": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:CreateUserDefinedFunction": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:DeleteDatabase": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:DeletePartition": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:DeleteTable": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:DeleteUserDefinedFunction": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:GetDatabase": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:GetDatabases": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:GetPartition": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:GetPartitions": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:GetTable": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:GetTableVersions": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:GetTables": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:GetUserDefinedFunction": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:GetUserDefinedFunctions": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:UpdateDatabase": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:UpdatePartition": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:UpdateTable": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:UpdateUserDefinedFunction": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:batchGetPartition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:checkSchemaVersionValidity": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getCatalogImportStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getClassifier": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getClassifiers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getCrawler": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getCrawlerMetrics": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getCrawlers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getDatabase": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getDatabases": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getDataflowGraph": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getDevEndpoint": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getDevEndpoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getJobRun": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getJobRuns": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getMapping": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getPartition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getPartitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getRegistry": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getSchema": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getSchemaByDefinition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getSchemaVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getSchemaVersionsDiff": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getTable": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getTableVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getTables": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getTrigger": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getTriggers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getUserDefinedFunction": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getUserDefinedFunctions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:listRegistries": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:listSchemaVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:listSchemas": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:querySchemaVersionMetadata": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getConnectivityInfo": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getCoreDefinition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getCoreDefinitionVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getDeploymentStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getDeviceDefinition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getDeviceDefinitionVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getFunctionDefinition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getFunctionDefinitionVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getGroupCertificateAuthority": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getGroupVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getLoggerDefinition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getLoggerDefinitionVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getResourceDefinitionVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getServiceRoleForAccount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getSubscriptionDefinition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getSubscriptionDefinitionVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listCoreDefinitionVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listCoreDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listDeployments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listDeviceDefinitionVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listDeviceDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listFunctionDefinitionVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listFunctionDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listGroupVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listLoggerDefinitionVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listLoggerDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listResourceDefinitionVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listResourceDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listSubscriptionDefinitionVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listSubscriptionDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:getDetector": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:getFindings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:getFindingsStatistics": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:getIPSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:getInvitationsCount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:getMasterAccount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:getMembers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:getThreatIntelSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:listDetectors": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:listFindings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:listIPSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:listInvitations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:listMembers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:listThreatIntelSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"health:describeAffectedAccountsForOrganization": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"health:describeAffectedEntities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"health:describeAffectedEntitiesForOrganization": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"health:describeEntityAggregates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"health:describeEventAggregates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"health:describeEventDetails": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"health:describeEventDetailsForOrganization": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"health:describeEventTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"health:describeEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"health:describeEventsForOrganization": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"health:describeHealthServiceStatusForOrganization": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:CreateServiceLinkedRole": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"arn:aws:iam::*:role/aws-service-role/spot.amazonaws.com/AWSServiceRoleForEC2Spot*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": {"StringLike": {"iam:AWSServiceName": "spot.amazonaws.com"}}}}}}}}}},"iam:DeleteRole": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"arn:aws:iam::*:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:GenerateCredentialReport": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}},"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}}}}},"iam:GetAccountPasswordPolicy": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"iam:GetAccountSummary": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"iam:GetCredentialReport": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}},"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}}}}},"iam:GetRole": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"iam:GetRolePolicy": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"iam:GetServerCertificate": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"iam:ListInstanceProfiles": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"iam:ListRolePolicies": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"iam:ListRoles": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"iam:ListServerCertificates": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"iam:PassRole": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"iam:getAccessKeyLastUsed": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getAccountAuthorizationDetails": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getAccountPasswordPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getAccountSummary": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getContextKeysForCustomPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getContextKeysForPrincipalPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getCredentialReport": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getGroupPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getInstanceProfile": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getLoginProfile": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getOpenIDConnectProvider": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getPolicyVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getRole": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getRolePolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getSAMLProvider": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getSSHPublicKey": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getServerCertificate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getUser": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getUserPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listAccessKeys": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listAccountAliases": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listAttachedGroupPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listAttachedRolePolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listAttachedUserPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listEntitiesForPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listGroupPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listGroupsForUser": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listInstanceProfiles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listInstanceProfilesForRole": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listMFADevices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listOpenIDConnectProviders": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listPolicyVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listRolePolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listRoles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listSAMLProviders": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listSSHPublicKeys": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listServerCertificates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listSigningCertificates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listUserPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listUsers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listVirtualMFADevices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:simulateCustomPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:simulatePrincipalPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:getComponent": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:getComponentPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:getContainerRecipe": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:getDistributionConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:getImage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:getImagePipeline": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:getImagePolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:getImageRecipe": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:getImageRecipePolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:getInfrastructureConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:listComponentBuildVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:listComponents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:listContainerRecipes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:listDistributionConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:listImageBuildVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:listImagePipelineImages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:listImagePipelines": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:listImageRecipes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:listImages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:listInfrastructureConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"importexport:getStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"importexport:listJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:describeAssessmentRuns": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:describeAssessmentTargets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:describeAssessmentTemplates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:describeCrossAccountAccessRole": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:describeResourceGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:describeRulesPackages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:getTelemetryMetadata": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:listAssessmentRunAgents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:listAssessmentRuns": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:listAssessmentTargets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:listAssessmentTemplates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:listEventSubscriptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:listRulesPackages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:describeAuthorizer": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:describeCACertificate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:describeCertificate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:describeDefaultAuthorizer": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:describeEndpoint": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:describeIndex": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:describeJobExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:describeThing": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:describeThingGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:describeTunnel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:getEffectivePolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:getIndexingConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:getLoggingOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:getPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:getPolicyVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:getTopicRule": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:getV2LoggingOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listAttachedPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listAuthorizers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listCACertificates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listCertificates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listCertificatesByCA": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listJobExecutionsForJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listJobExecutionsForThing": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listOutgoingCertificates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listPolicyPrincipals": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listPolicyVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listPrincipalPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listPrincipalThings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listRoleAliases": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listTargetsForPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listThingGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listThingGroupsForThing": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listThingPrincipals": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listThingRegistrationTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listThingTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listThings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listTopicRules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listTunnels": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listV2LoggingLevels": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotevents:describeDetector": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotevents:describeDetectorModel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotevents:describeInput": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotevents:describeLoggingOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotevents:listDetectorModelVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotevents:listDetectorModels": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotevents:listDetectors": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotevents:listInputs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:describeAccessPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:describeAsset": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:describeAssetModel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:describeAssetProperty": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:describeDashboard": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:describeGateway": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:describeGatewayCapabilityConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:describeLoggingOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:describePortal": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:describeProject": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:listAccessPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:listAssetModels": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:listAssets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:listAssociatedAssets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:listDashboards": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:listGateways": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:listPortals": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:listProjectAssets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:listProjects": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotwireless:getDestination": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotwireless:getDeviceProfile": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotwireless:getPartnerAccount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotwireless:getServiceEndpoint": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotwireless:getServiceProfile": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotwireless:getWirelessDevice": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotwireless:getWirelessDeviceStatistics": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotwireless:getWirelessGateway": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotwireless:getWirelessGatewayCertificate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotwireless:getWirelessGatewayFirmwareInformation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotwireless:getWirelessGatewayStatistics": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotwireless:getWirelessGatewayTask": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotwireless:getWirelessGatewayTaskDefinition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotwireless:listDestinations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotwireless:listDeviceProfiles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotwireless:listPartnerAccounts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotwireless:listServiceProfiles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotwireless:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotwireless:listWirelessDevices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotwireless:listWirelessGatewayTaskDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotwireless:listWirelessGateways": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kafka:describeCluster": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kafka:getBootstrapBrokers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kafka:listClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kafka:listNodes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kendra:describeDataSource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kendra:describeFaq": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kendra:describeIndex": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kendra:listDataSources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kendra:listFaqs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kendra:listIndices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kinesis:CreateStream": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"kinesis:DeleteStream": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"kinesis:DescribeLimits": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"kinesis:DescribeStream": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"kinesis:GetRecords": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"kinesis:GetShardIterator": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"kinesis:MergeShards": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"kinesis:PutRecord": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"kinesis:SplitShard": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"kinesis:describeStream": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kinesis:listStreams": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kinesis:listTagsForStream": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kinesisanalytics:describeApplication": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kinesisanalytics:describeApplicationSnapshot": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kinesisanalytics:listApplicationSnapshots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kinesisanalytics:listApplications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kms:DescribeKey": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"kms:GetKeyPolicy": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"kms:ListGrants": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"kms:ListKeyPolicies": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"kms:ListKeys": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"kms:describeKey": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kms:getKeyPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kms:getKeyRotationStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kms:listAliases": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kms:listGrants": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kms:listKeyPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kms:listKeys": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kms:listResourceTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kms:listRetirableGrants": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:GetLayerVersionPolicy": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"lambda:GetPolicy": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"lambda:ListAliases": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"lambda:ListFunctions": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"lambda:ListLayerVersions": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"lambda:ListLayers": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"lambda:ListVersionsByFunction": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"lambda:getAccountSettings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getAlias": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getCodeSigningConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getEventSourceMapping": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getFunction": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getFunctionCodeSigningConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getFunctionConcurrency": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getFunctionConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getFunctionEventInvokeConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getLayerVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getLayerVersionPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getProvisionedConcurrencyConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:listAliases": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:listCodeSigningConfigs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:listEventSourceMappings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:listFunctionEventInvokeConfigs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:listFunctions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:listFunctionsByCodeSigningConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:listLayerVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:listLayers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:listProvisionedConcurrencyConfigs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:listVersionsByFunction": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"launchwizard:describeProvisionedApp": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"launchwizard:describeProvisioningEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"launchwizard:listProvisionedApps": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getBot": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getBotAlias": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getBotAliases": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getBotChannelAssociation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getBotChannelAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getBotVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getBots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getBuiltinIntent": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getBuiltinIntents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getBuiltinSlotTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getIntent": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getIntentVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getIntents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getSlotType": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getSlotTypeVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getSlotTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"license-manager:getLicenseConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"license-manager:getServiceSettings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"license-manager:listAssociationsForLicenseConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"license-manager:listFailuresForLicenseConfigurationOperations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"license-manager:listLicenseConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"license-manager:listLicenseSpecificationsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"license-manager:listResourceInventory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"license-manager:listUsageForLicenseConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getActiveNames": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getAlarms": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getAutoSnapshots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getBlueprints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getBundles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getCertificates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getContainerImages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getContainerServiceDeployments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getContainerServices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getDisk": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getDiskSnapshot": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getDiskSnapshots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getDisks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getDistributions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getDomain": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getDomains": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getExportSnapshotRecords": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getInstance": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getInstanceMetricData": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getInstancePortStates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getInstanceSnapshot": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getInstanceSnapshots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getInstanceState": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getKeyPair": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getKeyPairs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getLoadBalancer": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getLoadBalancerTlsCertificates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getLoadBalancers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getOperation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getOperations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getOperationsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getRegions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getRelationalDatabase": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getRelationalDatabaseSnapshot": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getRelationalDatabaseSnapshots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getRelationalDatabases": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getStaticIp": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getStaticIps": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"logs:CreateLogGroup": {"roles": {"Allow": {"AROAJY5MNJYDKGD2UIATQ": {"Resource": {"arn:aws:logs:eu-west-1:430150006394:*": {"policies": {"ANPAIDFYJXP7KKG7FLVWO": {"condition": null}}}}}}}},"logs:CreateLogStream": {"roles": {"Allow": {"AROAJY5MNJYDKGD2UIATQ": {"Resource": {"arn:aws:logs:eu-west-1:430150006394:log-group:/aws/lambda/load-wikipedia:*": {"policies": {"ANPAIDFYJXP7KKG7FLVWO": {"condition": null}}}}}}}},"logs:DescribeMetricFilters": {"roles": {"Allow": {"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}}}}},"logs:PutLogEvents": {"roles": {"Allow": {"AROAJY5MNJYDKGD2UIATQ": {"Resource": {"arn:aws:logs:eu-west-1:430150006394:log-group:/aws/lambda/load-wikipedia:*": {"policies": {"ANPAIDFYJXP7KKG7FLVWO": {"condition": null}}}}}}}},"logs:describeDestinations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"logs:describeExportTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"logs:describeLogGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"logs:describeLogStreams": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"logs:describeMetricFilters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"logs:describeQueries": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"logs:describeSubscriptionFilters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"logs:testMetricFilter": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lookoutmetrics:describeAlert": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lookoutmetrics:describeAnomalyDetectionExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lookoutmetrics:describeAnomalyDetector": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lookoutmetrics:describeMetricSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lookoutmetrics:getAnomalyGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lookoutmetrics:getDataQualityMetrics": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lookoutmetrics:getFeedback": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lookoutmetrics:getSampleData": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lookoutmetrics:listAlerts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lookoutmetrics:listAnomalyDetectors": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lookoutmetrics:listAnomalyGroupSummaries": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lookoutmetrics:listAnomalyGroupTimeSeries": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lookoutmetrics:listMetricSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lookoutmetrics:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"machinelearning:describeBatchPredictions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"machinelearning:describeDataSources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"machinelearning:describeEvaluations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"machinelearning:describeMLModels": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"machinelearning:getBatchPrediction": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"machinelearning:getDataSource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"machinelearning:getEvaluation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"machinelearning:getMLModel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"managedblockchain:getMember": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"managedblockchain:getNetwork": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"managedblockchain:getNode": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"managedblockchain:listMembers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"managedblockchain:listNetworks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"managedblockchain:listNodes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediaconnect:describeFlow": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediaconnect:listEntitlements": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediaconnect:listFlows": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediaconvert:describeEndpoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediaconvert:getJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediaconvert:getJobTemplate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediaconvert:getPreset": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediaconvert:getQueue": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediaconvert:listJobTemplates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediaconvert:listJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:describeChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:describeInput": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:describeInputDevice": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:describeInputSecurityGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:describeMultiplex": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:describeOffering": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:describeReservation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:describeSchedule": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:listChannels": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:listInputDevices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:listInputSecurityGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:listInputs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:listMultiplexes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:listOfferings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:listReservations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediapackage:describeChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediapackage:describeOriginEndpoint": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediapackage:listChannels": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediapackage:listOriginEndpoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediastore:describeContainer": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediastore:describeObject": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediastore:getContainerPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediastore:getCorsPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediastore:listContainers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediastore:listItems": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediatailor:getPlaybackConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediatailor:listPlaybackConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mgn:describeJobLogItems": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mgn:describeJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mgn:describeReplicationConfigurationTemplates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mgn:describeSourceServers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mgn:getLaunchConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mgn:getReplicationConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getAdmChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getApnsChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getApnsSandboxChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getApnsVoipChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getApnsVoipSandboxChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getApp": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getApplicationSettings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getApps": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getBaiduChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getCampaign": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getCampaignActivities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getCampaignVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getCampaignVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getCampaigns": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getEmailChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getEndpoint": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getEventStream": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getExportJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getExportJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getGcmChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getImportJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getImportJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getSegment": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getSegmentImportJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getSegmentVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getSegmentVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getSegments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getSmsChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mq:describeBroker": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mq:describeConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mq:describeConfigurationRevision": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mq:describeUser": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mq:listBrokers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mq:listConfigurationRevisions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mq:listConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mq:listUsers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"network-firewall:describeFirewall": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"network-firewall:describeFirewallPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"network-firewall:describeLoggingConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"network-firewall:describeRuleGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"network-firewall:listFirewallPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"network-firewall:listFirewalls": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"network-firewall:listRuleGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"networkmanager:describeGlobalNetworks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"networkmanager:getCustomerGatewayAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"networkmanager:getDevices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"networkmanager:getLinkAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"networkmanager:getLinks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"networkmanager:getSites": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"networkmanager:getTransitGatewayRegistrations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks-cm:describeAccountAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks-cm:describeBackups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks-cm:describeEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks-cm:describeNodeAssociationStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks-cm:describeServers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeAgentVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeApps": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeCommands": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeDeployments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeEcsClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeElasticIps": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeElasticLoadBalancers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeLayers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeLoadBasedAutoScaling": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeMyUserProfile": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describePermissions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeRaidArrays": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeRdsDbInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeServiceErrors": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeStackProvisioningParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeStackSummary": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeStacks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeTimeBasedAutoScaling": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeUserProfiles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeVolumes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:getHostnameSuggestion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"organizations:DescribeAccount": {"roles": {"Allow": {"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}},"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"organizations:DescribeOrganization": {"roles": {"Allow": {"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}},"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"organizations:DescribeOrganizationalUnit": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"organizations:ListAWSServiceAccessForOrganization": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"organizations:ListAccounts": {"roles": {"Allow": {"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}},"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"organizations:ListAccountsForParent": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"organizations:ListChildren": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"organizations:ListDelegatedAdministrators": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"organizations:ListOrganizationalUnitsForParent": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"organizations:ListParents": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"organizations:ListRoots": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"organizations:listAccounts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"organizations:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"outposts:getOutpost": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"outposts:getOutpostInstanceTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"outposts:listOutposts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"outposts:listSites": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeAlgorithm": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeCampaign": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeDataset": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeDatasetGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeDatasetImportJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeEventTracker": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeFeatureTransformation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeRecipe": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeSchema": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeSolution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeSolutionVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:listCampaigns": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:listDatasetGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:listDatasetImportJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:listDatasets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:listEventTrackers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:listRecipes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:listSchemas": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:listSolutionVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:listSolutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"polly:describeVoices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"polly:getLexicon": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"polly:listLexicons": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"pricing:describeServices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"pricing:getAttributeValues": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"pricing:getProducts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:describeDashboard": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:describeDashboardPermissions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:describeGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:describeIAMPolicyAssignment": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:describeTemplate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:describeTemplateAlias": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:describeTemplatePermissions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:describeUser": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:listDashboards": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:listGroupMemberships": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:listGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:listIAMPolicyAssignments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:listIAMPolicyAssignmentsForUser": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:listTemplateAliases": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:listTemplateVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:listTemplates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:listUserGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:listUsers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ram:getPermission": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ram:getResourceShareAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ram:getResourceShareInvitations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ram:getResourceShares": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ram:listPendingInvitationResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ram:listPrincipals": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ram:listResourceSharePermissions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ram:listResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:Describe*": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"rds:DescribeAccountAttributes": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeDBClusters": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeDBEngineVersions": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeDBInstances": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeDBParameterGroups": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeDBParameters": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeDBSecurityGroups": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeDBSnapshots": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeDBSubnetGroups": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeEngineDefaultParameters": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeEvents": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeOptionGroupOptions": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeOptionGroups": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeOrderableDBInstanceOptions": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeReservedDBInstances": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeReservedDBInstancesOfferings": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:ListTagsForResource": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:describeAccountAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeCertificates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBClusterParameterGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBClusterParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBClusterSnapshots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBEngineVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBParameterGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBSecurityGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBSnapshotAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBSnapshots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBSubnetGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeEngineDefaultClusterParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeEngineDefaultParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeEventCategories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeEventSubscriptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeExportTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeOptionGroupOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeOptionGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeOrderableDBInstanceOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describePendingMaintenanceActions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeReservedDBInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeReservedDBInstancesOfferings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift-data:describeStatement": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift-data:listStatements": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:DescribeClusters": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"redshift:DescribeReservedNodeOfferings": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"redshift:DescribeReservedNodes": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"redshift:describeClusterParameterGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeClusterParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeClusterSecurityGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeClusterSnapshots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeClusterSubnetGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeClusterVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeDefaultClusterParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeEventCategories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeEventSubscriptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeHsmClientCertificates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeHsmConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeLoggingStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeOrderableClusterOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeReservedNodeOfferings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeReservedNodes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeResize": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeSnapshotCopyGrants": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeStorage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeTableRestoreStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rekognition:listCollections": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rekognition:listFaces": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"resource-groups:getGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"resource-groups:getGroupQuery": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"resource-groups:getTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"resource-groups:listGroupResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"resource-groups:listGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"resource-groups:searchResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:batchDescribeSimulationJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:describeDeploymentJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:describeFleet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:describeRobot": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:describeRobotApplication": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:describeSimulationApplication": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:describeSimulationJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:listDeploymentJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:listFleets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:listRobotApplications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:listRobots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:listSimulationApplications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:listSimulationJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53-recovery-readiness:getCell": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53-recovery-readiness:getCellReadinessSummary": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53-recovery-readiness:getReadinessCheck": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53-recovery-readiness:getReadinessCheckResourceStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53-recovery-readiness:getReadinessCheckStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53-recovery-readiness:getRecoveryGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53-recovery-readiness:getRecoveryGroupReadinessSummary": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53-recovery-readiness:listCells": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53-recovery-readiness:listReadinessChecks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53-recovery-readiness:listRecoveryGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53-recovery-readiness:listResourceSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:GetAccountLimit": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"route53:GetHealthCheck": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"route53:GetHostedZone": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"route53:ListHealthChecks": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"route53:ListHostedZones": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"route53:ListHostedZonesByName": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"route53:ListResourceRecordSets": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"route53:getChange": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getCheckerIpRanges": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getGeoLocation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getHealthCheck": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getHealthCheckCount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getHealthCheckLastFailureReason": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getHealthCheckStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getHostedZone": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getHostedZoneCount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getReusableDelegationSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getTrafficPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getTrafficPolicyInstance": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getTrafficPolicyInstanceCount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listGeoLocations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listHealthChecks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listHostedZones": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listHostedZonesByName": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listResourceRecordSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listReusableDelegationSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listTagsForResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listTrafficPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listTrafficPolicyInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listTrafficPolicyInstancesByHostedZone": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listTrafficPolicyInstancesByPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listTrafficPolicyVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53domains:checkDomainAvailability": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53domains:getContactReachabilityStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53domains:getDomainDetail": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53domains:getOperationDetail": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53domains:listDomains": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53domains:listOperations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53domains:listTagsForDomain": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53domains:viewBilling": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:getFirewallConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:getFirewallDomainList": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:getFirewallRuleGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:getFirewallRuleGroupAssociation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:getResolverDnssecConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:getResolverRulePolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:listFirewallConfigs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:listFirewallDomainLists": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:listFirewallDomains": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:listFirewallRuleGroupAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:listFirewallRuleGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:listFirewallRules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:listResolverDnssecConfigs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:listResolverEndpointIpAddresses": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:listResolverEndpoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:listResolverRuleAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:listResolverRules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:*": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"s3:CreateBucket": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"s3:DescribeMultiRegionAccessPointOperation": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"s3:Get*": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"s3:GetAccessPoint": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"s3:GetAccessPointPolicy": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"s3:GetAccessPointPolicyStatus": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"s3:GetAccountPublicAccessBlock": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}},"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"s3:GetBucketAcl": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}},"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"s3:GetBucketLocation": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}},"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"s3:GetBucketLogging": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"s3:GetBucketPolicy": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}},"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"s3:GetBucketPolicyStatus": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}},"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"s3:GetBucketPublicAccessBlock": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}},"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"s3:GetBucketVersioning": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"s3:GetMultiRegionAccessPoint": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"s3:GetMultiRegionAccessPointPolicy": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"s3:GetMultiRegionAccessPointPolicyStatus": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"s3:List*": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"s3:ListAccessPoints": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"s3:ListAllMyBuckets": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}},"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"s3:ListBucket": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"s3:ListMultiRegionAccessPoints": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"s3:getAccelerateConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getAccessPointConfigurationForObjectLambda": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getAccessPointForObjectLambda": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getAccessPointPolicyStatusForObjectLambda": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getAnalyticsConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getBucketAcl": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getBucketCORS": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getBucketLocation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getBucketLogging": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getBucketNotification": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getBucketPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getBucketRequestPayment": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getBucketTagging": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getBucketVersioning": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getBucketWebsite": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getEncryptionConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getInventoryConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getLifecycleConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getMetricsConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getReplicationConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:listAccessPointsForObjectLambda": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:listAllMyBuckets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:listBucket": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:listBucketMultipartUploads": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeAction": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeAlgorithm": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeApp": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeArtifact": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeAutoMLJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeCompilationJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeContext": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeDataQualityJobDefinition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeDevice": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeDeviceFleet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeDomain": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeEdgePackagingJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeEndpoint": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeEndpointConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeExperiment": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeFeatureGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeHumanTaskUi": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeHyperParameterTuningJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeImage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeImageVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeLabelingJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeModel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeModelBiasJobDefinition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeModelExplainabilityJobDefinition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeModelPackage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeModelPackageGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeModelQualityJobDefinition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeMonitoringSchedule": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeNotebookInstance": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeNotebookInstanceLifecycleConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describePipeline": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describePipelineDefinitionForExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describePipelineExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeProcessingJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeProject": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeSubscribedWorkteam": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeTrainingJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeTransformJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeTrial": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeTrialComponent": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeUserProfile": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeWorkteam": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listActions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listAlgorithms": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listApps": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listArtifacts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listAutoMLJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listCandidatesForAutoMLJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listCodeRepositories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listCompilationJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listContexts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listDataQualityJobDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listDeviceFleets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listDevices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listDomains": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listEdgePackagingJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listEndpointConfigs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listEndpoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listExperiments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listFeatureGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listFlowDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listHumanTaskUis": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listHyperParameterTuningJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listImageVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listImages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listLabelingJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listLabelingJobsForWorkteam": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listModelBiasJobDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listModelExplainabilityJobDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listModelPackageGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listModelPackages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listModelQualityJobDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listModels": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listMonitoringExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listMonitoringSchedules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listNotebookInstanceLifecycleConfigs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listNotebookInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listPipelineExecutionSteps": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listPipelineExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listPipelineParametersForExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listPipelines": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listProcessingJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listProjects": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listSubscribedWorkteams": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listTrainingJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listTrainingJobsForHyperParameterTuningJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listTransformJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listTrialComponents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listTrials": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listUserProfiles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listWorkteams": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sdb:*": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"sdb:BatchPutAttributes": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"sdb:Select": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"sdb:domainMetadata": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sdb:listDomains": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"secretsmanager:DescribeSecret": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"secretsmanager:GetResourcePolicy": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"secretsmanager:ListSecrets": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"secretsmanager:describeSecret": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"secretsmanager:getResourcePolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"secretsmanager:listSecretVersionIds": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"secretsmanager:listSecrets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"securityhub:getEnabledStandards": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"securityhub:getFindings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"securityhub:getInsightResults": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"securityhub:getInsights": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"securityhub:getMasterAccount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"securityhub:getMembers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"securityhub:listEnabledProductsForImport": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"securityhub:listInvitations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"securityhub:listMembers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:describeConstraint": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:describePortfolio": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:describeProduct": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:describeProductAsAdmin": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:describeProductView": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:describeProvisioningArtifact": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:describeProvisioningParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:describeRecord": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:listAcceptedPortfolioShares": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:listConstraintsForPortfolio": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:listLaunchPaths": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:listPortfolioAccess": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:listPortfolios": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:listPortfoliosForProduct": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:listPrincipalsForPortfolio": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:listProvisioningArtifacts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:listRecordHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:scanProvisionedProducts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:searchProducts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:getAWSDefaultServiceQuota": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:getAssociationForServiceQuotaTemplate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:getRequestedServiceQuotaChange": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:getServiceQuota": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:getServiceQuotaIncreaseRequestFromTemplate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:listAWSDefaultServiceQuotas": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:listRequestedServiceQuotaChangeHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:listRequestedServiceQuotaChangeHistoryByQuota": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:listServiceQuotaIncreaseRequestsInTemplate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:listServiceQuotas": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:listServices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:GetSendQuota": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ses:describeActiveReceiptRuleSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:describeReceiptRule": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:describeReceiptRuleSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getAccount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getBlacklistReports": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getConfigurationSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getConfigurationSetEventDestinations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getDedicatedIp": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getDedicatedIps": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getDeliverabilityDashboardOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getDeliverabilityTestReport": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getDomainDeliverabilityCampaign": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getDomainStatisticsReport": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getEmailIdentity": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getIdentityDkimAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getIdentityMailFromDomainAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getIdentityNotificationAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getIdentityPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getIdentityVerificationAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getSendQuota": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getSendStatistics": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listConfigurationSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listDedicatedIpPools": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listDeliverabilityTestReports": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listDomainDeliverabilityCampaigns": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listEmailIdentities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listIdentities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listIdentityPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listReceiptFilters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listReceiptRuleSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listVerifiedEmailAddresses": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"shield:describeAttack": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"shield:describeProtection": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"shield:describeSubscription": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"shield:listAttacks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"shield:listProtections": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sms-voice:getConfigurationSetEventDestinations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sms:getConnectors": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sms:getReplicationJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sms:getReplicationRuns": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sms:getServers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"snowball:describeAddress": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"snowball:describeAddresses": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"snowball:describeJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"snowball:getSnowballUsage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"snowball:listJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:*": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"sns:GetTopicAttributes": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"sns:ListSubscriptionsByTopic": {"roles": {"Allow": {"AROAWIJXQGZ5HSCDUOZE5": {"Resource": {"*": {"policies": {"ANPAJQPCESDDYDLLSOGYO": {"condition": null}}}}}}}},"sns:ListTopics": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"sns:checkIfPhoneNumberIsOptedOut": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:getEndpointAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:getPlatformApplicationAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:getSMSAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:getSubscriptionAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:getTopicAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:listEndpointsByPlatformApplication": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:listPhoneNumbersOptedOut": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:listPlatformApplications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:listSubscriptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:listSubscriptionsByTopic": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:listTopics": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sqs:*": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"sqs:CreateQueue": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"sqs:Delete*": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"sqs:GetQueue*": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"sqs:GetQueueAttributes": {"roles": {"Allow": {"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"sqs:ListQueues": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}},"AROAWIJXQGZ5OSPI4PBJL": {"Resource": {"*": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}}}}}},"sqs:PurgeQueue": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"sqs:ReceiveMessage": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"sqs:getQueueAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sqs:getQueueUrl": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sqs:listDeadLetterSourceQueues": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sqs:listQueues": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm-contacts:describeEngagement": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm-contacts:describePage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm-contacts:getContact": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm-contacts:getContactChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm-contacts:listContactChannels": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm-contacts:listContacts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm-contacts:listEngagements": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm-contacts:listPageReceipts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm-contacts:listPagesByContact": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm-contacts:listPagesByEngagement": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm-incidents:getIncidentRecord": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm-incidents:getReplicationSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm-incidents:getResponsePlan": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm-incidents:listIncidentRecords": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm-incidents:listReplicationSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm-incidents:listResponsePlans": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm-incidents:listTimelineEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeActivations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeAssociation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeAssociationExecutionTargets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeAssociationExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeAutomationExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeAutomationStepExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeAvailablePatches": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeDocument": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeDocumentPermission": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeEffectiveInstanceAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeEffectivePatchesForPatchBaseline": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeInstanceAssociationsStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeInstanceInformation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeInstancePatchStates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeInstancePatchStatesForPatchGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeInstancePatches": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeInventoryDeletions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeMaintenanceWindowExecutionTaskInvocations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeMaintenanceWindowExecutionTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeMaintenanceWindowExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeMaintenanceWindowSchedule": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeMaintenanceWindowTargets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeMaintenanceWindowTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeMaintenanceWindows": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeMaintenanceWindowsForTarget": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeOpsItems": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describePatchBaselines": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describePatchGroupState": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describePatchGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describePatchProperties": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeSessions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getAutomationExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getCommandInvocation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getConnectionStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getDefaultPatchBaseline": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getDeployablePatchSnapshotForInstance": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getInventorySchema": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getMaintenanceWindow": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getMaintenanceWindowExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getMaintenanceWindowExecutionTask": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getMaintenanceWindowExecutionTaskInvocation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getMaintenanceWindowTask": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getOpsItem": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getPatchBaseline": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getPatchBaselineForPatchGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getServiceSetting": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:labelParameterVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listAssociationVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listCommandInvocations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listCommands": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listComplianceItems": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listComplianceSummaries": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listDocumentVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listDocuments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listOpsItemEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listResourceComplianceSummaries": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listResourceDataSync": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"states:describeActivity": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"states:describeExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"states:describeStateMachine": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"states:describeStateMachineForExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"states:getExecutionHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"states:listActivities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"states:listExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"states:listStateMachines": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeBandwidthRateLimit": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeCache": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeCachediSCSIVolumes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeFileSystemAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeGatewayInformation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeMaintenanceStartTime": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeNFSFileShares": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeSMBFileShares": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeSMBSettings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeSnapshotSchedule": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeStorediSCSIVolumes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeTapeArchives": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeTapeRecoveryPoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeTapes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeUploadBuffer": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeVTLDevices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeWorkingStorage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:listFileShares": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:listFileSystemAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:listGateways": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:listLocalDisks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:listTapes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:listVolumeInitiators": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:listVolumeRecoveryPoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:listVolumes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:countClosedWorkflowExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:countOpenWorkflowExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:countPendingActivityTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:countPendingDecisionTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:describeActivityType": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:describeDomain": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:describeWorkflowExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:describeWorkflowType": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:getWorkflowExecutionHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:listActivityTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:listClosedWorkflowExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:listDomains": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:listOpenWorkflowExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:listWorkflowTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"synthetics:describeCanaries": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"synthetics:describeCanariesLastRun": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"synthetics:describeRuntimeVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"synthetics:getCanary": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"synthetics:getCanaryRuns": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"transfer:describeServer": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"transfer:describeUser": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"transfer:listServers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"transfer:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"transfer:listUsers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:getByteMatchSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:getChangeTokenStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:getIPSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:getRule": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:getSqlInjectionMatchSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:getWebACL": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:getWebACLForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:listByteMatchSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:listIPSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:listResourcesForWebACL": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:listRules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:listSqlInjectionMatchSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:listWebACLs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:getByteMatchSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:getChangeTokenStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:getIPSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:getRule": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:getSampledRequests": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:getSizeConstraintSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:getSqlInjectionMatchSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:getWebACL": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:getXssMatchSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:listByteMatchSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:listIPSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:listRules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:listSizeConstraintSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:listSqlInjectionMatchSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:listWebACLs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:listXssMatchSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:checkCapacity": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:describeManagedRuleGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:getIPSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:getLoggingConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:getPermissionPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:getRateBasedStatementManagedKeys": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:getRegexPatternSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:getRuleGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:getSampledRequests": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:getWebACL": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:getWebACLForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:listAvailableManagedRuleGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:listIPSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:listLoggingConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:listRegexPatternSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:listResourcesForWebACL": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:listRuleGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:listWebACLs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workdocs:checkAlias": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workdocs:describeAvailableDirectories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workdocs:describeInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:describeAuditStreamConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:describeCompanyNetworkConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:describeDevice": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:describeDevicePolicyConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:describeDomain": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:describeFleetMetadata": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:describeIdentityProviderConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:describeWebsiteCertificateAuthority": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:listDevices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:listDomains": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:listFleets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:listWebsiteAuthorizationProviders": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:listWebsiteCertificateAuthorities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:describeGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:describeOrganization": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:describeResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:describeUser": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:listAliases": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:listGroupMembers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:listGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:listMailboxPermissions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:listOrganizations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:listResourceDelegates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:listResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:listUsers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workspaces:describeAccount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workspaces:describeAccountModifications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workspaces:describeIpGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workspaces:describeTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workspaces:describeWorkspaceBundles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workspaces:describeWorkspaceDirectories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workspaces:describeWorkspaceImages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workspaces:describeWorkspaces": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workspaces:describeWorkspacesConnectionStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}}}},"policies": {"ANPAI4YEZURRMKACW56EA": {"PolicyDocument": {"Statement": [{"Action": ["ec2:DescribeInstances","ec2:DescribeLaunchTemplates","ec2:DescribeSpotInstanceRequests","ec2:DeleteLaunchTemplate","ec2:ModifyInstanceAttribute","ec2:TerminateInstances","ec2:CancelSpotInstanceRequests","ec2:DeleteNetworkInterface","ec2:DescribeInstanceAttribute","ec2:DescribeVolumeStatus","ec2:DescribeVolumes","ec2:DetachVolume","ec2:DeleteVolume","ec2:DescribePlacementGroups","ec2:DeletePlacementGroup"],"Effect": "Allow","Resource": ["*"]}],"Version": "2012-10-17"},"arn": "arn:aws:iam::aws:policy/aws-service-role/AmazonEMRCleanupPolicy","attached_to": {"roles": [{"id": "AROAJ2LRZXYT2USPF2ZTY","name": "AWSServiceRoleForEMRCleanup"}]},"id": "ANPAI4YEZURRMKACW56EA","name": "AmazonEMRCleanupPolicy"},"ANPAIDFYJXP7KKG7FLVWO": {"PolicyDocument": {"Statement": [{"Action": ["logs:CreateLogGroup"],"Effect": "Allow","Resource": ["arn:aws:logs:eu-west-1:430150006394:*"]},{"Action": ["logs:CreateLogStream","logs:PutLogEvents"],"Effect": "Allow","Resource": ["arn:aws:logs:eu-west-1:430150006394:log-group:/aws/lambda/load-wikipedia:*"]}],"Version": "2012-10-17"},"arn": "arn:aws:iam::430150006394:policy/service-role/AWSLambdaBasicExecutionRole-676647ec-377e-496c-8355-37f23bf12c85","attached_to": {"roles": [{"id": "AROAJY5MNJYDKGD2UIATQ","name": "load-wikipedia"}]},"id": "ANPAIDFYJXP7KKG7FLVWO","name": "AWSLambdaBasicExecutionRole-676647ec-377e-496c-8355-37f23bf12c85"},"ANPAIDI2BQT2LKXZG36TW": {"PolicyDocument": {"Statement": [{"Action": ["ec2:AuthorizeSecurityGroupEgress","ec2:AuthorizeSecurityGroupIngress","ec2:CancelSpotInstanceRequests","ec2:CreateFleet","ec2:CreateLaunchTemplate","ec2:CreateNetworkInterface","ec2:CreateSecurityGroup","ec2:CreateTags","ec2:DeleteLaunchTemplate","ec2:DeleteNetworkInterface","ec2:DeleteSecurityGroup","ec2:DeleteTags","ec2:DescribeAvailabilityZones","ec2:DescribeAccountAttributes","ec2:DescribeDhcpOptions","ec2:DescribeImages","ec2:DescribeInstanceStatus","ec2:DescribeInstances","ec2:DescribeKeyPairs","ec2:DescribeLaunchTemplates","ec2:DescribeNetworkAcls","ec2:DescribeNetworkInterfaces","ec2:DescribePrefixLists","ec2:DescribeRouteTables","ec2:DescribeSecurityGroups","ec2:DescribeSpotInstanceRequests","ec2:DescribeSpotPriceHistory","ec2:DescribeSubnets","ec2:DescribeTags","ec2:DescribeVpcAttribute","ec2:DescribeVpcEndpoints","ec2:DescribeVpcEndpointServices","ec2:DescribeVpcs","ec2:DetachNetworkInterface","ec2:ModifyImageAttribute","ec2:ModifyInstanceAttribute","ec2:RequestSpotInstances","ec2:RevokeSecurityGroupEgress","ec2:RunInstances","ec2:TerminateInstances","ec2:DeleteVolume","ec2:DescribeVolumeStatus","ec2:DescribeVolumes","ec2:DetachVolume","iam:GetRole","iam:GetRolePolicy","iam:ListInstanceProfiles","iam:ListRolePolicies","iam:PassRole","s3:CreateBucket","s3:Get*","s3:List*","sdb:BatchPutAttributes","sdb:Select","sqs:CreateQueue","sqs:Delete*","sqs:GetQueue*","sqs:PurgeQueue","sqs:ReceiveMessage","cloudwatch:PutMetricAlarm","cloudwatch:DescribeAlarms","cloudwatch:DeleteAlarms","application-autoscaling:RegisterScalableTarget","application-autoscaling:DeregisterScalableTarget","application-autoscaling:PutScalingPolicy","application-autoscaling:DeleteScalingPolicy","application-autoscaling:Describe*"],"Effect": "Allow","Resource": ["*"]},{"Action": ["iam:CreateServiceLinkedRole"],"Condition": {"StringLike": {"iam:AWSServiceName": "spot.amazonaws.com"}},"Effect": "Allow","Resource": ["arn:aws:iam::*:role/aws-service-role/spot.amazonaws.com/AWSServiceRoleForEC2Spot*"]}],"Version": "2012-10-17"},"arn": "arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceRole","attached_to": {"roles": [{"id": "AROAIXBSWIKGEEDLMO53I","name": "EMR_DefaultRole"}]},"id": "ANPAIDI2BQT2LKXZG36TW","name": "AmazonElasticMapReduceRole"},"ANPAIGALS5RCDLZLB3PGS": {"PolicyDocument": {"Statement": [{"Action": ["cloudwatch:*","dynamodb:*","ec2:Describe*","elasticmapreduce:Describe*","elasticmapreduce:ListBootstrapActions","elasticmapreduce:ListClusters","elasticmapreduce:ListInstanceGroups","elasticmapreduce:ListInstances","elasticmapreduce:ListSteps","kinesis:CreateStream","kinesis:DeleteStream","kinesis:DescribeStream","kinesis:GetRecords","kinesis:GetShardIterator","kinesis:MergeShards","kinesis:PutRecord","kinesis:SplitShard","rds:Describe*","s3:*","sdb:*","sns:*","sqs:*","glue:CreateDatabase","glue:UpdateDatabase","glue:DeleteDatabase","glue:GetDatabase","glue:GetDatabases","glue:CreateTable","glue:UpdateTable","glue:DeleteTable","glue:GetTable","glue:GetTables","glue:GetTableVersions","glue:CreatePartition","glue:BatchCreatePartition","glue:UpdatePartition","glue:DeletePartition","glue:BatchDeletePartition","glue:GetPartition","glue:GetPartitions","glue:BatchGetPartition","glue:CreateUserDefinedFunction","glue:UpdateUserDefinedFunction","glue:DeleteUserDefinedFunction","glue:GetUserDefinedFunction","glue:GetUserDefinedFunctions"],"Effect": "Allow","Resource": ["*"]}],"Version": "2012-10-17"},"arn": "arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceforEC2Role","attached_to": {"roles": [{"id": "AROAI265GPNVMDZAKJPPA","name": "EMR_EC2_DefaultRole"}]},"id": "ANPAIGALS5RCDLZLB3PGS","name": "AmazonElasticMapReduceforEC2Role"},"ANPAJ7W6266ELXF5MISDS": {"PolicyDocument": {"Statement": [{"Action": ["apigateway:GET"],"Effect": "Allow","Resource": ["arn:aws:apigateway:*::/account","arn:aws:apigateway:*::/apis","arn:aws:apigateway:*::/apis/*","arn:aws:apigateway:*::/apis/*/authorizers","arn:aws:apigateway:*::/apis/*/authorizers/*","arn:aws:apigateway:*::/apis/*/deployments","arn:aws:apigateway:*::/apis/*/deployments/*","arn:aws:apigateway:*::/apis/*/integrations","arn:aws:apigateway:*::/apis/*/integrations/*","arn:aws:apigateway:*::/apis/*/integrations/*/integrationresponses","arn:aws:apigateway:*::/apis/*/integrations/*/integrationresponses/*","arn:aws:apigateway:*::/apis/*/models","arn:aws:apigateway:*::/apis/*/models/*","arn:aws:apigateway:*::/apis/*/routes","arn:aws:apigateway:*::/apis/*/routes/*","arn:aws:apigateway:*::/apis/*/routes/*/routeresponses","arn:aws:apigateway:*::/apis/*/routes/*/routeresponses/*","arn:aws:apigateway:*::/apis/*/stages","arn:aws:apigateway:*::/apis/*/stages/*","arn:aws:apigateway:*::/clientcertificates","arn:aws:apigateway:*::/clientcertificates/*","arn:aws:apigateway:*::/domainnames","arn:aws:apigateway:*::/domainnames/*","arn:aws:apigateway:*::/domainnames/*/apimappings","arn:aws:apigateway:*::/domainnames/*/apimappings/*","arn:aws:apigateway:*::/domainnames/*/basepathmappings","arn:aws:apigateway:*::/domainnames/*/basepathmappings/*","arn:aws:apigateway:*::/restapis","arn:aws:apigateway:*::/restapis/*","arn:aws:apigateway:*::/restapis/*/authorizers","arn:aws:apigateway:*::/restapis/*/authorizers/*","arn:aws:apigateway:*::/restapis/*/deployments","arn:aws:apigateway:*::/restapis/*/deployments/*","arn:aws:apigateway:*::/restapis/*/models","arn:aws:apigateway:*::/restapis/*/models/*","arn:aws:apigateway:*::/restapis/*/models/*/default_template","arn:aws:apigateway:*::/restapis/*/resources","arn:aws:apigateway:*::/restapis/*/resources/*","arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/integration/responses/*","arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/responses/*","arn:aws:apigateway:*::/restapis/*/stages/*/sdks/*","arn:aws:apigateway:*::/restapis/*/resources/*/methods/*","arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/integration","arn:aws:apigateway:*::/restapis/*/stages","arn:aws:apigateway:*::/restapis/*/stages/*"]},{"Action": ["iam:DeleteRole"],"Effect": "Allow","Resource": ["arn:aws:iam::*:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport"]},{"Action": ["a4b:getDevice","a4b:getProfile","a4b:getRoom","a4b:getRoomSkillParameter","a4b:getSkillGroup","a4b:searchDevices","a4b:searchProfiles","a4b:searchRooms","a4b:searchSkillGroups","access-analyzer:getFinding","access-analyzer:listAnalyzers","access-analyzer:listArchiveRules","access-analyzer:listFindings","acm-pca:describeCertificateAuthority","acm-pca:describeCertificateAuthorityAuditReport","acm-pca:getCertificate","acm-pca:getCertificateAuthorityCertificate","acm-pca:getCertificateAuthorityCsr","acm-pca:listCertificateAuthorities","acm-pca:listTags","acm:describeCertificate","acm:getCertificate","acm:listCertificates","acm:listTagsForCertificate","airflow:getEnvironment","airflow:listEnvironments","airflow:listTagsForResource","amplify:getApp","amplify:getBranch","amplify:getDomainAssociation","amplify:getJob","amplify:getWebhook","amplify:listApps","amplify:listWebhooks","appflow:describeConnectorEntity","appflow:describeConnectorProfiles","appflow:describeFlow","appflow:listFlows","application-autoscaling:describeScalableTargets","application-autoscaling:describeScalingActivities","application-autoscaling:describeScalingPolicies","application-autoscaling:describeScheduledActions","applicationinsights:describeComponentConfiguration","applicationinsights:describeComponentConfigurationRecommendation","applicationinsights:listApplications","applicationinsights:listComponents","applicationinsights:listConfigurationHistory","applicationinsights:listLogPatterns","applicationinsights:listLogPatternSets","appmesh:describeGatewayRoute","appmesh:describeMesh","appmesh:describeRoute","appmesh:describeVirtualGateway","appmesh:describeVirtualNode","appmesh:describeVirtualRouter","appmesh:describeVirtualService","appmesh:listGatewayRoutes","appmesh:listMeshes","appmesh:listRoutes","appmesh:listTagsForResource","appmesh:listVirtualGateways","appmesh:listVirtualNodes","appmesh:listVirtualRouters","appmesh:listVirtualServices","apprunner:describeAutoScalingConfiguration","apprunner:describeCustomDomains","apprunner:describeOperation","apprunner:describeService","apprunner:listAutoScalingConfigurations","apprunner:listConnections","apprunner:listOperations","apprunner:listServices","apprunner:listTagsForResource","appstream:describeDirectoryConfigs","appstream:describeFleets","appstream:describeImageBuilders","appstream:describeImages","appstream:describeSessions","appstream:describeStacks","appstream:listAssociatedFleets","appstream:listAssociatedStacks","appstream:listTagsForResource","appsync:getFunction","appsync:getGraphqlApi","appsync:getIntrospectionSchema","appsync:getResolver","appsync:getSchemaCreationStatus","appsync:getType","appsync:listDataSources","appsync:listFunctions","appsync:listGraphqlApis","appsync:listResolvers","appsync:listTypes","athena:batchGetNamedQuery","athena:batchGetQueryExecution","athena:getNamedQuery","athena:getQueryExecution","athena:getWorkGroup","athena:listNamedQueries","athena:listQueryExecutions","athena:listTagsForResource","athena:listWorkGroups","auditmanager:getAccountStatus","auditmanager:getDelegations","auditmanager:listAssessmentFrameworks","auditmanager:listAssessmentReports","auditmanager:listAssessments","auditmanager:listControls","auditmanager:listKeywordsForDataSource","auditmanager:listNotifications","autoscaling-plans:describeScalingPlanResources","autoscaling-plans:describeScalingPlans","autoscaling-plans:getScalingPlanResourceForecastData","autoscaling:describeAccountLimits","autoscaling:describeAdjustmentTypes","autoscaling:describeAutoScalingGroups","autoscaling:describeAutoScalingInstances","autoscaling:describeAutoScalingNotificationTypes","autoscaling:describeInstanceRefreshes","autoscaling:describeLaunchConfigurations","autoscaling:describeLifecycleHooks","autoscaling:describeLifecycleHookTypes","autoscaling:describeLoadBalancers","autoscaling:describeLoadBalancerTargetGroups","autoscaling:describeMetricCollectionTypes","autoscaling:describeNotificationConfigurations","autoscaling:describePolicies","autoscaling:describeScalingActivities","autoscaling:describeScalingProcessTypes","autoscaling:describeScheduledActions","autoscaling:describeTags","autoscaling:describeTerminationPolicyTypes","backup:describeBackupJob","backup:describeBackupVault","backup:describeProtectedResource","backup:describeRecoveryPoint","backup:describeRestoreJob","backup:getBackupPlan","backup:getBackupPlanFromJSON","backup:getBackupPlanFromTemplate","backup:getBackupSelection","backup:getBackupVaultAccessPolicy","backup:getBackupVaultNotifications","backup:getRecoveryPointRestoreMetadata","backup:getSupportedResourceTypes","backup:listBackupJobs","backup:listBackupPlans","backup:listBackupPlanTemplates","backup:listBackupPlanVersions","backup:listBackupSelections","backup:listBackupVaults","backup:listProtectedResources","backup:listRecoveryPointsByBackupVault","backup:listRecoveryPointsByResource","backup:listRestoreJobs","backup:listTags","batch:describeComputeEnvironments","batch:describeJobDefinitions","batch:describeJobQueues","batch:describeJobs","batch:listJobs","braket:getDevice","braket:getQuantumTask","braket:searchDevices","braket:searchQuantumTasks","budgets:viewBudget","ce:getCostAndUsage","ce:getCostAndUsageWithResources","ce:getCostForecast","ce:getDimensionValues","ce:getReservationCoverage","ce:getReservationPurchaseRecommendation","ce:getReservationUtilization","ce:getRightsizingRecommendation","ce:getSavingsPlansCoverage","ce:getSavingsPlansPurchaseRecommendation","ce:getSavingsPlansUtilization","ce:getSavingsPlansUtilizationDetails","ce:getTags","cloud9:describeEnvironmentMemberships","cloud9:describeEnvironments","cloud9:listEnvironments","clouddirectory:getDirectory","clouddirectory:listDirectories","cloudformation:describeAccountLimits","cloudformation:describeChangeSet","cloudformation:describeStackEvents","cloudformation:describeStackInstance","cloudformation:describeStackResource","cloudformation:describeStackResources","cloudformation:describeStacks","cloudformation:describeStackSet","cloudformation:describeStackSetOperation","cloudformation:estimateTemplateCost","cloudformation:getStackPolicy","cloudformation:getTemplate","cloudformation:getTemplateSummary","cloudformation:listChangeSets","cloudformation:listExports","cloudformation:listImports","cloudformation:listStackInstances","cloudformation:listStackResources","cloudformation:listStacks","cloudformation:listStackSetOperationResults","cloudformation:listStackSetOperations","cloudformation:listStackSets","cloudfront:getCloudFrontOriginAccessIdentity","cloudfront:getCloudFrontOriginAccessIdentityConfig","cloudfront:getDistribution","cloudfront:getDistributionConfig","cloudfront:getInvalidation","cloudfront:getStreamingDistribution","cloudfront:getStreamingDistributionConfig","cloudfront:listCloudFrontOriginAccessIdentities","cloudfront:listDistributions","cloudfront:listDistributionsByWebACLId","cloudfront:listInvalidations","cloudfront:listStreamingDistributions","cloudhsm:describeBackups","cloudhsm:describeClusters","cloudsearch:describeAnalysisSchemes","cloudsearch:describeAvailabilityOptions","cloudsearch:describeDomains","cloudsearch:describeExpressions","cloudsearch:describeIndexFields","cloudsearch:describeScalingParameters","cloudsearch:describeServiceAccessPolicies","cloudsearch:describeSuggesters","cloudsearch:listDomainNames","cloudtrail:describeTrails","cloudtrail:getEventSelectors","cloudtrail:getInsightSelectors","cloudtrail:getTrail","cloudtrail:getTrailStatus","cloudtrail:listPublicKeys","cloudtrail:listTags","cloudtrail:listTrails","cloudtrail:lookupEvents","cloudwatch:describeAlarmHistory","cloudwatch:describeAlarms","cloudwatch:describeAlarmsForMetric","cloudwatch:describeAnomalyDetectors","cloudwatch:describeInsightRules","cloudwatch:getDashboard","cloudwatch:getInsightRuleReport","cloudwatch:getMetricData","cloudwatch:getMetricStatistics","cloudwatch:listDashboards","cloudwatch:listMetrics","codeartifact:describeDomain","codeartifact:describePackageVersion","codeartifact:describeRepository","codeartifact:getDomainPermissionsPolicy","codeartifact:getRepositoryEndPoint","codeartifact:getRepositoryPermissionsPolicy","codeartifact:listDomains","codeartifact:listPackages","codeartifact:listPackageVersionAssets","codeartifact:listPackageVersions","codeartifact:listRepositories","codeartifact:listRepositoriesInDomain","codebuild:batchGetBuildBatches","codebuild:batchGetBuilds","codebuild:batchGetProjects","codebuild:listBuildBatches","codebuild:listBuildBatchesForProject","codebuild:listBuilds","codebuild:listBuildsForProject","codebuild:listCuratedEnvironmentImages","codebuild:listProjects","codebuild:listSourceCredentials","codecommit:batchGetRepositories","codecommit:getBranch","codecommit:getRepository","codecommit:getRepositoryTriggers","codecommit:listBranches","codecommit:listRepositories","codedeploy:batchGetApplicationRevisions","codedeploy:batchGetApplications","codedeploy:batchGetDeploymentGroups","codedeploy:batchGetDeploymentInstances","codedeploy:batchGetDeployments","codedeploy:batchGetDeploymentTargets","codedeploy:batchGetOnPremisesInstances","codedeploy:getApplication","codedeploy:getApplicationRevision","codedeploy:getDeployment","codedeploy:getDeploymentConfig","codedeploy:getDeploymentGroup","codedeploy:getDeploymentInstance","codedeploy:getDeploymentTarget","codedeploy:getOnPremisesInstance","codedeploy:listApplicationRevisions","codedeploy:listApplications","codedeploy:listDeploymentConfigs","codedeploy:listDeploymentGroups","codedeploy:listDeploymentInstances","codedeploy:listDeployments","codedeploy:listDeploymentTargets","codedeploy:listGitHubAccountTokenNames","codedeploy:listOnPremisesInstances","codepipeline:getJobDetails","codepipeline:getPipeline","codepipeline:getPipelineExecution","codepipeline:getPipelineState","codepipeline:listActionExecutions","codepipeline:listActionTypes","codepipeline:listPipelineExecutions","codepipeline:listPipelines","codepipeline:listWebhooks","codestar:describeProject","codestar:listProjects","codestar:listResources","codestar:listTeamMembers","codestar:listUserProfiles","cognito-identity:describeIdentityPool","cognito-identity:getIdentityPoolRoles","cognito-identity:listIdentities","cognito-identity:listIdentityPools","cognito-idp:adminGetUser","cognito-idp:describeIdentityProvider","cognito-idp:describeResourceServer","cognito-idp:describeRiskConfiguration","cognito-idp:describeUserImportJob","cognito-idp:describeUserPool","cognito-idp:describeUserPoolClient","cognito-idp:describeUserPoolDomain","cognito-idp:getGroup","cognito-idp:getUICustomization","cognito-idp:getUser","cognito-idp:getUserPoolMfaConfig","cognito-idp:listGroups","cognito-idp:listIdentityProviders","cognito-idp:listResourceServers","cognito-idp:listUserImportJobs","cognito-idp:listUserPoolClients","cognito-idp:listUserPools","cognito-sync:describeDataset","cognito-sync:describeIdentityPoolUsage","cognito-sync:describeIdentityUsage","cognito-sync:getCognitoEvents","cognito-sync:getIdentityPoolConfiguration","cognito-sync:listDatasets","cognito-sync:listIdentityPoolUsage","compute-optimizer:getAutoScalingGroupRecommendations","compute-optimizer:getEBSVolumeRecommendations","compute-optimizer:getEC2InstanceRecommendations","compute-optimizer:getEC2RecommendationProjectedMetrics","compute-optimizer:getEnrollmentStatus","compute-optimizer:getRecommendationSummaries","config:describeConfigRuleEvaluationStatus","config:describeConfigRules","config:describeConfigurationRecorders","config:describeConfigurationRecorderStatus","config:describeDeliveryChannels","config:describeDeliveryChannelStatus","config:getResourceConfigHistory","config:listDiscoveredResources","connect:describeUser","connect:getCurrentMetricData","connect:getMetricData","connect:listRoutingProfiles","connect:listSecurityProfiles","connect:listUsers","controltower:describeAccountFactoryConfig","controltower:describeCoreService","controltower:describeGuardrail","controltower:describeGuardrailForTarget","controltower:describeManagedAccount","controltower:describeSingleSignOn","controltower:getAvailableUpdates","controltower:getHomeRegion","controltower:getLandingZoneStatus","controltower:listDirectoryGroups","controltower:listGuardrailsForTarget","controltower:listGuardrailViolations","controltower:listManagedAccounts","controltower:listManagedAccountsForGuardrail","controltower:listManagedAccountsForParent","controltower:listManagedOrganizationalUnits","controltower:listManagedOrganizationalUnitsForGuardrail","databrew:describeDataset","databrew:describeJob","databrew:describeProject","databrew:describeRecipe","databrew:listDatasets","databrew:listJobRuns","databrew:listJobs","databrew:listProjects","databrew:listRecipes","databrew:listRecipeVersions","databrew:listTagsForResource","datapipeline:describeObjects","datapipeline:describePipelines","datapipeline:getPipelineDefinition","datapipeline:listPipelines","datapipeline:queryObjects","datasync:describeAgent","datasync:describeLocationEfs","datasync:describeLocationFsxWindows","datasync:describeLocationNfs","datasync:describeLocationObjectStorage","datasync:describeLocationS3","datasync:describeLocationSmb","datasync:describeTask","datasync:describeTaskExecution","datasync:listAgents","datasync:listLocations","datasync:listTaskExecutions","datasync:listTasks","dax:describeClusters","dax:describeDefaultParameters","dax:describeEvents","dax:describeParameterGroups","dax:describeParameters","dax:describeSubnetGroups","detective:getMembers","detective:listGraphs","detective:listInvitations","detective:listMembers","devicefarm:getAccountSettings","devicefarm:getDevice","devicefarm:getDevicePool","devicefarm:getDevicePoolCompatibility","devicefarm:getJob","devicefarm:getProject","devicefarm:getRemoteAccessSession","devicefarm:getRun","devicefarm:getSuite","devicefarm:getTest","devicefarm:getTestGridProject","devicefarm:getTestGridSession","devicefarm:getUpload","devicefarm:listArtifacts","devicefarm:listDevicePools","devicefarm:listDevices","devicefarm:listJobs","devicefarm:listProjects","devicefarm:listRemoteAccessSessions","devicefarm:listRuns","devicefarm:listSamples","devicefarm:listSuites","devicefarm:listTestGridProjects","devicefarm:listTestGridSessionActions","devicefarm:listTestGridSessionArtifacts","devicefarm:listTestGridSessions","devicefarm:listTests","devicefarm:listUniqueProblems","devicefarm:listUploads","directconnect:describeConnections","directconnect:describeConnectionsOnInterconnect","directconnect:describeInterconnects","directconnect:describeLocations","directconnect:describeVirtualGateways","directconnect:describeVirtualInterfaces","dlm:getLifecyclePolicies","dlm:getLifecyclePolicy","dms:describeAccountAttributes","dms:describeConnections","dms:describeEndpoints","dms:describeEndpointTypes","dms:describeOrderableReplicationInstances","dms:describeRefreshSchemasStatus","dms:describeReplicationInstances","dms:describeReplicationSubnetGroups","ds:describeConditionalForwarders","ds:describeDirectories","ds:describeEventTopics","ds:describeSnapshots","ds:describeTrusts","ds:getDirectoryLimits","ds:getSnapshotLimits","ds:listIpRoutes","ds:listSchemaExtensions","ds:listTagsForResource","dynamodb:describeBackup","dynamodb:describeContinuousBackups","dynamodb:describeGlobalTable","dynamodb:describeLimits","dynamodb:describeStream","dynamodb:describeTable","dynamodb:describeTimeToLive","dynamodb:listBackups","dynamodb:listGlobalTables","dynamodb:listStreams","dynamodb:listTables","dynamodb:listTagsOfResource","ec2:acceptReservedInstancesExchangeQuote","ec2:cancelReservedInstancesListing","ec2:createReservedInstancesListing","ec2:describeAccountAttributes","ec2:describeAddresses","ec2:describeAvailabilityZones","ec2:describeBundleTasks","ec2:describeByoipCidrs","ec2:describeCapacityReservations","ec2:describeClassicLinkInstances","ec2:describeClientVpnAuthorizationRules","ec2:describeClientVpnConnections","ec2:describeClientVpnEndpoints","ec2:describeClientVpnRoutes","ec2:describeClientVpnTargetNetworks","ec2:describeCoipPools","ec2:describeConversionTasks","ec2:describeCustomerGateways","ec2:describeDhcpOptions","ec2:describeElasticGpus","ec2:describeExportImageTasks","ec2:describeExportTasks","ec2:describeFastSnapshotRestores","ec2:describeFleetHistory","ec2:describeFleetInstances","ec2:describeFleets","ec2:describeFlowLogs","ec2:describeHostReservationOfferings","ec2:describeHostReservations","ec2:describeHosts","ec2:describeIdentityIdFormat","ec2:describeIdFormat","ec2:describeImageAttribute","ec2:describeImages","ec2:describeImportImageTasks","ec2:describeImportSnapshotTasks","ec2:describeInstanceAttribute","ec2:describeInstances","ec2:describeInstanceStatus","ec2:describeInternetGateways","ec2:describeKeyPairs","ec2:describeLaunchTemplates","ec2:describeLaunchTemplateVersions","ec2:describeLocalGatewayRouteTables","ec2:describeLocalGatewayRouteTableVirtualInterfaceGroupAssociations","ec2:describeLocalGatewayRouteTableVpcAssociations","ec2:describeLocalGateways","ec2:describeLocalGatewayVirtualInterfaceGroups","ec2:describeLocalGatewayVirtualInterfaces","ec2:describeMovingAddresses","ec2:describeNatGateways","ec2:describeNetworkAcls","ec2:describeNetworkInterfaceAttribute","ec2:describeNetworkInterfaces","ec2:describePlacementGroups","ec2:describePrefixLists","ec2:describePublicIpv4Pools","ec2:describeRegions","ec2:describeReservedInstances","ec2:describeReservedInstancesListings","ec2:describeReservedInstancesModifications","ec2:describeReservedInstancesOfferings","ec2:describeRouteTables","ec2:describeScheduledInstances","ec2:describeSecurityGroups","ec2:describeSnapshotAttribute","ec2:describeSnapshots","ec2:describeSpotDatafeedSubscription","ec2:describeSpotFleetInstances","ec2:describeSpotFleetRequestHistory","ec2:describeSpotFleetRequests","ec2:describeSpotInstanceRequests","ec2:describeSpotPriceHistory","ec2:describeSubnets","ec2:describeTags","ec2:describeTrafficMirrorFilters","ec2:describeTrafficMirrorSessions","ec2:describeTrafficMirrorTargets","ec2:describeTransitGatewayAttachments","ec2:describeTransitGatewayRouteTables","ec2:describeTransitGateways","ec2:describeTransitGatewayVpcAttachments","ec2:describeVolumeAttribute","ec2:describeVolumes","ec2:describeVolumesModifications","ec2:describeVolumeStatus","ec2:describeVpcAttribute","ec2:describeVpcClassicLink","ec2:describeVpcClassicLinkDnsSupport","ec2:describeVpcEndpointConnectionNotifications","ec2:describeVpcEndpointConnections","ec2:describeVpcEndpoints","ec2:describeVpcEndpointServiceConfigurations","ec2:describeVpcEndpointServicePermissions","ec2:describeVpcEndpointServices","ec2:describeVpcPeeringConnections","ec2:describeVpcs","ec2:describeVpnConnections","ec2:describeVpnGateways","ec2:getCoipPoolUsage","ec2:getConsoleScreenshot","ec2:getReservedInstancesExchangeQuote","ec2:getTransitGatewayAttachmentPropagations","ec2:getTransitGatewayRouteTableAssociations","ec2:getTransitGatewayRouteTablePropagations","ec2:modifyReservedInstances","ec2:purchaseReservedInstancesOffering","ec2:searchLocalGatewayRoutes","ecr-public:describeImages","ecr-public:describeImageTags","ecr-public:describeRegistries","ecr-public:describeRepositories","ecr-public:getRegistryCatalogData","ecr-public:getRepositoryCatalogData","ecr-public:getRepositoryPolicy","ecr-public:listTagsForResource","ecr:batchCheckLayerAvailability","ecr:describeImages","ecr:describeImageScanFindings","ecr:describeRegistry","ecr:describeRepositories","ecr:getLifecyclePolicy","ecr:getRegistryPolicy","ecr:getRepositoryPolicy","ecr:listImages","ecr:listTagsForResource","ecs:describeCapacityProviders","ecs:describeClusters","ecs:describeContainerInstances","ecs:describeServices","ecs:describeTaskDefinition","ecs:describeTasks","ecs:describeTaskSets","ecs:listAccountSettings","ecs:listAttributes","ecs:listClusters","ecs:listContainerInstances","ecs:listServices","ecs:listTagsForResource","ecs:listTaskDefinitionFamilies","ecs:listTaskDefinitions","ecs:listTasks","eks:describeCluster","eks:describeFargateProfile","eks:describeNodegroup","eks:describeUpdate","eks:listClusters","eks:listFargateProfiles","eks:listNodegroups","eks:listUpdates","elasticache:describeCacheClusters","elasticache:describeCacheEngineVersions","elasticache:describeCacheParameterGroups","elasticache:describeCacheParameters","elasticache:describeCacheSecurityGroups","elasticache:describeCacheSubnetGroups","elasticache:describeEngineDefaultParameters","elasticache:describeEvents","elasticache:describeReplicationGroups","elasticache:describeReservedCacheNodes","elasticache:describeReservedCacheNodesOfferings","elasticache:describeSnapshots","elasticache:listAllowedNodeTypeModifications","elasticache:listTagsForResource","elasticbeanstalk:checkDNSAvailability","elasticbeanstalk:describeApplications","elasticbeanstalk:describeApplicationVersions","elasticbeanstalk:describeConfigurationOptions","elasticbeanstalk:describeConfigurationSettings","elasticbeanstalk:describeEnvironmentHealth","elasticbeanstalk:describeEnvironmentManagedActionHistory","elasticbeanstalk:describeEnvironmentManagedActions","elasticbeanstalk:describeEnvironmentResources","elasticbeanstalk:describeEnvironments","elasticbeanstalk:describeEvents","elasticbeanstalk:describeInstancesHealth","elasticbeanstalk:describePlatformVersion","elasticbeanstalk:listAvailableSolutionStacks","elasticbeanstalk:listPlatformVersions","elasticbeanstalk:validateConfigurationSettings","elasticfilesystem:describeAccessPoints","elasticfilesystem:describeFileSystemPolicy","elasticfilesystem:describeFileSystems","elasticfilesystem:describeLifecycleConfiguration","elasticfilesystem:describeMountTargets","elasticfilesystem:describeMountTargetSecurityGroups","elasticfilesystem:describeTags","elasticfilesystem:listTagsForResource","elasticloadbalancing:describeInstanceHealth","elasticloadbalancing:describeListenerCertificates","elasticloadbalancing:describeListeners","elasticloadbalancing:describeLoadBalancerAttributes","elasticloadbalancing:describeLoadBalancerPolicies","elasticloadbalancing:describeLoadBalancerPolicyTypes","elasticloadbalancing:describeLoadBalancers","elasticloadbalancing:describeRules","elasticloadbalancing:describeSSLPolicies","elasticloadbalancing:describeTags","elasticloadbalancing:describeTargetGroupAttributes","elasticloadbalancing:describeTargetGroups","elasticloadbalancing:describeTargetHealth","elasticmapreduce:describeCluster","elasticmapreduce:describeSecurityConfiguration","elasticmapreduce:describeStep","elasticmapreduce:listBootstrapActions","elasticmapreduce:listClusters","elasticmapreduce:listInstanceGroups","elasticmapreduce:listInstances","elasticmapreduce:listSecurityConfigurations","elasticmapreduce:listSteps","elastictranscoder:listJobsByPipeline","elastictranscoder:listJobsByStatus","elastictranscoder:listPipelines","elastictranscoder:listPresets","elastictranscoder:readPipeline","elastictranscoder:readPreset","es:describeElasticsearchDomain","es:describeElasticsearchDomainConfig","es:describeElasticsearchDomains","es:listDomainNames","es:listTags","events:describeApiDestination","events:describeEventBus","events:describeEventSource","events:describePartnerEventSource","events:describeRule","events:listApiDestinations","events:listConnections","events:listEventBuses","events:listEventSources","events:listPartnerEventSourceAccounts","events:listPartnerEventSources","events:listRuleNamesByTarget","events:listRules","events:listTargetsByRule","events:testEventPattern","firehose:describeDeliveryStream","firehose:listDeliveryStreams","fms:getAdminAccount","fms:getComplianceDetail","fms:getNotificationChannel","fms:getPolicy","fms:getProtectionStatus","fms:listComplianceStatus","fms:listMemberAccounts","fms:listPolicies","forecast:describeDataset","forecast:describeDatasetGroup","forecast:describeDatasetImportJob","forecast:describeForecast","forecast:describeForecastExportJob","forecast:describePredictor","forecast:getAccuracyMetrics","forecast:listDatasetGroups","forecast:listDatasetImportJobs","forecast:listDatasets","forecast:listForecastExportJobs","forecast:listForecasts","forecast:listPredictors","fsx:describeBackups","fsx:describeDataRepositoryTasks","fsx:describeFileSystems","fsx:listTagsForResource","glacier:describeJob","glacier:describeVault","glacier:getDataRetrievalPolicy","glacier:getVaultAccessPolicy","glacier:getVaultLock","glacier:getVaultNotifications","glacier:listJobs","glacier:listTagsForVault","glacier:listVaults","globalaccelerator:describeAccelerator","globalaccelerator:describeAcceleratorAttributes","globalaccelerator:describeEndpointGroup","globalaccelerator:describeListener","globalaccelerator:listAccelerators","globalaccelerator:listEndpointGroups","globalaccelerator:listListeners","glue:batchGetPartition","glue:checkSchemaVersionValidity","glue:getCatalogImportStatus","glue:getClassifier","glue:getClassifiers","glue:getCrawler","glue:getCrawlerMetrics","glue:getCrawlers","glue:getDatabase","glue:getDatabases","glue:getDataflowGraph","glue:getDevEndpoint","glue:getDevEndpoints","glue:getJob","glue:getJobRun","glue:getJobRuns","glue:getJobs","glue:getMapping","glue:getPartition","glue:getPartitions","glue:getRegistry","glue:getSchema","glue:getSchemaByDefinition","glue:getSchemaVersion","glue:getSchemaVersionsDiff","glue:getTable","glue:getTables","glue:getTableVersions","glue:getTrigger","glue:getTriggers","glue:getUserDefinedFunction","glue:getUserDefinedFunctions","glue:listRegistries","glue:listSchemas","glue:listSchemaVersions","glue:querySchemaVersionMetadata","greengrass:getConnectivityInfo","greengrass:getCoreDefinition","greengrass:getCoreDefinitionVersion","greengrass:getDeploymentStatus","greengrass:getDeviceDefinition","greengrass:getDeviceDefinitionVersion","greengrass:getFunctionDefinition","greengrass:getFunctionDefinitionVersion","greengrass:getGroup","greengrass:getGroupCertificateAuthority","greengrass:getGroupVersion","greengrass:getLoggerDefinition","greengrass:getLoggerDefinitionVersion","greengrass:getResourceDefinitionVersion","greengrass:getServiceRoleForAccount","greengrass:getSubscriptionDefinition","greengrass:getSubscriptionDefinitionVersion","greengrass:listCoreDefinitions","greengrass:listCoreDefinitionVersions","greengrass:listDeployments","greengrass:listDeviceDefinitions","greengrass:listDeviceDefinitionVersions","greengrass:listFunctionDefinitions","greengrass:listFunctionDefinitionVersions","greengrass:listGroups","greengrass:listGroupVersions","greengrass:listLoggerDefinitions","greengrass:listLoggerDefinitionVersions","greengrass:listResourceDefinitions","greengrass:listResourceDefinitionVersions","greengrass:listSubscriptionDefinitions","greengrass:listSubscriptionDefinitionVersions","guardduty:getDetector","guardduty:getFindings","guardduty:getFindingsStatistics","guardduty:getInvitationsCount","guardduty:getIPSet","guardduty:getMasterAccount","guardduty:getMembers","guardduty:getThreatIntelSet","guardduty:listDetectors","guardduty:listFindings","guardduty:listInvitations","guardduty:listIPSets","guardduty:listMembers","guardduty:listThreatIntelSets","health:describeAffectedAccountsForOrganization","health:describeAffectedEntities","health:describeAffectedEntitiesForOrganization","health:describeEntityAggregates","health:describeEventAggregates","health:describeEventDetails","health:describeEventDetailsForOrganization","health:describeEvents","health:describeEventsForOrganization","health:describeEventTypes","health:describeHealthServiceStatusForOrganization","iam:getAccessKeyLastUsed","iam:getAccountAuthorizationDetails","iam:getAccountPasswordPolicy","iam:getAccountSummary","iam:getContextKeysForCustomPolicy","iam:getContextKeysForPrincipalPolicy","iam:getCredentialReport","iam:getGroup","iam:getGroupPolicy","iam:getInstanceProfile","iam:getLoginProfile","iam:getOpenIDConnectProvider","iam:getPolicy","iam:getPolicyVersion","iam:getRole","iam:getRolePolicy","iam:getSAMLProvider","iam:getServerCertificate","iam:getSSHPublicKey","iam:getUser","iam:getUserPolicy","iam:listAccessKeys","iam:listAccountAliases","iam:listAttachedGroupPolicies","iam:listAttachedRolePolicies","iam:listAttachedUserPolicies","iam:listEntitiesForPolicy","iam:listGroupPolicies","iam:listGroups","iam:listGroupsForUser","iam:listInstanceProfiles","iam:listInstanceProfilesForRole","iam:listMFADevices","iam:listOpenIDConnectProviders","iam:listPolicies","iam:listPolicyVersions","iam:listRolePolicies","iam:listRoles","iam:listSAMLProviders","iam:listServerCertificates","iam:listSigningCertificates","iam:listSSHPublicKeys","iam:listUserPolicies","iam:listUsers","iam:listVirtualMFADevices","iam:simulateCustomPolicy","iam:simulatePrincipalPolicy","imagebuilder:getComponent","imagebuilder:getComponentPolicy","imagebuilder:getContainerRecipe","imagebuilder:getDistributionConfiguration","imagebuilder:getImage","imagebuilder:getImagePipeline","imagebuilder:getImagePolicy","imagebuilder:getImageRecipe","imagebuilder:getImageRecipePolicy","imagebuilder:getInfrastructureConfiguration","imagebuilder:listComponentBuildVersions","imagebuilder:listComponents","imagebuilder:listContainerRecipes","imagebuilder:listDistributionConfigurations","imagebuilder:listImageBuildVersions","imagebuilder:listImagePipelineImages","imagebuilder:listImagePipelines","imagebuilder:listImageRecipes","imagebuilder:listImages","imagebuilder:listInfrastructureConfigurations","imagebuilder:listTagsForResource","importexport:getStatus","importexport:listJobs","inspector:describeAssessmentRuns","inspector:describeAssessmentTargets","inspector:describeAssessmentTemplates","inspector:describeCrossAccountAccessRole","inspector:describeResourceGroups","inspector:describeRulesPackages","inspector:getTelemetryMetadata","inspector:listAssessmentRunAgents","inspector:listAssessmentRuns","inspector:listAssessmentTargets","inspector:listAssessmentTemplates","inspector:listEventSubscriptions","inspector:listRulesPackages","inspector:listTagsForResource","iot:describeAuthorizer","iot:describeCACertificate","iot:describeCertificate","iot:describeDefaultAuthorizer","iot:describeEndpoint","iot:describeIndex","iot:describeJobExecution","iot:describeThing","iot:describeThingGroup","iot:describeTunnel","iot:getEffectivePolicies","iot:getIndexingConfiguration","iot:getLoggingOptions","iot:getPolicy","iot:getPolicyVersion","iot:getTopicRule","iot:getV2LoggingOptions","iot:listAttachedPolicies","iot:listAuthorizers","iot:listCACertificates","iot:listCertificates","iot:listCertificatesByCA","iot:listJobExecutionsForJob","iot:listJobExecutionsForThing","iot:listJobs","iot:listOutgoingCertificates","iot:listPolicies","iot:listPolicyPrincipals","iot:listPolicyVersions","iot:listPrincipalPolicies","iot:listPrincipalThings","iot:listRoleAliases","iot:listTargetsForPolicy","iot:listThingGroups","iot:listThingGroupsForThing","iot:listThingPrincipals","iot:listThingRegistrationTasks","iot:listThings","iot:listThingTypes","iot:listTopicRules","iot:listTunnels","iot:listV2LoggingLevels","iotevents:describeDetector","iotevents:describeDetectorModel","iotevents:describeInput","iotevents:describeLoggingOptions","iotevents:listDetectorModels","iotevents:listDetectorModelVersions","iotevents:listDetectors","iotevents:listInputs","iotsitewise:describeAccessPolicy","iotsitewise:describeAsset","iotsitewise:describeAssetModel","iotsitewise:describeAssetProperty","iotsitewise:describeDashboard","iotsitewise:describeGateway","iotsitewise:describeGatewayCapabilityConfiguration","iotsitewise:describeLoggingOptions","iotsitewise:describePortal","iotsitewise:describeProject","iotsitewise:listAccessPolicies","iotsitewise:listAssetModels","iotsitewise:listAssets","iotsitewise:listAssociatedAssets","iotsitewise:listDashboards","iotsitewise:listGateways","iotsitewise:listPortals","iotsitewise:listProjectAssets","iotsitewise:listProjects","iotwireless:getDestination","iotwireless:getDeviceProfile","iotwireless:getPartnerAccount","iotwireless:getServiceEndpoint","iotwireless:getServiceProfile","iotwireless:getWirelessDevice","iotwireless:getWirelessDeviceStatistics","iotwireless:getWirelessGateway","iotwireless:getWirelessGatewayCertificate","iotwireless:getWirelessGatewayFirmwareInformation","iotwireless:getWirelessGatewayStatistics","iotwireless:getWirelessGatewayTask","iotwireless:getWirelessGatewayTaskDefinition","iotwireless:listDestinations","iotwireless:listDeviceProfiles","iotwireless:listPartnerAccounts","iotwireless:listServiceProfiles","iotwireless:listTagsForResource","iotwireless:listWirelessDevices","iotwireless:listWirelessGateways","iotwireless:listWirelessGatewayTaskDefinitions","kafka:describeCluster","kafka:getBootstrapBrokers","kafka:listClusters","kafka:listNodes","kendra:describeDataSource","kendra:describeFaq","kendra:describeIndex","kendra:listDataSources","kendra:listFaqs","kendra:listIndices","kinesis:describeStream","kinesis:listStreams","kinesis:listTagsForStream","kinesisanalytics:describeApplication","kinesisanalytics:describeApplicationSnapshot","kinesisanalytics:listApplications","kinesisanalytics:listApplicationSnapshots","kms:describeKey","kms:getKeyPolicy","kms:getKeyRotationStatus","kms:listAliases","kms:listGrants","kms:listKeyPolicies","kms:listKeys","kms:listResourceTags","kms:listRetirableGrants","lambda:getAccountSettings","lambda:getAlias","lambda:getCodeSigningConfig","lambda:getEventSourceMapping","lambda:getFunction","lambda:getFunctionCodeSigningConfig","lambda:getFunctionConcurrency","lambda:getFunctionConfiguration","lambda:getFunctionEventInvokeConfig","lambda:getLayerVersion","lambda:getLayerVersionPolicy","lambda:getPolicy","lambda:getProvisionedConcurrencyConfig","lambda:listAliases","lambda:listCodeSigningConfigs","lambda:listEventSourceMappings","lambda:listFunctionEventInvokeConfigs","lambda:listFunctions","lambda:listFunctionsByCodeSigningConfig","lambda:listLayers","lambda:listLayerVersions","lambda:listProvisionedConcurrencyConfigs","lambda:listVersionsByFunction","launchwizard:describeProvisionedApp","launchwizard:describeProvisioningEvents","launchwizard:listProvisionedApps","lex:getBot","lex:getBotAlias","lex:getBotAliases","lex:getBotChannelAssociation","lex:getBotChannelAssociations","lex:getBots","lex:getBotVersions","lex:getBuiltinIntent","lex:getBuiltinIntents","lex:getBuiltinSlotTypes","lex:getIntent","lex:getIntents","lex:getIntentVersions","lex:getSlotType","lex:getSlotTypes","lex:getSlotTypeVersions","license-manager:getLicenseConfiguration","license-manager:getServiceSettings","license-manager:listAssociationsForLicenseConfiguration","license-manager:listFailuresForLicenseConfigurationOperations","license-manager:listLicenseConfigurations","license-manager:listLicenseSpecificationsForResource","license-manager:listResourceInventory","license-manager:listUsageForLicenseConfiguration","lightsail:getActiveNames","lightsail:getAlarms","lightsail:getAutoSnapshots","lightsail:getBlueprints","lightsail:getBundles","lightsail:getCertificates","lightsail:getContainerImages","lightsail:getContainerServiceDeployments","lightsail:getContainerServices","lightsail:getDisk","lightsail:getDisks","lightsail:getDiskSnapshot","lightsail:getDiskSnapshots","lightsail:getDistributions","lightsail:getDomain","lightsail:getDomains","lightsail:getExportSnapshotRecords","lightsail:getInstance","lightsail:getInstanceMetricData","lightsail:getInstancePortStates","lightsail:getInstances","lightsail:getInstanceSnapshot","lightsail:getInstanceSnapshots","lightsail:getInstanceState","lightsail:getKeyPair","lightsail:getKeyPairs","lightsail:getLoadBalancer","lightsail:getLoadBalancers","lightsail:getLoadBalancerTlsCertificates","lightsail:getOperation","lightsail:getOperations","lightsail:getOperationsForResource","lightsail:getRegions","lightsail:getRelationalDatabase","lightsail:getRelationalDatabases","lightsail:getRelationalDatabaseSnapshot","lightsail:getRelationalDatabaseSnapshots","lightsail:getStaticIp","lightsail:getStaticIps","logs:describeDestinations","logs:describeExportTasks","logs:describeLogGroups","logs:describeLogStreams","logs:describeMetricFilters","logs:describeQueries","logs:describeSubscriptionFilters","logs:testMetricFilter","lookoutmetrics:describeAlert","lookoutmetrics:describeAnomalyDetectionExecutions","lookoutmetrics:describeAnomalyDetector","lookoutmetrics:describeMetricSet","lookoutmetrics:getAnomalyGroup","lookoutmetrics:getDataQualityMetrics","lookoutmetrics:getFeedback","lookoutmetrics:getSampleData","lookoutmetrics:listAlerts","lookoutmetrics:listAnomalyDetectors","lookoutmetrics:listAnomalyGroupSummaries","lookoutmetrics:listAnomalyGroupTimeSeries","lookoutmetrics:listMetricSets","lookoutmetrics:listTagsForResource","machinelearning:describeBatchPredictions","machinelearning:describeDataSources","machinelearning:describeEvaluations","machinelearning:describeMLModels","machinelearning:getBatchPrediction","machinelearning:getDataSource","machinelearning:getEvaluation","machinelearning:getMLModel","managedblockchain:getMember","managedblockchain:getNetwork","managedblockchain:getNode","managedblockchain:listMembers","managedblockchain:listNetworks","managedblockchain:listNodes","mediaconnect:describeFlow","mediaconnect:listEntitlements","mediaconnect:listFlows","mediaconvert:describeEndpoints","mediaconvert:getJob","mediaconvert:getJobTemplate","mediaconvert:getPreset","mediaconvert:getQueue","mediaconvert:listJobs","mediaconvert:listJobTemplates","medialive:describeChannel","medialive:describeInput","medialive:describeInputDevice","medialive:describeInputSecurityGroup","medialive:describeMultiplex","medialive:describeOffering","medialive:describeReservation","medialive:describeSchedule","medialive:listChannels","medialive:listInputDevices","medialive:listInputs","medialive:listInputSecurityGroups","medialive:listMultiplexes","medialive:listOfferings","medialive:listReservations","mediapackage:describeChannel","mediapackage:describeOriginEndpoint","mediapackage:listChannels","mediapackage:listOriginEndpoints","mediastore:describeContainer","mediastore:describeObject","mediastore:getContainerPolicy","mediastore:getCorsPolicy","mediastore:listContainers","mediastore:listItems","mediatailor:getPlaybackConfiguration","mediatailor:listPlaybackConfigurations","mgn:describeJobLogItems","mgn:describeJobs","mgn:describeReplicationConfigurationTemplates","mgn:describeSourceServers","mgn:getLaunchConfiguration","mgn:getReplicationConfiguration","mobiletargeting:getAdmChannel","mobiletargeting:getApnsChannel","mobiletargeting:getApnsSandboxChannel","mobiletargeting:getApnsVoipChannel","mobiletargeting:getApnsVoipSandboxChannel","mobiletargeting:getApp","mobiletargeting:getApplicationSettings","mobiletargeting:getApps","mobiletargeting:getBaiduChannel","mobiletargeting:getCampaign","mobiletargeting:getCampaignActivities","mobiletargeting:getCampaigns","mobiletargeting:getCampaignVersion","mobiletargeting:getCampaignVersions","mobiletargeting:getEmailChannel","mobiletargeting:getEndpoint","mobiletargeting:getEventStream","mobiletargeting:getExportJob","mobiletargeting:getExportJobs","mobiletargeting:getGcmChannel","mobiletargeting:getImportJob","mobiletargeting:getImportJobs","mobiletargeting:getSegment","mobiletargeting:getSegmentImportJobs","mobiletargeting:getSegments","mobiletargeting:getSegmentVersion","mobiletargeting:getSegmentVersions","mobiletargeting:getSmsChannel","mq:describeBroker","mq:describeConfiguration","mq:describeConfigurationRevision","mq:describeUser","mq:listBrokers","mq:listConfigurationRevisions","mq:listConfigurations","mq:listUsers","network-firewall:describeFirewall","network-firewall:describeFirewallPolicy","network-firewall:describeLoggingConfiguration","network-firewall:describeRuleGroup","network-firewall:listFirewallPolicies","network-firewall:listFirewalls","network-firewall:listRuleGroups","networkmanager:describeGlobalNetworks","networkmanager:getCustomerGatewayAssociations","networkmanager:getDevices","networkmanager:getLinkAssociations","networkmanager:getLinks","networkmanager:getSites","networkmanager:getTransitGatewayRegistrations","opsworks-cm:describeAccountAttributes","opsworks-cm:describeBackups","opsworks-cm:describeEvents","opsworks-cm:describeNodeAssociationStatus","opsworks-cm:describeServers","opsworks:describeAgentVersions","opsworks:describeApps","opsworks:describeCommands","opsworks:describeDeployments","opsworks:describeEcsClusters","opsworks:describeElasticIps","opsworks:describeElasticLoadBalancers","opsworks:describeInstances","opsworks:describeLayers","opsworks:describeLoadBasedAutoScaling","opsworks:describeMyUserProfile","opsworks:describePermissions","opsworks:describeRaidArrays","opsworks:describeRdsDbInstances","opsworks:describeServiceErrors","opsworks:describeStackProvisioningParameters","opsworks:describeStacks","opsworks:describeStackSummary","opsworks:describeTimeBasedAutoScaling","opsworks:describeUserProfiles","opsworks:describeVolumes","opsworks:getHostnameSuggestion","organizations:listAccounts","organizations:listTagsForResource","outposts:getOutpost","outposts:getOutpostInstanceTypes","outposts:listOutposts","outposts:listSites","personalize:describeAlgorithm","personalize:describeCampaign","personalize:describeDataset","personalize:describeDatasetGroup","personalize:describeDatasetImportJob","personalize:describeEventTracker","personalize:describeFeatureTransformation","personalize:describeRecipe","personalize:describeSchema","personalize:describeSolution","personalize:describeSolutionVersion","personalize:listCampaigns","personalize:listDatasetGroups","personalize:listDatasetImportJobs","personalize:listDatasets","personalize:listEventTrackers","personalize:listRecipes","personalize:listSchemas","personalize:listSolutions","personalize:listSolutionVersions","polly:describeVoices","polly:getLexicon","polly:listLexicons","pricing:describeServices","pricing:getAttributeValues","pricing:getProducts","quicksight:describeDashboard","quicksight:describeDashboardPermissions","quicksight:describeGroup","quicksight:describeIAMPolicyAssignment","quicksight:describeTemplate","quicksight:describeTemplateAlias","quicksight:describeTemplatePermissions","quicksight:describeUser","quicksight:listDashboards","quicksight:listGroupMemberships","quicksight:listGroups","quicksight:listIAMPolicyAssignments","quicksight:listIAMPolicyAssignmentsForUser","quicksight:listTemplateAliases","quicksight:listTemplates","quicksight:listTemplateVersions","quicksight:listUserGroups","quicksight:listUsers","ram:getPermission","ram:getResourceShareAssociations","ram:getResourceShareInvitations","ram:getResourceShares","ram:listPendingInvitationResources","ram:listPrincipals","ram:listResources","ram:listResourceSharePermissions","rds:describeAccountAttributes","rds:describeCertificates","rds:describeDBClusterParameterGroups","rds:describeDBClusterParameters","rds:describeDBClusters","rds:describeDBClusterSnapshots","rds:describeDBEngineVersions","rds:describeDBInstances","rds:describeDBParameterGroups","rds:describeDBParameters","rds:describeDBSecurityGroups","rds:describeDBSnapshotAttributes","rds:describeDBSnapshots","rds:describeDBSubnetGroups","rds:describeEngineDefaultClusterParameters","rds:describeEngineDefaultParameters","rds:describeEventCategories","rds:describeEvents","rds:describeEventSubscriptions","rds:describeExportTasks","rds:describeOptionGroupOptions","rds:describeOptionGroups","rds:describeOrderableDBInstanceOptions","rds:describePendingMaintenanceActions","rds:describeReservedDBInstances","rds:describeReservedDBInstancesOfferings","rds:listTagsForResource","redshift-data:describeStatement","redshift-data:listStatements","redshift:describeClusterParameterGroups","redshift:describeClusterParameters","redshift:describeClusters","redshift:describeClusterSecurityGroups","redshift:describeClusterSnapshots","redshift:describeClusterSubnetGroups","redshift:describeClusterVersions","redshift:describeDefaultClusterParameters","redshift:describeEventCategories","redshift:describeEvents","redshift:describeEventSubscriptions","redshift:describeHsmClientCertificates","redshift:describeHsmConfigurations","redshift:describeLoggingStatus","redshift:describeOrderableClusterOptions","redshift:describeReservedNodeOfferings","redshift:describeReservedNodes","redshift:describeResize","redshift:describeSnapshotCopyGrants","redshift:describeStorage","redshift:describeTableRestoreStatus","redshift:describeTags","rekognition:listCollections","rekognition:listFaces","resource-groups:getGroup","resource-groups:getGroupQuery","resource-groups:getTags","resource-groups:listGroupResources","resource-groups:listGroups","resource-groups:searchResources","robomaker:batchDescribeSimulationJob","robomaker:describeDeploymentJob","robomaker:describeFleet","robomaker:describeRobot","robomaker:describeRobotApplication","robomaker:describeSimulationApplication","robomaker:describeSimulationJob","robomaker:listDeploymentJobs","robomaker:listFleets","robomaker:listRobotApplications","robomaker:listRobots","robomaker:listSimulationApplications","robomaker:listSimulationJobs","route53-recovery-readiness:getCell","route53-recovery-readiness:getCellReadinessSummary","route53-recovery-readiness:getReadinessCheck","route53-recovery-readiness:getReadinessCheckResourceStatus","route53-recovery-readiness:getReadinessCheckStatus","route53-recovery-readiness:getRecoveryGroup","route53-recovery-readiness:getRecoveryGroupReadinessSummary","route53-recovery-readiness:listCells","route53-recovery-readiness:listReadinessChecks","route53-recovery-readiness:listRecoveryGroups","route53-recovery-readiness:listResourceSets","route53:getChange","route53:getCheckerIpRanges","route53:getGeoLocation","route53:getHealthCheck","route53:getHealthCheckCount","route53:getHealthCheckLastFailureReason","route53:getHealthCheckStatus","route53:getHostedZone","route53:getHostedZoneCount","route53:getReusableDelegationSet","route53:getTrafficPolicy","route53:getTrafficPolicyInstance","route53:getTrafficPolicyInstanceCount","route53:listGeoLocations","route53:listHealthChecks","route53:listHostedZones","route53:listHostedZonesByName","route53:listResourceRecordSets","route53:listReusableDelegationSets","route53:listTagsForResource","route53:listTagsForResources","route53:listTrafficPolicies","route53:listTrafficPolicyInstances","route53:listTrafficPolicyInstancesByHostedZone","route53:listTrafficPolicyInstancesByPolicy","route53:listTrafficPolicyVersions","route53domains:checkDomainAvailability","route53domains:getContactReachabilityStatus","route53domains:getDomainDetail","route53domains:getOperationDetail","route53domains:listDomains","route53domains:listOperations","route53domains:listTagsForDomain","route53domains:viewBilling","route53resolver:getFirewallConfig","route53resolver:getFirewallDomainList","route53resolver:getFirewallRuleGroup","route53resolver:getFirewallRuleGroupAssociation","route53resolver:getResolverDnssecConfig","route53resolver:getResolverRulePolicy","route53resolver:listFirewallConfigs","route53resolver:listFirewallDomainLists","route53resolver:listFirewallDomains","route53resolver:listFirewallRuleGroupAssociations","route53resolver:listFirewallRuleGroups","route53resolver:listFirewallRules","route53resolver:listResolverDnssecConfigs","route53resolver:listResolverEndpointIpAddresses","route53resolver:listResolverEndpoints","route53resolver:listResolverRuleAssociations","route53resolver:listResolverRules","route53resolver:listTagsForResource","s3:getAccelerateConfiguration","s3:getAccessPointConfigurationForObjectLambda","s3:getAccessPointForObjectLambda","s3:getAccessPointPolicyStatusForObjectLambda","s3:getAnalyticsConfiguration","s3:getBucketAcl","s3:getBucketCORS","s3:getBucketLocation","s3:getBucketLogging","s3:getBucketNotification","s3:getBucketPolicy","s3:getBucketRequestPayment","s3:getBucketTagging","s3:getBucketVersioning","s3:getBucketWebsite","s3:getEncryptionConfiguration","s3:getInventoryConfiguration","s3:getLifecycleConfiguration","s3:getMetricsConfiguration","s3:getReplicationConfiguration","s3:listAccessPointsForObjectLambda","s3:listAllMyBuckets","s3:listBucket","s3:listBucketMultipartUploads","sagemaker:describeAction","sagemaker:describeAlgorithm","sagemaker:describeApp","sagemaker:describeArtifact","sagemaker:describeAutoMLJob","sagemaker:describeCompilationJob","sagemaker:describeContext","sagemaker:describeDataQualityJobDefinition","sagemaker:describeDevice","sagemaker:describeDeviceFleet","sagemaker:describeDomain","sagemaker:describeEdgePackagingJob","sagemaker:describeEndpoint","sagemaker:describeEndpointConfig","sagemaker:describeExperiment","sagemaker:describeFeatureGroup","sagemaker:describeHumanTaskUi","sagemaker:describeHyperParameterTuningJob","sagemaker:describeImage","sagemaker:describeImageVersion","sagemaker:describeLabelingJob","sagemaker:describeModel","sagemaker:describeModelBiasJobDefinition","sagemaker:describeModelExplainabilityJobDefinition","sagemaker:describeModelPackage","sagemaker:describeModelPackageGroup","sagemaker:describeModelQualityJobDefinition","sagemaker:describeMonitoringSchedule","sagemaker:describeNotebookInstance","sagemaker:describeNotebookInstanceLifecycleConfig","sagemaker:describePipeline","sagemaker:describePipelineDefinitionForExecution","sagemaker:describePipelineExecution","sagemaker:describeProcessingJob","sagemaker:describeProject","sagemaker:describeSubscribedWorkteam","sagemaker:describeTrainingJob","sagemaker:describeTransformJob","sagemaker:describeTrial","sagemaker:describeTrialComponent","sagemaker:describeUserProfile","sagemaker:describeWorkteam","sagemaker:listActions","sagemaker:listAlgorithms","sagemaker:listApps","sagemaker:listArtifacts","sagemaker:listAssociations","sagemaker:listAutoMLJobs","sagemaker:listCandidatesForAutoMLJob","sagemaker:listCodeRepositories","sagemaker:listCompilationJobs","sagemaker:listContexts","sagemaker:listDataQualityJobDefinitions","sagemaker:listDeviceFleets","sagemaker:listDevices","sagemaker:listDomains","sagemaker:listEdgePackagingJobs","sagemaker:listEndpointConfigs","sagemaker:listEndpoints","sagemaker:listExperiments","sagemaker:listFeatureGroups","sagemaker:listFlowDefinitions","sagemaker:listHumanTaskUis","sagemaker:listHyperParameterTuningJobs","sagemaker:listImages","sagemaker:listImageVersions","sagemaker:listLabelingJobs","sagemaker:listLabelingJobsForWorkteam","sagemaker:listModelBiasJobDefinitions","sagemaker:listModelExplainabilityJobDefinitions","sagemaker:listModelPackageGroups","sagemaker:listModelPackages","sagemaker:listModelQualityJobDefinitions","sagemaker:listModels","sagemaker:listMonitoringExecutions","sagemaker:listMonitoringSchedules","sagemaker:listNotebookInstanceLifecycleConfigs","sagemaker:listNotebookInstances","sagemaker:listPipelineExecutions","sagemaker:listPipelineExecutionSteps","sagemaker:listPipelineParametersForExecution","sagemaker:listPipelines","sagemaker:listProcessingJobs","sagemaker:listProjects","sagemaker:listSubscribedWorkteams","sagemaker:listTags","sagemaker:listTrainingJobs","sagemaker:listTrainingJobsForHyperParameterTuningJob","sagemaker:listTransformJobs","sagemaker:listTrialComponents","sagemaker:listTrials","sagemaker:listUserProfiles","sagemaker:listWorkteams","sdb:domainMetadata","sdb:listDomains","secretsmanager:describeSecret","secretsmanager:getResourcePolicy","secretsmanager:listSecrets","secretsmanager:listSecretVersionIds","securityhub:getEnabledStandards","securityhub:getFindings","securityhub:getInsightResults","securityhub:getInsights","securityhub:getMasterAccount","securityhub:getMembers","securityhub:listEnabledProductsForImport","securityhub:listInvitations","securityhub:listMembers","servicecatalog:describeConstraint","servicecatalog:describePortfolio","servicecatalog:describeProduct","servicecatalog:describeProductAsAdmin","servicecatalog:describeProductView","servicecatalog:describeProvisioningArtifact","servicecatalog:describeProvisioningParameters","servicecatalog:describeRecord","servicecatalog:listAcceptedPortfolioShares","servicecatalog:listConstraintsForPortfolio","servicecatalog:listLaunchPaths","servicecatalog:listPortfolioAccess","servicecatalog:listPortfolios","servicecatalog:listPortfoliosForProduct","servicecatalog:listPrincipalsForPortfolio","servicecatalog:listProvisioningArtifacts","servicecatalog:listRecordHistory","servicecatalog:scanProvisionedProducts","servicecatalog:searchProducts","servicequotas:getAssociationForServiceQuotaTemplate","servicequotas:getAWSDefaultServiceQuota","servicequotas:getRequestedServiceQuotaChange","servicequotas:getServiceQuota","servicequotas:getServiceQuotaIncreaseRequestFromTemplate","servicequotas:listAWSDefaultServiceQuotas","servicequotas:listRequestedServiceQuotaChangeHistory","servicequotas:listRequestedServiceQuotaChangeHistoryByQuota","servicequotas:listServiceQuotaIncreaseRequestsInTemplate","servicequotas:listServiceQuotas","servicequotas:listServices","ses:describeActiveReceiptRuleSet","ses:describeReceiptRule","ses:describeReceiptRuleSet","ses:getAccount","ses:getBlacklistReports","ses:getConfigurationSet","ses:getConfigurationSetEventDestinations","ses:getDedicatedIp","ses:getDedicatedIps","ses:getDeliverabilityDashboardOptions","ses:getDeliverabilityTestReport","ses:getDomainDeliverabilityCampaign","ses:getDomainStatisticsReport","ses:getEmailIdentity","ses:getIdentityDkimAttributes","ses:getIdentityMailFromDomainAttributes","ses:getIdentityNotificationAttributes","ses:getIdentityPolicies","ses:getIdentityVerificationAttributes","ses:getSendQuota","ses:getSendStatistics","ses:listConfigurationSets","ses:listDedicatedIpPools","ses:listDeliverabilityTestReports","ses:listDomainDeliverabilityCampaigns","ses:listEmailIdentities","ses:listIdentities","ses:listIdentityPolicies","ses:listReceiptFilters","ses:listReceiptRuleSets","ses:listTagsForResource","ses:listVerifiedEmailAddresses","shield:describeAttack","shield:describeProtection","shield:describeSubscription","shield:listAttacks","shield:listProtections","sms-voice:getConfigurationSetEventDestinations","sms:getConnectors","sms:getReplicationJobs","sms:getReplicationRuns","sms:getServers","snowball:describeAddress","snowball:describeAddresses","snowball:describeJob","snowball:getSnowballUsage","snowball:listJobs","sns:checkIfPhoneNumberIsOptedOut","sns:getEndpointAttributes","sns:getPlatformApplicationAttributes","sns:getSMSAttributes","sns:getSubscriptionAttributes","sns:getTopicAttributes","sns:listEndpointsByPlatformApplication","sns:listPhoneNumbersOptedOut","sns:listPlatformApplications","sns:listSubscriptions","sns:listSubscriptionsByTopic","sns:listTopics","sqs:getQueueAttributes","sqs:getQueueUrl","sqs:listDeadLetterSourceQueues","sqs:listQueues","ssm-contacts:describeEngagement","ssm-contacts:describePage","ssm-contacts:getContact","ssm-contacts:getContactChannel","ssm-contacts:listContactChannels","ssm-contacts:listContacts","ssm-contacts:listEngagements","ssm-contacts:listPageReceipts","ssm-contacts:listPagesByContact","ssm-contacts:listPagesByEngagement","ssm-incidents:getIncidentRecord","ssm-incidents:getReplicationSet","ssm-incidents:getResponsePlan","ssm-incidents:listIncidentRecords","ssm-incidents:listReplicationSets","ssm-incidents:listResponsePlans","ssm-incidents:listTimelineEvents","ssm:describeActivations","ssm:describeAssociation","ssm:describeAssociationExecutions","ssm:describeAssociationExecutionTargets","ssm:describeAutomationExecutions","ssm:describeAutomationStepExecutions","ssm:describeAvailablePatches","ssm:describeDocument","ssm:describeDocumentPermission","ssm:describeEffectiveInstanceAssociations","ssm:describeEffectivePatchesForPatchBaseline","ssm:describeInstanceAssociationsStatus","ssm:describeInstanceInformation","ssm:describeInstancePatches","ssm:describeInstancePatchStates","ssm:describeInstancePatchStatesForPatchGroup","ssm:describeInventoryDeletions","ssm:describeMaintenanceWindowExecutions","ssm:describeMaintenanceWindowExecutionTaskInvocations","ssm:describeMaintenanceWindowExecutionTasks","ssm:describeMaintenanceWindows","ssm:describeMaintenanceWindowSchedule","ssm:describeMaintenanceWindowsForTarget","ssm:describeMaintenanceWindowTargets","ssm:describeMaintenanceWindowTasks","ssm:describeOpsItems","ssm:describeParameters","ssm:describePatchBaselines","ssm:describePatchGroups","ssm:describePatchGroupState","ssm:describePatchProperties","ssm:describeSessions","ssm:getAutomationExecution","ssm:getCommandInvocation","ssm:getConnectionStatus","ssm:getDefaultPatchBaseline","ssm:getDeployablePatchSnapshotForInstance","ssm:getInventorySchema","ssm:getMaintenanceWindow","ssm:getMaintenanceWindowExecution","ssm:getMaintenanceWindowExecutionTask","ssm:getMaintenanceWindowExecutionTaskInvocation","ssm:getMaintenanceWindowTask","ssm:getOpsItem","ssm:getPatchBaseline","ssm:getPatchBaselineForPatchGroup","ssm:getServiceSetting","ssm:labelParameterVersion","ssm:listAssociations","ssm:listAssociationVersions","ssm:listCommandInvocations","ssm:listCommands","ssm:listComplianceItems","ssm:listComplianceSummaries","ssm:listDocuments","ssm:listDocumentVersions","ssm:listOpsItemEvents","ssm:listResourceComplianceSummaries","ssm:listResourceDataSync","ssm:listTagsForResource","states:describeActivity","states:describeExecution","states:describeStateMachine","states:describeStateMachineForExecution","states:getExecutionHistory","states:listActivities","states:listExecutions","states:listStateMachines","storagegateway:describeBandwidthRateLimit","storagegateway:describeCache","storagegateway:describeCachediSCSIVolumes","storagegateway:describeFileSystemAssociations","storagegateway:describeGatewayInformation","storagegateway:describeMaintenanceStartTime","storagegateway:describeNFSFileShares","storagegateway:describeSMBFileShares","storagegateway:describeSMBSettings","storagegateway:describeSnapshotSchedule","storagegateway:describeStorediSCSIVolumes","storagegateway:describeTapeArchives","storagegateway:describeTapeRecoveryPoints","storagegateway:describeTapes","storagegateway:describeUploadBuffer","storagegateway:describeVTLDevices","storagegateway:describeWorkingStorage","storagegateway:listFileShares","storagegateway:listFileSystemAssociations","storagegateway:listGateways","storagegateway:listLocalDisks","storagegateway:listTagsForResource","storagegateway:listTapes","storagegateway:listVolumeInitiators","storagegateway:listVolumeRecoveryPoints","storagegateway:listVolumes","swf:countClosedWorkflowExecutions","swf:countOpenWorkflowExecutions","swf:countPendingActivityTasks","swf:countPendingDecisionTasks","swf:describeActivityType","swf:describeDomain","swf:describeWorkflowExecution","swf:describeWorkflowType","swf:getWorkflowExecutionHistory","swf:listActivityTypes","swf:listClosedWorkflowExecutions","swf:listDomains","swf:listOpenWorkflowExecutions","swf:listWorkflowTypes","synthetics:describeCanaries","synthetics:describeCanariesLastRun","synthetics:describeRuntimeVersions","synthetics:getCanary","synthetics:getCanaryRuns","transfer:describeServer","transfer:describeUser","transfer:listServers","transfer:listTagsForResource","transfer:listUsers","waf-regional:getByteMatchSet","waf-regional:getChangeTokenStatus","waf-regional:getIPSet","waf-regional:getRule","waf-regional:getSqlInjectionMatchSet","waf-regional:getWebACL","waf-regional:getWebACLForResource","waf-regional:listByteMatchSets","waf-regional:listIPSets","waf-regional:listResourcesForWebACL","waf-regional:listRules","waf-regional:listSqlInjectionMatchSets","waf-regional:listWebACLs","waf:getByteMatchSet","waf:getChangeTokenStatus","waf:getIPSet","waf:getRule","waf:getSampledRequests","waf:getSizeConstraintSet","waf:getSqlInjectionMatchSet","waf:getWebACL","waf:getXssMatchSet","waf:listByteMatchSets","waf:listIPSets","waf:listRules","waf:listSizeConstraintSets","waf:listSqlInjectionMatchSets","waf:listWebACLs","waf:listXssMatchSets","wafv2:checkCapacity","wafv2:describeManagedRuleGroup","wafv2:getIPSet","wafv2:getLoggingConfiguration","wafv2:getPermissionPolicy","wafv2:getRateBasedStatementManagedKeys","wafv2:getRegexPatternSet","wafv2:getRuleGroup","wafv2:getSampledRequests","wafv2:getWebACL","wafv2:getWebACLForResource","wafv2:listAvailableManagedRuleGroups","wafv2:listIPSets","wafv2:listLoggingConfigurations","wafv2:listRegexPatternSets","wafv2:listResourcesForWebACL","wafv2:listRuleGroups","wafv2:listTagsForResource","wafv2:listWebACLs","workdocs:checkAlias","workdocs:describeAvailableDirectories","workdocs:describeInstances","worklink:describeAuditStreamConfiguration","worklink:describeCompanyNetworkConfiguration","worklink:describeDevice","worklink:describeDevicePolicyConfiguration","worklink:describeDomain","worklink:describeFleetMetadata","worklink:describeIdentityProviderConfiguration","worklink:describeWebsiteCertificateAuthority","worklink:listDevices","worklink:listDomains","worklink:listFleets","worklink:listWebsiteAuthorizationProviders","worklink:listWebsiteCertificateAuthorities","workmail:describeGroup","workmail:describeOrganization","workmail:describeResource","workmail:describeUser","workmail:listAliases","workmail:listGroupMembers","workmail:listGroups","workmail:listMailboxPermissions","workmail:listOrganizations","workmail:listResourceDelegates","workmail:listResources","workmail:listUsers","workspaces:describeAccount","workspaces:describeAccountModifications","workspaces:describeIpGroups","workspaces:describeTags","workspaces:describeWorkspaceBundles","workspaces:describeWorkspaceDirectories","workspaces:describeWorkspaceImages","workspaces:describeWorkspaces","workspaces:describeWorkspacesConnectionStatus"],"Effect": "Allow","Resource": ["*"]}],"Version": "2012-10-17"},"arn": "arn:aws:iam::aws:policy/aws-service-role/AWSSupportServiceRolePolicy","attached_to": {"roles": [{"id": "AROAJCXETX2ROIWUKOPGG","name": "AWSServiceRoleForSupport"}]},"id": "ANPAJ7W6266ELXF5MISDS","name": "AWSSupportServiceRolePolicy"},"ANPAJH4QJ2WMHBOB47BUE": {"PolicyDocument": {"Statement": [{"Action": ["autoscaling:DescribeAccountLimits","autoscaling:DescribeAutoScalingGroups","autoscaling:DescribeLaunchConfigurations","cloudformation:DescribeAccountLimits","cloudformation:DescribeStacks","cloudformation:ListStacks","cloudfront:ListDistributions","cloudtrail:DescribeTrails","cloudtrail:GetTrailStatus","dynamodb:DescribeLimits","dynamodb:DescribeTable","dynamodb:ListTables","ec2:DescribeAddresses","ec2:DescribeReservedInstances","ec2:DescribeInstances","ec2:DescribeVpcs","ec2:DescribeInternetGateways","ec2:DescribeImages","ec2:DescribeVolumes","ec2:DescribeSecurityGroups","ec2:DescribeReservedInstancesOfferings","ec2:DescribeSnapshots","ec2:DescribeVpnConnections","ec2:DescribeVpnGateways","ec2:DescribeLaunchTemplateVersions","elasticloadbalancing:DescribeAccountLimits","elasticloadbalancing:DescribeInstanceHealth","elasticloadbalancing:DescribeLoadBalancerAttributes","elasticloadbalancing:DescribeLoadBalancerPolicies","elasticloadbalancing:DescribeLoadBalancerPolicyTypes","elasticloadbalancing:DescribeLoadBalancers","elasticloadbalancing:DescribeTargetGroups","iam:GenerateCredentialReport","iam:GetAccountPasswordPolicy","iam:GetAccountSummary","iam:GetCredentialReport","iam:GetServerCertificate","iam:ListServerCertificates","kinesis:DescribeLimits","rds:DescribeAccountAttributes","rds:DescribeDBClusters","rds:DescribeDBEngineVersions","rds:DescribeDBInstances","rds:DescribeDBParameterGroups","rds:DescribeDBParameters","rds:DescribeDBSecurityGroups","rds:DescribeDBSnapshots","rds:DescribeDBSubnetGroups","rds:DescribeEngineDefaultParameters","rds:DescribeEvents","rds:DescribeOptionGroupOptions","rds:DescribeOptionGroups","rds:DescribeOrderableDBInstanceOptions","rds:DescribeReservedDBInstances","rds:DescribeReservedDBInstancesOfferings","rds:ListTagsForResource","redshift:DescribeClusters","redshift:DescribeReservedNodeOfferings","redshift:DescribeReservedNodes","route53:GetAccountLimit","route53:GetHealthCheck","route53:GetHostedZone","route53:ListHealthChecks","route53:ListHostedZones","route53:ListHostedZonesByName","route53:ListResourceRecordSets","s3:GetAccountPublicAccessBlock","s3:GetBucketAcl","s3:GetBucketPolicy","s3:GetBucketPolicyStatus","s3:GetBucketLocation","s3:GetBucketLogging","s3:GetBucketVersioning","s3:GetBucketPublicAccessBlock","s3:ListBucket","s3:ListAllMyBuckets","ses:GetSendQuota","sqs:ListQueues","cloudwatch:GetMetricStatistics","ce:GetReservationPurchaseRecommendation","ce:GetSavingsPlansPurchaseRecommendation"],"Effect": "Allow","Resource": ["*"]}],"Version": "2012-10-17"},"arn": "arn:aws:iam::aws:policy/aws-service-role/AWSTrustedAdvisorServiceRolePolicy","attached_to": {"roles": [{"id": "AROAJCHEQKY4NYQFQWP5K","name": "AWSServiceRoleForTrustedAdvisor"}]},"id": "ANPAJH4QJ2WMHBOB47BUE","name": "AWSTrustedAdvisorServiceRolePolicy"},"ANPAJQPCESDDYDLLSOGYO": {"PolicyDocument": {"Statement": [{"Action": ["cloudtrail:DescribeTrails","cloudtrail:GetTrailStatus","cloudtrail:GetEventSelectors","cloudwatch:DescribeAlarms","cloudwatch:DescribeAlarmsForMetric","logs:DescribeMetricFilters","sns:ListSubscriptionsByTopic","config:DescribeConfigurationRecorders","config:DescribeConfigurationRecorderStatus","config:DescribeConfigRules","config:BatchGetResourceConfig","config:SelectResourceConfig","iam:GenerateCredentialReport","iam:GetCredentialReport","organizations:ListAccounts","organizations:DescribeAccount","organizations:DescribeOrganization","config:PutEvaluations"],"Effect": "Allow","Resource": ["*"]},{"Action": ["config:PutConfigRule","config:DeleteConfigRule","config:GetComplianceDetailsByConfigRule","config:DescribeConfigRuleEvaluationStatus"],"Effect": "Allow","Resource": ["arn:aws:config:*:*:config-rule/aws-service-rule/*securityhub*"]}],"Version": "2012-10-17"},"arn": "arn:aws:iam::aws:policy/aws-service-role/AWSSecurityHubServiceRolePolicy","attached_to": {"roles": [{"id": "AROAWIJXQGZ5HSCDUOZE5","name": "AWSServiceRoleForSecurityHub"}]},"id": "ANPAJQPCESDDYDLLSOGYO","name": "AWSSecurityHubServiceRolePolicy"},"ANPAJSVXG6QHPE6VHDZ4Q": {"PolicyDocument": {"Statement": [{"Action": ["cloudwatch:DescribeAlarms","elasticmapreduce:ListInstanceGroups","elasticmapreduce:ModifyInstanceGroups"],"Effect": "Allow","Resource": ["*"]}],"Version": "2012-10-17"},"arn": "arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceforAutoScalingRole","attached_to": {"roles": [{"id": "AROAIH747R37LKSEOZ2MA","name": "EMR_AutoScaling_DefaultRole"}]},"id": "ANPAJSVXG6QHPE6VHDZ4Q","name": "AmazonElasticMapReduceforAutoScalingRole"},"ANPAZKAPJZG4CAIXDDRI2": {"PolicyDocument": {"Statement": [{"Action": ["ec2:DescribeAddresses","ec2:DescribeByoipCidrs","ec2:DescribeVpcEndpoints","ec2:DescribeVpcs","iam:GetRole","iam:ListRoles","kms:DescribeKey","kms:GetKeyPolicy","kms:ListGrants","kms:ListKeyPolicies","kms:ListKeys","lambda:GetLayerVersionPolicy","lambda:GetPolicy","lambda:ListAliases","lambda:ListFunctions","lambda:ListLayers","lambda:ListLayerVersions","lambda:ListVersionsByFunction","organizations:DescribeAccount","organizations:DescribeOrganization","organizations:DescribeOrganizationalUnit","organizations:ListAccounts","organizations:ListAccountsForParent","organizations:ListAWSServiceAccessForOrganization","organizations:ListChildren","organizations:ListDelegatedAdministrators","organizations:ListOrganizationalUnitsForParent","organizations:ListParents","organizations:ListRoots","s3:DescribeMultiRegionAccessPointOperation","s3:GetAccessPoint","s3:GetAccessPointPolicy","s3:GetAccessPointPolicyStatus","s3:GetAccountPublicAccessBlock","s3:GetBucketAcl","s3:GetBucketLocation","s3:GetBucketPolicyStatus","s3:GetBucketPolicy","s3:GetBucketPublicAccessBlock","s3:GetMultiRegionAccessPoint","s3:GetMultiRegionAccessPointPolicy","s3:GetMultiRegionAccessPointPolicyStatus","s3:ListAccessPoints","s3:ListAllMyBuckets","s3:ListMultiRegionAccessPoints","sns:GetTopicAttributes","sns:ListTopics","secretsmanager:DescribeSecret","secretsmanager:GetResourcePolicy","secretsmanager:ListSecrets","sqs:GetQueueAttributes","sqs:ListQueues"],"Effect": "Allow","Resource": ["*"]}],"Version": "2012-10-17"},"arn": "arn:aws:iam::aws:policy/aws-service-role/AccessAnalyzerServiceRolePolicy","attached_to": {"roles": [{"id": "AROAWIJXQGZ5OSPI4PBJL","name": "AWSServiceRoleForAccessAnalyzer"}]},"id": "ANPAZKAPJZG4CAIXDDRI2","name": "AccessAnalyzerServiceRolePolicy"}},"policies_count": 9,"roles": {"AROAI265GPNVMDZAKJPPA": {"arn": "arn:aws:iam::430150006394:role/EMR_EC2_DefaultRole","assume_role_policy": {"PolicyDocument": {"Statement": [{"Action": "sts:AssumeRole","Effect": "Allow","Principal": {"Service": "ec2.amazonaws.com"},"Sid": ""}],"Version": "2008-10-17"}},"awslambdas_count": 0,"create_date": "2019-01-26 09:04:06+00:00","description": null,"id": "AROAI265GPNVMDZAKJPPA","inline_policies": {},"inline_policies_count": 0,"instance_profiles": {"AIPAJLM3SI3PSXMHLNA24": {"arn": "arn:aws:iam::430150006394:instance-profile/EMR_EC2_DefaultRole","name": "EMR_EC2_DefaultRole"}},"instances_count": 0,"max_session_duration": 3600,"name": "EMR_EC2_DefaultRole","path": "/","policies": ["ANPAIGALS5RCDLZLB3PGS"],"policies_counts": 1},"AROAIH747R37LKSEOZ2MA": {"arn": "arn:aws:iam::430150006394:role/EMR_AutoScaling_DefaultRole","assume_role_policy": {"PolicyDocument": {"Statement": [{"Action": "sts:AssumeRole","Effect": "Allow","Principal": {"Service": ["application-autoscaling.amazonaws.com","elasticmapreduce.amazonaws.com"]}}],"Version": "2012-10-17"}},"awslambdas_count": 0,"create_date": "2019-01-26 09:04:06+00:00","description": null,"id": "AROAIH747R37LKSEOZ2MA","inline_policies": {},"inline_policies_count": 0,"instance_profiles": {},"instances_count": 0,"max_session_duration": 3600,"name": "EMR_AutoScaling_DefaultRole","path": "/","policies": ["ANPAJSVXG6QHPE6VHDZ4Q"],"policies_counts": 1},"AROAIXBSWIKGEEDLMO53I": {"arn": "arn:aws:iam::430150006394:role/EMR_DefaultRole","assume_role_policy": {"PolicyDocument": {"Statement": [{"Action": "sts:AssumeRole","Effect": "Allow","Principal": {"Service": "elasticmapreduce.amazonaws.com"},"Sid": ""}],"Version": "2008-10-17"}},"awslambdas_count": 0,"create_date": "2019-01-26 09:04:06+00:00","description": null,"id": "AROAIXBSWIKGEEDLMO53I","inline_policies": {},"inline_policies_count": 0,"instance_profiles": {},"instances_count": 0,"max_session_duration": 3600,"name": "EMR_DefaultRole","path": "/","policies": ["ANPAIDI2BQT2LKXZG36TW"],"policies_counts": 1},"AROAJ2LRZXYT2USPF2ZTY": {"arn": "arn:aws:iam::430150006394:role/aws-service-role/elasticmapreduce.amazonaws.com/AWSServiceRoleForEMRCleanup","assume_role_policy": {"PolicyDocument": {"Statement": [{"Action": "sts:AssumeRole","Effect": "Allow","Principal": {"Service": "elasticmapreduce.amazonaws.com"}}],"Version": "2012-10-17"}},"awslambdas_count": 0,"create_date": "2019-01-26 09:04:23+00:00","description": null,"id": "AROAJ2LRZXYT2USPF2ZTY","inline_policies": {},"inline_policies_count": 0,"instance_profiles": {},"instances_count": 0,"max_session_duration": 3600,"name": "AWSServiceRoleForEMRCleanup","path": "/aws-service-role/elasticmapreduce.amazonaws.com/","policies": ["ANPAI4YEZURRMKACW56EA"],"policies_counts": 1},"AROAJCHEQKY4NYQFQWP5K": {"arn": "arn:aws:iam::430150006394:role/aws-service-role/trustedadvisor.amazonaws.com/AWSServiceRoleForTrustedAdvisor","assume_role_policy": {"PolicyDocument": {"Statement": [{"Action": "sts:AssumeRole","Effect": "Allow","Principal": {"Service": "trustedadvisor.amazonaws.com"}}],"Version": "2012-10-17"}},"awslambdas_count": 0,"create_date": "2018-08-15 22:08:26+00:00","description": "Access for the AWS Trusted Advisor Service to help reduce cost, increase performance, and improve security of your AWS environment.","id": "AROAJCHEQKY4NYQFQWP5K","inline_policies": {},"inline_policies_count": 0,"instance_profiles": {},"instances_count": 0,"max_session_duration": 3600,"name": "AWSServiceRoleForTrustedAdvisor","path": "/aws-service-role/trustedadvisor.amazonaws.com/","policies": ["ANPAJH4QJ2WMHBOB47BUE"],"policies_counts": 1},"AROAJCXETX2ROIWUKOPGG": {"arn": "arn:aws:iam::430150006394:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport","assume_role_policy": {"PolicyDocument": {"Statement": [{"Action": "sts:AssumeRole","Effect": "Allow","Principal": {"Service": "support.amazonaws.com"}}],"Version": "2012-10-17"}},"awslambdas_count": 0,"create_date": "2018-08-09 19:34:27+00:00","description": "Enables resource access for AWS to provide billing, administrative and support services","id": "AROAJCXETX2ROIWUKOPGG","inline_policies": {},"inline_policies_count": 0,"instance_profiles": {},"instances_count": 0,"max_session_duration": 3600,"name": "AWSServiceRoleForSupport","path": "/aws-service-role/support.amazonaws.com/","policies": ["ANPAJ7W6266ELXF5MISDS"],"policies_counts": 1},"AROAJY5MNJYDKGD2UIATQ": {"arn": "arn:aws:iam::430150006394:role/service-role/load-wikipedia","assume_role_policy": {"PolicyDocument": {"Statement": [{"Action": "sts:AssumeRole","Effect": "Allow","Principal": {"Service": "lambda.amazonaws.com"}}],"Version": "2012-10-17"}},"awslambdas": {"load-wikipedia": {"access_policy": {"Id": "default","Statement": [],"Version": "2012-10-17"},"arn": "arn:aws:lambda:eu-west-1:430150006394:function:load-wikipedia","code_sha256": "txY7sj38mwfot6uoeqMhNs4P/VycimyJcRBdlDBTyik=","code_size": 506,"description": "","env_variable_names": [],"env_variable_values": [],"env_variables": [],"execution_role": {"Arn": "arn:aws:iam::430150006394:role/service-role/load-wikipedia","AssumeRolePolicyDocument": {"Statement": [{"Action": "sts:AssumeRole","Effect": "Allow","Principal": {"Service": "lambda.amazonaws.com"}}],"Version": "2012-10-17"},"CreateDate": "2019-01-23 17:01:24+00:00","MaxSessionDuration": 3600,"Path": "/service-role/","RoleId": "AROAJY5MNJYDKGD2UIATQ","RoleLastUsed": {},"RoleName": "load-wikipedia","policies": [{"Document": {"Statement": [{"Action": "logs:CreateLogGroup","Effect": "Allow","Resource": "arn:aws:logs:eu-west-1:430150006394:*"},{"Action": ["logs:CreateLogStream","logs:PutLogEvents"],"Effect": "Allow","Resource": ["arn:aws:logs:eu-west-1:430150006394:log-group:/aws/lambda/load-wikipedia:*"]}],"Version": "2012-10-17"},"PolicyArn": "arn:aws:iam::430150006394:policy/service-role/AWSLambdaBasicExecutionRole-676647ec-377e-496c-8355-37f23bf12c85","PolicyName": "AWSLambdaBasicExecutionRole-676647ec-377e-496c-8355-37f23bf12c85"}],"policy_statements": [{"Action": "logs:CreateLogGroup","Effect": "Allow","Resource": "arn:aws:logs:eu-west-1:430150006394:*"},{"Action": ["logs:CreateLogStream","logs:PutLogEvents"],"Effect": "Allow","Resource": ["arn:aws:logs:eu-west-1:430150006394:log-group:/aws/lambda/load-wikipedia:*"]}]},"handler": "lambda_function.lambda_handler","last_modified": "2019-01-25T17:47:21.038+0000","memory_size": 128,"name": "load-wikipedia","region": "eu-west-1","revision_id": "9ec6c002-9048-4d53-a4c2-001e406827b3","role_arn": "arn:aws:iam::430150006394:role/service-role/load-wikipedia","runtime": "python2.7","timeout": 3,"tracing_config": {"Mode": "PassThrough"},"version": "$LATEST"}},"awslambdas_count": 1,"create_date": "2019-01-23 17:01:24+00:00","description": null,"id": "AROAJY5MNJYDKGD2UIATQ","inline_policies": {},"inline_policies_count": 0,"instance_profiles": {},"instances_count": 0,"max_session_duration": 3600,"name": "load-wikipedia","path": "/service-role/","policies": ["ANPAIDFYJXP7KKG7FLVWO"],"policies_counts": 1},"AROAWIJXQGZ5HSCDUOZE5": {"arn": "arn:aws:iam::430150006394:role/aws-service-role/securityhub.amazonaws.com/AWSServiceRoleForSecurityHub","assume_role_policy": {"PolicyDocument": {"Statement": [{"Action": "sts:AssumeRole","Effect": "Allow","Principal": {"Service": "securityhub.amazonaws.com"}}],"Version": "2012-10-17"}},"awslambdas_count": 0,"create_date": "2021-04-28 13:12:07+00:00","description": "A service-linked role required for AWS Security Hub to access your resources.","id": "AROAWIJXQGZ5HSCDUOZE5","inline_policies": {},"inline_policies_count": 0,"instance_profiles": {},"instances_count": 0,"max_session_duration": 3600,"name": "AWSServiceRoleForSecurityHub","path": "/aws-service-role/securityhub.amazonaws.com/","policies": ["ANPAJQPCESDDYDLLSOGYO"],"policies_counts": 1},"AROAWIJXQGZ5OSPI4PBJL": {"arn": "arn:aws:iam::430150006394:role/aws-service-role/access-analyzer.amazonaws.com/AWSServiceRoleForAccessAnalyzer","assume_role_policy": {"PolicyDocument": {"Statement": [{"Action": "sts:AssumeRole","Effect": "Allow","Principal": {"Service": "access-analyzer.amazonaws.com"}}],"Version": "2012-10-17"}},"awslambdas_count": 0,"create_date": "2021-04-28 13:17:38+00:00","description": null,"id": "AROAWIJXQGZ5OSPI4PBJL","inline_policies": {},"inline_policies_count": 0,"instance_profiles": {},"instances_count": 0,"max_session_duration": 3600,"name": "AWSServiceRoleForAccessAnalyzer","path": "/aws-service-role/access-analyzer.amazonaws.com/","policies": ["ANPAZKAPJZG4CAIXDDRI2"],"policies_counts": 1}},"roles_count": 9,"users": {"AIDAJUK77MEJCW5J3DWZU": {"AccessKeys": [{"AccessKeyId": "AKIAJA4OP6C7FVAIIK6A","CreateDate": "2013-12-19 09:13:40+00:00","Status": "Active","UserName": "dams"},{"AccessKeyId": "AKIAI6RSA3TKSH5RFPJQ","CreateDate": "2019-01-25 17:58:41+00:00","Status": "Active","UserName": "dams"}],"CreateDate": "2013-12-19 09:13:40+00:00","MFADevices": [],"Path": "/","arn": "arn:aws:iam::430150006394:user/dams","groups": ["devs"],"id": "AIDAJUK77MEJCW5J3DWZU","inline_policies": {},"inline_policies_count": 0,"name": "dams","tags": {"IsTruncated": false,"ResponseMetadata": {"HTTPHeaders": {"content-length": "300","content-type": "text/xml","date": "Fri, 01 Oct 2021 18:47:29 GMT","x-amzn-requestid": "3fe4d555-c7cc-46e3-ab08-63c4a6b4aca3"},"HTTPStatusCode": 200,"RequestId": "3fe4d555-c7cc-46e3-ab08-63c4a6b4aca3","RetryAttempts": 0},"Tags": []}}},"users_count": 1},"kms": {"filters": {},"findings": {"kms-cmk-rotation-disabled": {"checked_items": 0,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "2.8","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "2.8","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "2.8","version": "1.2.0"}],"dashboard_name": "Keys","description": "KMS Customer Master Keys (CMKs) with Rotation Disabled","display_path": "kms.regions.id.keys.id","flagged_items": 0,"id_suffix": "rotation_enabled","items": [],"level": "warning","path": "kms.regions.id.keys.id","rationale": "Cryptographic best practices discourage extensive reuse of encryption keys. Consequently, Customer Master Keys (CMKs) should be rotated to prevent usage of compromised keys.

Note that AWS KMS supports optional automatic key rotation only for customer managed CMKs.","references": ["https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html"],"remediation": "For every KMS Customer Master Keys (CMKs), ensure that Rotate this key every year is enabled","service": "KMS"}},"keys_count": 0,"regions": {"ap-northeast-1": {"id": "ap-northeast-1","keys": {},"keys_count": 0,"name": "ap-northeast-1","region": "ap-northeast-1"},"ap-northeast-2": {"id": "ap-northeast-2","keys": {},"keys_count": 0,"name": "ap-northeast-2","region": "ap-northeast-2"},"ap-northeast-3": {"id": "ap-northeast-3","keys": {},"keys_count": 0,"name": "ap-northeast-3","region": "ap-northeast-3"},"ap-south-1": {"id": "ap-south-1","keys": {},"keys_count": 0,"name": "ap-south-1","region": "ap-south-1"},"ap-southeast-1": {"id": "ap-southeast-1","keys": {},"keys_count": 0,"name": "ap-southeast-1","region": "ap-southeast-1"},"ap-southeast-2": {"id": "ap-southeast-2","keys": {},"keys_count": 0,"name": "ap-southeast-2","region": "ap-southeast-2"},"ca-central-1": {"id": "ca-central-1","keys": {},"keys_count": 0,"name": "ca-central-1","region": "ca-central-1"},"eu-central-1": {"id": "eu-central-1","keys": {},"keys_count": 0,"name": "eu-central-1","region": "eu-central-1"},"eu-north-1": {"id": "eu-north-1","keys": {},"keys_count": 0,"name": "eu-north-1","region": "eu-north-1"},"eu-west-1": {"id": "eu-west-1","keys": {},"keys_count": 0,"name": "eu-west-1","region": "eu-west-1"},"eu-west-2": {"id": "eu-west-2","keys": {},"keys_count": 0,"name": "eu-west-2","region": "eu-west-2"},"eu-west-3": {"id": "eu-west-3","keys": {},"keys_count": 0,"name": "eu-west-3","region": "eu-west-3"},"sa-east-1": {"id": "sa-east-1","keys": {},"keys_count": 0,"name": "sa-east-1","region": "sa-east-1"},"us-east-1": {"id": "us-east-1","keys": {},"keys_count": 0,"name": "us-east-1","region": "us-east-1"},"us-east-2": {"id": "us-east-2","keys": {},"keys_count": 0,"name": "us-east-2","region": "us-east-2"},"us-west-1": {"id": "us-west-1","keys": {},"keys_count": 0,"name": "us-west-1","region": "us-west-1"},"us-west-2": {"id": "us-west-2","keys": {},"keys_count": 0,"name": "us-west-2","region": "us-west-2"}},"regions_count": 17},"rds": {"filters": {},"findings": {"rds-instance-backup-disabled": {"checked_items": 0,"compliance": null,"dashboard_name": "Instances","description": "Backup Disabled","flagged_items": 0,"id_suffix": "BackupRetentionPeriod","items": [],"level": "danger","path": "rds.regions.id.vpcs.id.instances.id","rationale": "Backups should be enabled to enable disaster recovery.","references": ["https://aws.amazon.com/rds/details/backup/"],"remediation": null,"service": "RDS"},"rds-instance-ca-certificate-deprecated": {"checked_items": 0,"compliance": null,"dashboard_name": "Instances","description": "Deprecated Certificate Authority Assigned to RDS Instance","flagged_items": 0,"id_suffix": "CACertificateIdentifier","items": [],"level": "warning","path": "rds.regions.id.vpcs.id.instances.id","rationale": "Amazon Web Services is deprecating the RDS Certificate Authority created in 2015 (rds-ca-2015). Any endpoints using TLS to protect RDS communications will fail after March 5th, 2020.","references": ["https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL-certificate-rotation.html"],"remediation": null,"service": "RDS"},"rds-instance-no-minor-upgrade": {"checked_items": 0,"compliance": null,"dashboard_name": "Instances","description": "Auto Minor Version Upgrade Disabled","flagged_items": 0,"id_suffix": "AutoMinorVersionUpgrade","items": [],"level": "danger","path": "rds.regions.id.vpcs.id.instances.id","rationale": "Auto Minor Version Upgrade is a feature that you can enable to have your database automatically upgraded when a new minor database engine version is available. Minor version upgrades often patch security vulnerabilities and fix bugs, and therefor should be applied.","references": ["https://aws.amazon.com/blogs/database/best-practices-for-upgrading-amazon-rds-to-major-and-minor-versions-of-postgresql/","https://aws.amazon.com/about-aws/whats-new/2018/12/amazon-rds-enhances-auto-minor-version-upgrades/"],"remediation": null,"service": "RDS"},"rds-instance-short-backup-retention-period": {"checked_items": 0,"compliance": null,"dashboard_name": "Instances","description": "Short Backup Retention Period","flagged_items": 0,"id_suffix": "BackupRetentionPeriod","items": [],"level": "warning","path": "rds.regions.id.vpcs.id.instances.id","rationale": "The backup retention period is a period of time between 0 and 35 days for which you can perform a point-in-time restore. Setting the backup retention period to 0 disables automated backups.

It is recommended that the retention period is set to at least 30 days. Having a short retention period will impact how far back in time the database can be restored to, and may affect integrity and availability of data.","references": ["https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithAutomatedBackups.html"],"remediation": null,"service": "RDS"},"rds-instance-single-az": {"checked_items": 0,"compliance": null,"dashboard_name": "Instances","description": "Single AZ RDS Instance","flagged_items": 0,"id_suffix": "MultiAZ","items": [],"level": "danger","path": "rds.regions.id.vpcs.id.instances.id","rationale": "In case of failure, with a single-AZ deployment configuration, should an availability zone specific database failure occur, Amazon RDS can not automatically fail over to the standby availability zone.","references": ["https://aws.amazon.com/rds/features/multi-az/"],"remediation": null,"service": "RDS"},"rds-instance-storage-not-encrypted": {"checked_items": 0,"compliance": null,"dashboard_name": "Instances","description": "Instance Storage Not Encrypted","flagged_items": 0,"id_suffix": "StorageEncrypted","items": [],"level": "warning","path": "rds.regions.id.vpcs.id.instances.id","rationale": "Data-at-rest should be encrypted.","references": ["https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.Encryption.html"],"remediation": null,"service": "RDS"},"rds-security-group-allows-all": {"checked_items": 0,"compliance": null,"dashboard_name": "Security Groups","description": "Security Group Allows All IP Addresses","display_path": "rds.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "rds.regions.id.vpcs.id.security_groups.id.ip_ranges","rationale": "The security group allows access to RDS instances from any source address, which creates a wider attack surface for resources assigned to it. Source address restrictions should be implemented","references": null,"remediation": null,"service": "RDS"},"rds-snapshot-public": {"checked_items": 0,"compliance": null,"dashboard_name": "Snapshots","description": "Publicly Accessible RDS Snapshot","display_path": "rds.regions.id.vpcs.id.snapshots.id","flagged_items": 0,"items": [],"level": "danger","path": "rds.regions.id.vpcs.id.snapshots.id.attributes.id","rationale": "Snapshots should never be public, as this risks exposing sensitive data.","references": ["https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ShareSnapshot.html"],"remediation": null,"service": "RDS"}},"instances_count": 0,"parameter_groups_count": 0,"regions": {"ap-northeast-1": {"id": "ap-northeast-1","instances_count": 0,"name": "ap-northeast-1","parameter_groups": {},"parameter_groups_count": 0,"region": "ap-northeast-1","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:ap-northeast-1:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-0cbc506a": {"arn": "arn:aws:vpc:ap-northeast-1:430150006394:virtual-private-cloud/vpc-0cbc506a","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-0cbc506a","instances": {},"instances_count": 0,"name": "vpc-0cbc506a","snapshots": {},"snapshots_count": 0,"state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"ap-northeast-2": {"id": "ap-northeast-2","instances_count": 0,"name": "ap-northeast-2","parameter_groups": {},"parameter_groups_count": 0,"region": "ap-northeast-2","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:ap-northeast-2:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-73f44e18": {"arn": "arn:aws:vpc:ap-northeast-2:430150006394:virtual-private-cloud/vpc-73f44e18","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-73f44e18","instances": {},"instances_count": 0,"name": "vpc-73f44e18","snapshots": {},"snapshots_count": 0,"state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"ap-northeast-3": {"id": "ap-northeast-3","instances_count": 0,"name": "ap-northeast-3","parameter_groups": {},"parameter_groups_count": 0,"region": "ap-northeast-3","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:ap-northeast-3:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-47b7dd2e": {"arn": "arn:aws:vpc:ap-northeast-3:430150006394:virtual-private-cloud/vpc-47b7dd2e","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-47b7dd2e","instances": {},"instances_count": 0,"name": "vpc-47b7dd2e","snapshots": {},"snapshots_count": 0,"state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"ap-south-1": {"id": "ap-south-1","instances_count": 0,"name": "ap-south-1","parameter_groups": {},"parameter_groups_count": 0,"region": "ap-south-1","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:ap-south-1:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-2651a14d": {"arn": "arn:aws:vpc:ap-south-1:430150006394:virtual-private-cloud/vpc-2651a14d","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-2651a14d","instances": {},"instances_count": 0,"name": "vpc-2651a14d","snapshots": {},"snapshots_count": 0,"state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"ap-southeast-1": {"id": "ap-southeast-1","instances_count": 0,"name": "ap-southeast-1","parameter_groups": {},"parameter_groups_count": 0,"region": "ap-southeast-1","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:ap-southeast-1:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-04ed1062": {"arn": "arn:aws:vpc:ap-southeast-1:430150006394:virtual-private-cloud/vpc-04ed1062","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-04ed1062","instances": {},"instances_count": 0,"name": "vpc-04ed1062","snapshots": {},"snapshots_count": 0,"state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"ap-southeast-2": {"id": "ap-southeast-2","instances_count": 0,"name": "ap-southeast-2","parameter_groups": {},"parameter_groups_count": 0,"region": "ap-southeast-2","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:ap-southeast-2:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-5d22c33b": {"arn": "arn:aws:vpc:ap-southeast-2:430150006394:virtual-private-cloud/vpc-5d22c33b","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-5d22c33b","instances": {},"instances_count": 0,"name": "vpc-5d22c33b","snapshots": {},"snapshots_count": 0,"state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"ca-central-1": {"id": "ca-central-1","instances_count": 0,"name": "ca-central-1","parameter_groups": {},"parameter_groups_count": 0,"region": "ca-central-1","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:ca-central-1:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-b5113ddd": {"arn": "arn:aws:vpc:ca-central-1:430150006394:virtual-private-cloud/vpc-b5113ddd","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-b5113ddd","instances": {},"instances_count": 0,"name": "vpc-b5113ddd","snapshots": {},"snapshots_count": 0,"state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"eu-central-1": {"id": "eu-central-1","instances_count": 0,"name": "eu-central-1","parameter_groups": {},"parameter_groups_count": 0,"region": "eu-central-1","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:eu-central-1:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-78b43312": {"arn": "arn:aws:vpc:eu-central-1:430150006394:virtual-private-cloud/vpc-78b43312","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-78b43312","instances": {},"instances_count": 0,"name": "vpc-78b43312","snapshots": {},"snapshots_count": 0,"state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"eu-north-1": {"id": "eu-north-1","instances_count": 0,"name": "eu-north-1","parameter_groups": {},"parameter_groups_count": 0,"region": "eu-north-1","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:eu-north-1:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-fa259d93": {"arn": "arn:aws:vpc:eu-north-1:430150006394:virtual-private-cloud/vpc-fa259d93","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-fa259d93","instances": {},"instances_count": 0,"name": "vpc-fa259d93","snapshots": {},"snapshots_count": 0,"state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"eu-west-1": {"id": "eu-west-1","instances_count": 0,"name": "eu-west-1","parameter_groups": {},"parameter_groups_count": 0,"region": "eu-west-1","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:eu-west-1:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-f24c7994": {"arn": "arn:aws:vpc:eu-west-1:430150006394:virtual-private-cloud/vpc-f24c7994","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-f24c7994","instances": {},"instances_count": 0,"name": "vpc-f24c7994","snapshots": {},"snapshots_count": 0,"state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"eu-west-2": {"id": "eu-west-2","instances_count": 0,"name": "eu-west-2","parameter_groups": {},"parameter_groups_count": 0,"region": "eu-west-2","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:eu-west-2:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-3fa2fa57": {"arn": "arn:aws:vpc:eu-west-2:430150006394:virtual-private-cloud/vpc-3fa2fa57","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-3fa2fa57","instances": {},"instances_count": 0,"name": "vpc-3fa2fa57","snapshots": {},"snapshots_count": 0,"state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"eu-west-3": {"id": "eu-west-3","instances_count": 0,"name": "eu-west-3","parameter_groups": {},"parameter_groups_count": 0,"region": "eu-west-3","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:eu-west-3:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-87d3fdee": {"arn": "arn:aws:vpc:eu-west-3:430150006394:virtual-private-cloud/vpc-87d3fdee","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-87d3fdee","instances": {},"instances_count": 0,"name": "vpc-87d3fdee","snapshots": {},"snapshots_count": 0,"state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"sa-east-1": {"id": "sa-east-1","instances_count": 0,"name": "sa-east-1","parameter_groups": {},"parameter_groups_count": 0,"region": "sa-east-1","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:sa-east-1:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-b14fa4d7": {"arn": "arn:aws:vpc:sa-east-1:430150006394:virtual-private-cloud/vpc-b14fa4d7","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-b14fa4d7","instances": {},"instances_count": 0,"name": "vpc-b14fa4d7","snapshots": {},"snapshots_count": 0,"state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"us-east-1": {"id": "us-east-1","instances_count": 0,"name": "us-east-1","parameter_groups": {},"parameter_groups_count": 0,"region": "us-east-1","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:us-east-1:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-ba1cbdc7": {"arn": "arn:aws:vpc:us-east-1:430150006394:virtual-private-cloud/vpc-ba1cbdc7","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-ba1cbdc7","instances": {},"instances_count": 0,"name": "vpc-ba1cbdc7","snapshots": {},"snapshots_count": 0,"state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"us-east-2": {"id": "us-east-2","instances_count": 0,"name": "us-east-2","parameter_groups": {},"parameter_groups_count": 0,"region": "us-east-2","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:us-east-2:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-e429ad8f": {"arn": "arn:aws:vpc:us-east-2:430150006394:virtual-private-cloud/vpc-e429ad8f","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-e429ad8f","instances": {},"instances_count": 0,"name": "vpc-e429ad8f","snapshots": {},"snapshots_count": 0,"state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"us-west-1": {"id": "us-west-1","instances_count": 0,"name": "us-west-1","parameter_groups": {},"parameter_groups_count": 0,"region": "us-west-1","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:us-west-1:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-6e6fa508": {"arn": "arn:aws:vpc:us-west-1:430150006394:virtual-private-cloud/vpc-6e6fa508","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-6e6fa508","instances": {},"instances_count": 0,"name": "vpc-6e6fa508","snapshots": {},"snapshots_count": 0,"state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1},"us-west-2": {"id": "us-west-2","instances_count": 0,"name": "us-west-2","parameter_groups": {},"parameter_groups_count": 0,"region": "us-west-2","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:us-west-2:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpcs": {"vpc-d45709ac": {"arn": "arn:aws:vpc:us-west-2:430150006394:virtual-private-cloud/vpc-d45709ac","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-d45709ac","instances": {},"instances_count": 0,"name": "vpc-d45709ac","snapshots": {},"snapshots_count": 0,"state": "available","subnet_groups": {},"subnet_groups_count": 0}},"vpcs_count": 1}},"regions_count": 17,"security_groups_count": 17,"snapshots_count": 0,"subnet_groups_count": 0},"redshift": {"filters": {},"findings": {"redshift-cluster-database-not-encrypted": {"checked_items": 0,"compliance": null,"dashboard_name": "Clusters","description": "Cluster Database Encryption Disabled","flagged_items": 0,"id_suffix": "Encrypted","items": [],"level": "warning","path": "redshift.regions.id.vpcs.id.clusters.id","rationale": "Data-at-rest should be encrypted.","references": ["https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-db-encryption.html"],"remediation": null,"service": "RedShift"},"redshift-cluster-no-version-upgrade": {"checked_items": 0,"compliance": null,"dashboard_name": "Clusters","description": "Version Upgrade Disabled","flagged_items": 0,"id_suffix": "AllowVersionUpgrade","items": [],"level": "danger","path": "redshift.regions.id.vpcs.id.clusters.id","rationale": "Version upgrade is necessary to ensure major version upgrades will be applied automatically to the cluster within the maintenance window.","references": ["https://docs.aws.amazon.com/redshift/latest/APIReference/API_ModifyCluster.html"],"remediation": null,"service": "RedShift"},"redshift-cluster-publicly-accessible": {"checked_items": 0,"compliance": null,"dashboard_name": "Clusters","description": "Cluster Publicly Accessible","flagged_items": 0,"id_suffix": "PubliclyAccessible","items": [],"level": "warning","path": "redshift.regions.id.vpcs.id.clusters.id","rationale": "Redshift clusters should never be public, as this increases the risk of exposing sensitive data. Public accessibility means that other AWS users can access your cluster and the data stored in it.","references": ["https://docs.aws.amazon.com/redshift/latest/gsg/getting-started.html"],"remediation": null,"service": "RedShift"},"redshift-parameter-group-logging-disabled": {"checked_items": 0,"compliance": null,"dashboard_name": "Parameter Groups","description": "User Activity Logging Disabled","flagged_items": 0,"id_suffix": "enable_user_activity_logging","items": [],"level": "warning","path": "redshift.regions.id.parameter_groups.id","rationale": "Audit logging is not enabled by default in Amazon Redshift. A lack of user activity logging could impede the ability to investigate issues involving misuse, malicious access or performance.

Note that this rule will only flag non-default parameter groups, as default parameter groups cannot be modified. It is recommended to use custom groups and configure them according to security best practice.","references": ["https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html"],"remediation": null,"service": "RedShift"},"redshift-parameter-group-ssl-not-required": {"checked_items": 0,"compliance": null,"dashboard_name": "Parameter Groups","description": "SSL Not Required","flagged_items": 0,"id_suffix": "require_ssl","items": [],"level": "danger","path": "redshift.regions.id.parameter_groups.id","rationale": "Parameter groups associated with Redshift clusters should have the \"require_ssl\" parameter enabled, to ensure that data in transit is encrypted.

Note that this rule will only flag non-default parameter groups, as default parameter groups cannot be modified. It is recommended to use custom groups and configure them according to security best practice.","references": ["https://docs.aws.amazon.com/redshift/latest/mgmt/connecting-ssl-support.html"],"remediation": null,"service": "RedShift"},"redshift-security-group-whitelists-all": {"checked_items": 0,"compliance": null,"dashboard_name": "Security Groups","description": "Security Group Allows All Traffic","display_path": "redshift.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "redshift.regions.id.vpcs.id.security_groups.id.IPRanges.id.CIDRIP","rationale": "The security group allows access to Redshift instances from any source address, which creates a wider attack surface for resources assigned to it. Source address restrictions should be implemented","references": null,"remediation": null,"service": "RedShift"}},"parameter_groups_count": 0,"regions": {"ap-northeast-1": {"id": "ap-northeast-1","name": "ap-northeast-1","parameter_groups": {},"parameter_groups_count": 0,"region": "ap-northeast-1","security_groups": {},"security_groups_count": 0,"vpcs": {"vpc-0cbc506a": {"arn": "arn:aws:vpc:ap-northeast-1:430150006394:virtual-private-cloud/vpc-0cbc506a","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-0cbc506a","name": "vpc-0cbc506a","state": "available"}},"vpcs_count": 1},"ap-northeast-2": {"id": "ap-northeast-2","name": "ap-northeast-2","parameter_groups": {},"parameter_groups_count": 0,"region": "ap-northeast-2","security_groups": {},"security_groups_count": 0,"vpcs": {"vpc-73f44e18": {"arn": "arn:aws:vpc:ap-northeast-2:430150006394:virtual-private-cloud/vpc-73f44e18","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-73f44e18","name": "vpc-73f44e18","state": "available"}},"vpcs_count": 1},"ap-northeast-3": {"id": "ap-northeast-3","name": "ap-northeast-3","parameter_groups": {},"parameter_groups_count": 0,"region": "ap-northeast-3","security_groups": {},"security_groups_count": 0,"vpcs": {"vpc-47b7dd2e": {"arn": "arn:aws:vpc:ap-northeast-3:430150006394:virtual-private-cloud/vpc-47b7dd2e","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-47b7dd2e","name": "vpc-47b7dd2e","state": "available"}},"vpcs_count": 1},"ap-south-1": {"id": "ap-south-1","name": "ap-south-1","parameter_groups": {},"parameter_groups_count": 0,"region": "ap-south-1","security_groups": {},"security_groups_count": 0,"vpcs": {"vpc-2651a14d": {"arn": "arn:aws:vpc:ap-south-1:430150006394:virtual-private-cloud/vpc-2651a14d","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-2651a14d","name": "vpc-2651a14d","state": "available"}},"vpcs_count": 1},"ap-southeast-1": {"id": "ap-southeast-1","name": "ap-southeast-1","parameter_groups": {},"parameter_groups_count": 0,"region": "ap-southeast-1","security_groups": {},"security_groups_count": 0,"vpcs": {"vpc-04ed1062": {"arn": "arn:aws:vpc:ap-southeast-1:430150006394:virtual-private-cloud/vpc-04ed1062","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-04ed1062","name": "vpc-04ed1062","state": "available"}},"vpcs_count": 1},"ap-southeast-2": {"id": "ap-southeast-2","name": "ap-southeast-2","parameter_groups": {},"parameter_groups_count": 0,"region": "ap-southeast-2","security_groups": {},"security_groups_count": 0,"vpcs": {"vpc-5d22c33b": {"arn": "arn:aws:vpc:ap-southeast-2:430150006394:virtual-private-cloud/vpc-5d22c33b","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-5d22c33b","name": "vpc-5d22c33b","state": "available"}},"vpcs_count": 1},"ca-central-1": {"id": "ca-central-1","name": "ca-central-1","parameter_groups": {},"parameter_groups_count": 0,"region": "ca-central-1","security_groups": {},"security_groups_count": 0,"vpcs": {"vpc-b5113ddd": {"arn": "arn:aws:vpc:ca-central-1:430150006394:virtual-private-cloud/vpc-b5113ddd","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-b5113ddd","name": "vpc-b5113ddd","state": "available"}},"vpcs_count": 1},"eu-central-1": {"id": "eu-central-1","name": "eu-central-1","parameter_groups": {},"parameter_groups_count": 0,"region": "eu-central-1","security_groups": {},"security_groups_count": 0,"vpcs": {"vpc-78b43312": {"arn": "arn:aws:vpc:eu-central-1:430150006394:virtual-private-cloud/vpc-78b43312","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-78b43312","name": "vpc-78b43312","state": "available"}},"vpcs_count": 1},"eu-north-1": {"id": "eu-north-1","name": "eu-north-1","parameter_groups": {},"parameter_groups_count": 0,"region": "eu-north-1","security_groups": {},"security_groups_count": 0,"vpcs": {"vpc-fa259d93": {"arn": "arn:aws:vpc:eu-north-1:430150006394:virtual-private-cloud/vpc-fa259d93","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-fa259d93","name": "vpc-fa259d93","state": "available"}},"vpcs_count": 1},"eu-west-1": {"id": "eu-west-1","name": "eu-west-1","parameter_groups": {},"parameter_groups_count": 0,"region": "eu-west-1","security_groups": {},"security_groups_count": 0,"vpcs": {"vpc-f24c7994": {"arn": "arn:aws:vpc:eu-west-1:430150006394:virtual-private-cloud/vpc-f24c7994","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-f24c7994","name": "vpc-f24c7994","state": "available"}},"vpcs_count": 1},"eu-west-2": {"id": "eu-west-2","name": "eu-west-2","parameter_groups": {},"parameter_groups_count": 0,"region": "eu-west-2","security_groups": {},"security_groups_count": 0,"vpcs": {"vpc-3fa2fa57": {"arn": "arn:aws:vpc:eu-west-2:430150006394:virtual-private-cloud/vpc-3fa2fa57","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-3fa2fa57","name": "vpc-3fa2fa57","state": "available"}},"vpcs_count": 1},"eu-west-3": {"id": "eu-west-3","name": "eu-west-3","parameter_groups": {},"parameter_groups_count": 0,"region": "eu-west-3","security_groups": {},"security_groups_count": 0,"vpcs": {"vpc-87d3fdee": {"arn": "arn:aws:vpc:eu-west-3:430150006394:virtual-private-cloud/vpc-87d3fdee","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-87d3fdee","name": "vpc-87d3fdee","state": "available"}},"vpcs_count": 1},"sa-east-1": {"id": "sa-east-1","name": "sa-east-1","parameter_groups": {},"parameter_groups_count": 0,"region": "sa-east-1","security_groups": {},"security_groups_count": 0,"vpcs": {"vpc-b14fa4d7": {"arn": "arn:aws:vpc:sa-east-1:430150006394:virtual-private-cloud/vpc-b14fa4d7","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-b14fa4d7","name": "vpc-b14fa4d7","state": "available"}},"vpcs_count": 1},"us-east-1": {"id": "us-east-1","name": "us-east-1","parameter_groups": {},"parameter_groups_count": 0,"region": "us-east-1","security_groups": {},"security_groups_count": 0,"vpcs": {"vpc-ba1cbdc7": {"arn": "arn:aws:vpc:us-east-1:430150006394:virtual-private-cloud/vpc-ba1cbdc7","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-ba1cbdc7","name": "vpc-ba1cbdc7","state": "available"}},"vpcs_count": 1},"us-east-2": {"id": "us-east-2","name": "us-east-2","parameter_groups": {},"parameter_groups_count": 0,"region": "us-east-2","security_groups": {},"security_groups_count": 0,"vpcs": {"vpc-e429ad8f": {"arn": "arn:aws:vpc:us-east-2:430150006394:virtual-private-cloud/vpc-e429ad8f","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-e429ad8f","name": "vpc-e429ad8f","state": "available"}},"vpcs_count": 1},"us-west-1": {"id": "us-west-1","name": "us-west-1","parameter_groups": {},"parameter_groups_count": 0,"region": "us-west-1","security_groups": {},"security_groups_count": 0,"vpcs": {"vpc-6e6fa508": {"arn": "arn:aws:vpc:us-west-1:430150006394:virtual-private-cloud/vpc-6e6fa508","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-6e6fa508","name": "vpc-6e6fa508","state": "available"}},"vpcs_count": 1},"us-west-2": {"id": "us-west-2","name": "us-west-2","parameter_groups": {},"parameter_groups_count": 0,"region": "us-west-2","security_groups": {},"security_groups_count": 0,"vpcs": {"vpc-d45709ac": {"arn": "arn:aws:vpc:us-west-2:430150006394:virtual-private-cloud/vpc-d45709ac","cidr_block": "172.31.0.0/16","clusters": {},"clusters_count": 0,"default": true,"id": "vpc-d45709ac","name": "vpc-d45709ac","state": "available"}},"vpcs_count": 1}},"regions_count": 17,"security_groups_count": 0},"route53": {"domains_count": 0,"filters": {},"findings": {"route53-domain-no-autorenew": {"checked_items": 0,"compliance": null,"dashboard_name": "Domains","description": "Automatic Renewal Not Set for Domain","flagged_items": 0,"id_suffix": "auto_renew","items": [],"level": "danger","path": "route53.regions.id.domains.id","rationale": "Enable automatic renewal to remove the risk of losing control over your domain names.","references": ["https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-enable-disable-auto-renewal.html"],"remediation": null,"service": "Route53"},"route53-domain-no-transferlock": {"checked_items": 0,"compliance": null,"dashboard_name": "Domains","description": "Domain Transfer Not Locked","flagged_items": 0,"id_suffix": "transfer_lock","items": [],"level": "danger","path": "route53.regions.id.domains.id","rationale": "A domain lock prevents someone from transferring your domain to another registrar without your permission.","references": ["https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-lock.html"],"remediation": null,"service": "Route53"},"route53-domain-transferlock-not-authorized": {"checked_items": 0,"compliance": null,"dashboard_name": "Domains","description": "Domain Transfer Lock Not Supported by TLD","flagged_items": 0,"id_suffix": "transfer_lock","items": [],"level": "danger","path": "route53.regions.id.domains.id","rationale": "A domain lock prevents someone from transferring your domain to another registrar without your permission. Your domain's TLD does not support this feature.","references": ["https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/registrar-tld-list.html"],"remediation": null,"service": "Route53"}},"hosted_zones_count": 0,"regions": {"us-east-1": {"domains": {},"domains_count": 0,"hosted_zones": {},"hosted_zones_count": 0,"id": "us-east-1","name": "us-east-1","region": "us-east-1"}},"regions_count": 1},"s3": {"buckets": {"49db3c2810ba973e0a870403be5c8eac6157223c": {"CreationDate": "2020-06-25 05:33:02+00:00","arn": "arn:aws:s3:::wikipedia-bff/*","default_encryption_enabled": false,"grantees": {"a63aba602186926290f04476eec5c7dd1bbce3fd75694d0eec1431b54a978e0e": {"DisplayName": "damien.carol","permissions": {"read": true,"read_acp": true,"write": true,"write_acp": true}}},"groups": {"AGPAIW3P3726RZDVZBZL2": {"inline_policies": {"58cd3df92811df89e93933e00cd5a76813cf6258": {"condition": null}}}},"groups_count": 1,"id": "49db3c2810ba973e0a870403be5c8eac6157223c","logging": "Disabled","name": "wikipedia-bff","public_access_block_configuration": {"BlockPublicAcls": true,"BlockPublicPolicy": true,"IgnorePublicAcls": true,"RestrictPublicBuckets": true},"region": "eu-west-1","roles": {"AROAI265GPNVMDZAKJPPA": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}},"AROAIXBSWIKGEEDLMO53I": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}},"AROAJCHEQKY4NYQFQWP5K": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}},"AROAJCXETX2ROIWUKOPGG": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"AROAWIJXQGZ5OSPI4PBJL": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}},"roles_count": 5,"secure_transport_enabled": false,"version_mfa_delete_enabled": false,"versioning_status_enabled": false,"web_hosting_enabled": false},"5eb65545fecb56b5aad0f2e39ff0adfed160cbd2": {"CreationDate": "2020-06-23 20:19:43+00:00","arn": "arn:aws:s3:::aws-logs-430150006394-eu-west-1/*","default_encryption_enabled": false,"grantees": {"a63aba602186926290f04476eec5c7dd1bbce3fd75694d0eec1431b54a978e0e": {"DisplayName": "damien.carol","permissions": {"read": true,"read_acp": true,"write": true,"write_acp": true}}},"groups": {"AGPAIW3P3726RZDVZBZL2": {"inline_policies": {"58cd3df92811df89e93933e00cd5a76813cf6258": {"condition": null}}}},"groups_count": 1,"id": "5eb65545fecb56b5aad0f2e39ff0adfed160cbd2","logging": "Disabled","name": "aws-logs-430150006394-eu-west-1","public_access_block_configuration": {"BlockPublicAcls": false,"BlockPublicPolicy": false,"IgnorePublicAcls": false,"RestrictPublicBuckets": false},"region": "eu-west-1","roles": {"AROAI265GPNVMDZAKJPPA": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}},"AROAIXBSWIKGEEDLMO53I": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}},"AROAJCHEQKY4NYQFQWP5K": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}},"AROAJCXETX2ROIWUKOPGG": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"AROAWIJXQGZ5OSPI4PBJL": {"policies": {"ANPAZKAPJZG4CAIXDDRI2": {"condition": null}}}},"roles_count": 5,"secure_transport_enabled": false,"version_mfa_delete_enabled": false,"versioning_status_enabled": false,"web_hosting_enabled": false}},"buckets_count": 2,"filters": {"s3-bucket-website-enabled": {"checked_items": 2,"compliance": null,"dashboard_name": "Buckets","description": "Bucket with static website enabled","display_path": "s3.buckets.id","flagged_items": 0,"id_suffix": "web_hosting_enabled","items": [],"level": "","path": "s3.buckets.id","rationale": null,"references": null,"remediation": null,"service": "S3"}},"findings": {"s3-bucket-AllUsers-read": {"checked_items": 2,"compliance": null,"dashboard_name": "Bucket ACLs","description": "Bucket world-listable (anonymous)","display_path": "s3.buckets.id","flagged_items": 0,"id_suffix": "read","items": [],"level": "warning","path": "s3.buckets.id.grantees.id","rationale": "An S3 bucket has been found that was accessible for AllUsers. If sensitive information is stored in this bucket, it could be at risk of being accessed by potential attackers.","references": null,"remediation": null,"service": "S3"},"s3-bucket-AllUsers-read_acp": {"checked_items": 2,"compliance": null,"dashboard_name": "Bucket ACLs","description": "Bucket's permissions world-readable (anonymous)","display_path": "s3.buckets.id","flagged_items": 0,"id_suffix": "read_acp","items": [],"level": "warning","path": "s3.buckets.id.grantees.id","rationale": "An S3 bucket has been found that was accessible for AllUsers. If sensitive information is stored in this bucket, it could be at risk of being accessed by potential attackers.","references": null,"remediation": null,"service": "S3"},"s3-bucket-AllUsers-write": {"checked_items": 2,"compliance": null,"dashboard_name": "Bucket ACLs","description": "Bucket world-writable (anonymous)","display_path": "s3.buckets.id","flagged_items": 0,"id_suffix": "write","items": [],"level": "danger","path": "s3.buckets.id.grantees.id","rationale": "An S3 bucket has been found that was accessible for AllUsers. If sensitive information is stored in this bucket, it could be at risk of being accessed by potential attackers.","references": null,"remediation": null,"service": "S3"},"s3-bucket-AllUsers-write_acp": {"checked_items": 2,"compliance": null,"dashboard_name": "Bucket ACLs","description": "Bucket's permissions world-writable (anonymous)","display_path": "s3.buckets.id","flagged_items": 0,"id_suffix": "write_acp","items": [],"level": "danger","path": "s3.buckets.id.grantees.id","rationale": "An S3 bucket has been found that was accessible for AllUsers. If sensitive information is stored in this bucket, it could be at risk of being accessed by potential attackers.","references": null,"remediation": null,"service": "S3"},"s3-bucket-AuthenticatedUsers-read": {"checked_items": 2,"compliance": null,"dashboard_name": "Bucket ACLs","description": "Bucket world-listable","display_path": "s3.buckets.id","flagged_items": 0,"id_suffix": "read","items": [],"level": "danger","path": "s3.buckets.id.grantees.id","rationale": "An S3 bucket has been found that was accessible for AuthenticatedUsers. If sensitive information is stored in this bucket, it could be at risk of being accessed by potential attackers.","references": null,"remediation": null,"service": "S3"},"s3-bucket-AuthenticatedUsers-read_acp": {"checked_items": 2,"compliance": null,"dashboard_name": "Bucket ACLs","description": "Bucket's permissions world-readable","display_path": "s3.buckets.id","flagged_items": 0,"id_suffix": "read_acp","items": [],"level": "warning","path": "s3.buckets.id.grantees.id","rationale": "An S3 bucket has been found that was accessible for AuthenticatedUsers. If sensitive information is stored in this bucket, it could be at risk of being accessed by potential attackers.","references": null,"remediation": null,"service": "S3"},"s3-bucket-AuthenticatedUsers-write": {"checked_items": 2,"compliance": null,"dashboard_name": "Bucket ACLs","description": "Bucket world-writable","display_path": "s3.buckets.id","flagged_items": 0,"id_suffix": "write","items": [],"level": "danger","path": "s3.buckets.id.grantees.id","rationale": "An S3 bucket has been found that was accessible for AuthenticatedUsers. If sensitive information is stored in this bucket, it could be at risk of being accessed by potential attackers.","references": null,"remediation": null,"service": "S3"},"s3-bucket-AuthenticatedUsers-write_acp": {"checked_items": 2,"compliance": null,"dashboard_name": "Bucket ACLs","description": "Bucket's permissions world-writable","display_path": "s3.buckets.id","flagged_items": 0,"id_suffix": "write_acp","items": [],"level": "danger","path": "s3.buckets.id.grantees.id","rationale": "An S3 bucket has been found that was accessible for AuthenticatedUsers. If sensitive information is stored in this bucket, it could be at risk of being accessed by potential attackers.","references": null,"remediation": null,"service": "S3"},"s3-bucket-allowing-cleartext": {"checked_items": 2,"compliance": null,"dashboard_name": "Buckets","description": "Bucket Allowing Clear Text (HTTP) Communication","flagged_items": 2,"id_suffix": "secure_transport_enabled","items": ["s3.buckets.5eb65545fecb56b5aad0f2e39ff0adfed160cbd2.secure_transport_enabled","s3.buckets.49db3c2810ba973e0a870403be5c8eac6157223c.secure_transport_enabled"],"level": "warning","path": "s3.buckets.id","rationale": "If HTTPS is not enforced on the bucket policy, communication between clients and S3 buckets can use unencrypted HTTP. As a result, sensitive information could be transmitted in clear text over the network|Internet.","references": ["https://docs.aws.amazon.com/AmazonS3/latest/dev/security-best-practices.html"],"remediation": null,"service": "S3"},"s3-bucket-no-default-encryption": {"checked_items": 2,"compliance": null,"dashboard_name": "Buckets","description": "Bucket without Default Encryption Enabled","flagged_items": 2,"id_suffix": "default_encryption_enabled","items": ["s3.buckets.5eb65545fecb56b5aad0f2e39ff0adfed160cbd2.default_encryption_enabled","s3.buckets.49db3c2810ba973e0a870403be5c8eac6157223c.default_encryption_enabled"],"level": "warning","path": "s3.buckets.id","rationale": "Amazon S3 default encryption provides a way to set the default encryption behavior for an S3 bucket. This will ensure data-at-rest is encrypted","references": ["https://docs.aws.amazon.com/AmazonS3/latest/dev/security-best-practices.html","https://docs.aws.amazon.com/AmazonS3/latest/dev/bucket-encryption.html"],"remediation": null,"service": "S3"},"s3-bucket-no-logging": {"checked_items": 2,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "2.6","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "2.6","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "2.6","version": "1.2.0"}],"dashboard_name": "Buckets","description": "Bucket Access Logging Disabled","flagged_items": 2,"id_suffix": "logging","items": ["s3.buckets.5eb65545fecb56b5aad0f2e39ff0adfed160cbd2.logging","s3.buckets.49db3c2810ba973e0a870403be5c8eac6157223c.logging"],"level": "warning","path": "s3.buckets.id","rationale": "Server access logging provides detailed records of the requests that are made to a bucket. Server access logs can assist you in security and access audits, help you learn about your customer base, and understand your Amazon S3 bill.

Note: CloudTrail data events can be used in place of S3 bucket logging. If that is the case, this finding can be considered a false positive.","references": ["https://docs.aws.amazon.com/AmazonS3/latest/dev/security-best-practices.html"],"remediation": "Ensure that S3 buckets have Logging enabled","service": "S3"},"s3-bucket-no-mfa-delete": {"checked_items": 2,"compliance": null,"dashboard_name": "Buckets","description": "Bucket without MFA Delete","flagged_items": 2,"id_suffix": "mfa_delete","items": ["s3.buckets.5eb65545fecb56b5aad0f2e39ff0adfed160cbd2.mfa_delete","s3.buckets.49db3c2810ba973e0a870403be5c8eac6157223c.mfa_delete"],"level": "warning","path": "s3.buckets.id","rationale": "Enable MFA delete to help protect objects from accidental or unauthorized deletion. It should be noted that MFA Delete can only be configured on buckets that have versioning enabled.","references": ["https://docs.aws.amazon.com/AmazonS3/latest/dev/security-best-practices.html"],"remediation": null,"service": "S3"},"s3-bucket-no-versioning": {"checked_items": 2,"compliance": null,"dashboard_name": "Buckets","description": "Bucket without Versioning","flagged_items": 2,"id_suffix": "versioning","items": ["s3.buckets.5eb65545fecb56b5aad0f2e39ff0adfed160cbd2.versioning","s3.buckets.49db3c2810ba973e0a870403be5c8eac6157223c.versioning"],"level": "warning","path": "s3.buckets.id","rationale": "Versioning is a means of keeping multiple variants of an object in the same bucket. With versioning, you can easily recover from both unintended user actions and application failures.","references": ["https://docs.aws.amazon.com/AmazonS3/latest/dev/security-best-practices.html"],"remediation": null,"service": "S3"},"s3-bucket-world-Delete-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Bucket Policy Statements","description": "Delete Actions Authorized to All Principals","display_path": "s3.buckets.id","flagged_items": 0,"items": [],"level": "danger","path": "s3.buckets.id.policy.Statement.id","rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.","references": null,"remediation": null,"service": "S3"},"s3-bucket-world-Get-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Bucket Policy Statements","description": "Get Actions Authorized to All Principals","display_path": "s3.buckets.id","flagged_items": 0,"items": [],"level": "danger","path": "s3.buckets.id.policy.Statement.id","rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.","references": null,"remediation": null,"service": "S3"},"s3-bucket-world-List-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Bucket Policy Statements","description": "List Actions Authorized to All Principals","display_path": "s3.buckets.id","flagged_items": 0,"items": [],"level": "danger","path": "s3.buckets.id.policy.Statement.id","rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.","references": null,"remediation": null,"service": "S3"},"s3-bucket-world-Put-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Bucket Policy Statements","description": "Put Actions Authorized to All Principals","display_path": "s3.buckets.id","flagged_items": 0,"items": [],"level": "danger","path": "s3.buckets.id.policy.Statement.id","rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.","references": null,"remediation": null,"service": "S3"},"s3-bucket-world-policy-star": {"checked_items": 0,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "2.3","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "2.3","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "2.3","version": "1.2.0"}],"dashboard_name": "Bucket Policy Statements","description": "All Actions Authorized to All Principals","display_path": "s3.buckets.id","flagged_items": 0,"items": [],"level": "danger","path": "s3.buckets.id.policy.Statement.id","rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.","references": null,"remediation": "Remove any Statement having an Effect set to Allow and a Principal set to \"*\" or {\"AWS\":\"*\"} in the affected bucket policy","service": "S3"}},"public_access_block_configuration": {"BlockPublicAcls": false,"BlockPublicPolicy": false,"IgnorePublicAcls": false,"RestrictPublicBuckets": false}},"secretsmanager": {"filters": {},"findings": {},"regions": {"ap-northeast-1": {"id": "ap-northeast-1","name": "ap-northeast-1","region": "ap-northeast-1","secrets": {},"secrets_count": 0},"ap-northeast-2": {"id": "ap-northeast-2","name": "ap-northeast-2","region": "ap-northeast-2","secrets": {},"secrets_count": 0},"ap-northeast-3": {"id": "ap-northeast-3","name": "ap-northeast-3","region": "ap-northeast-3","secrets": {},"secrets_count": 0},"ap-south-1": {"id": "ap-south-1","name": "ap-south-1","region": "ap-south-1","secrets": {},"secrets_count": 0},"ap-southeast-1": {"id": "ap-southeast-1","name": "ap-southeast-1","region": "ap-southeast-1","secrets": {},"secrets_count": 0},"ap-southeast-2": {"id": "ap-southeast-2","name": "ap-southeast-2","region": "ap-southeast-2","secrets": {},"secrets_count": 0},"ca-central-1": {"id": "ca-central-1","name": "ca-central-1","region": "ca-central-1","secrets": {},"secrets_count": 0},"eu-central-1": {"id": "eu-central-1","name": "eu-central-1","region": "eu-central-1","secrets": {},"secrets_count": 0},"eu-north-1": {"id": "eu-north-1","name": "eu-north-1","region": "eu-north-1","secrets": {},"secrets_count": 0},"eu-west-1": {"id": "eu-west-1","name": "eu-west-1","region": "eu-west-1","secrets": {},"secrets_count": 0},"eu-west-2": {"id": "eu-west-2","name": "eu-west-2","region": "eu-west-2","secrets": {},"secrets_count": 0},"eu-west-3": {"id": "eu-west-3","name": "eu-west-3","region": "eu-west-3","secrets": {},"secrets_count": 0},"sa-east-1": {"id": "sa-east-1","name": "sa-east-1","region": "sa-east-1","secrets": {},"secrets_count": 0},"us-east-1": {"id": "us-east-1","name": "us-east-1","region": "us-east-1","secrets": {},"secrets_count": 0},"us-east-2": {"id": "us-east-2","name": "us-east-2","region": "us-east-2","secrets": {},"secrets_count": 0},"us-west-1": {"id": "us-west-1","name": "us-west-1","region": "us-west-1","secrets": {},"secrets_count": 0},"us-west-2": {"id": "us-west-2","name": "us-west-2","region": "us-west-2","secrets": {},"secrets_count": 0}},"regions_count": 17,"secrets_count": 0},"ses": {"filters": {},"findings": {"ses-identity-dkim-not-enabled": {"checked_items": 0,"compliance": null,"dashboard_name": "Identities","description": "DKIM Not Enabled","flagged_items": 0,"items": [],"level": "warning","path": "ses.regions.id.identities.id","rationale": "DKIM signing is not enabled for emails sent from the identity.","references": ["https://docs.aws.amazon.com/ses/latest/DeveloperGuide/send-email-authentication-dkim.html"],"remediation": null,"service": "SES"},"ses-identity-dkim-not-verified": {"checked_items": 0,"compliance": null,"dashboard_name": "Identities","description": "DKIM Not Verified","flagged_items": 0,"items": [],"level": "warning","path": "ses.regions.id.identities.id","rationale": "Amazon SES has not verified the DKIM DNS records (tokens) published in the domain name's DNS.","references": ["https://docs.aws.amazon.com/ses/latest/DeveloperGuide/send-email-authentication-dkim.html"],"remediation": null,"service": "SES"},"ses-identity-world-SendEmail-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Statements","description": "SendEmail Authorized to All Principals","display_path": "ses.regions.id.identities.id","flagged_items": 0,"items": [],"level": "danger","path": "ses.regions.id.identities.id.policies.id.Statement.id","rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.","references": null,"remediation": null,"service": "SES"},"ses-identity-world-SendRawEmail-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Statements","description": "SendRawEmail Authorized to All Principals","display_path": "ses.regions.id.identities.id","flagged_items": 0,"items": [],"level": "danger","path": "ses.regions.id.identities.id.policies.id.Statement.id","rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.","references": null,"remediation": null,"service": "SES"}},"identities_count": 0,"regions": {"ap-south-1": {"id": "ap-south-1","identities": {},"identities_count": 0,"name": "ap-south-1","region": "ap-south-1"},"ap-southeast-2": {"id": "ap-southeast-2","identities": {},"identities_count": 0,"name": "ap-southeast-2","region": "ap-southeast-2"},"eu-central-1": {"id": "eu-central-1","identities": {},"identities_count": 0,"name": "eu-central-1","region": "eu-central-1"},"eu-west-1": {"id": "eu-west-1","identities": {},"identities_count": 0,"name": "eu-west-1","region": "eu-west-1"},"us-east-1": {"id": "us-east-1","identities": {},"identities_count": 0,"name": "us-east-1","region": "us-east-1"},"us-west-2": {"id": "us-west-2","identities": {},"identities_count": 0,"name": "us-west-2","region": "us-west-2"}},"regions_count": 6},"sns": {"filters": {},"findings": {"sns-topic-world-AddPermission-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Statements","description": "AddPermission Authorized to All Principals","display_path": "sns.regions.id.topics.id","flagged_items": 0,"items": [],"level": "danger","path": "sns.regions.id.topics.id.Policy.Statement.id","rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.","references": null,"remediation": null,"service": "SNS"},"sns-topic-world-DeleteTopic-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Statements","description": "DeleteTopic Authorized to All Principals","display_path": "sns.regions.id.topics.id","flagged_items": 0,"items": [],"level": "danger","path": "sns.regions.id.topics.id.Policy.Statement.id","rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.","references": null,"remediation": null,"service": "SNS"},"sns-topic-world-Publish-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Statements","description": "Publish Authorized to All Principals","display_path": "sns.regions.id.topics.id","flagged_items": 0,"items": [],"level": "danger","path": "sns.regions.id.topics.id.Policy.Statement.id","rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.","references": null,"remediation": null,"service": "SNS"},"sns-topic-world-Receive-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Statements","description": "Receive Authorized to All Principals","display_path": "sns.regions.id.topics.id","flagged_items": 0,"items": [],"level": "danger","path": "sns.regions.id.topics.id.Policy.Statement.id","rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.","references": null,"remediation": null,"service": "SNS"},"sns-topic-world-RemovePermission-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Statements","description": "RemovePermission Authorized to All Principals","display_path": "sns.regions.id.topics.id","flagged_items": 0,"items": [],"level": "danger","path": "sns.regions.id.topics.id.Policy.Statement.id","rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.","references": null,"remediation": null,"service": "SNS"},"sns-topic-world-SetTopicAttributes-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Statements","description": "SetTopicAttributes Authorized to All Principals","display_path": "sns.regions.id.topics.id","flagged_items": 0,"items": [],"level": "danger","path": "sns.regions.id.topics.id.Policy.Statement.id","rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.","references": null,"remediation": null,"service": "SNS"},"sns-topic-world-Subscribe-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Statements","description": "Subscribe Authorized to All Principals","display_path": "sns.regions.id.topics.id","flagged_items": 0,"items": [],"level": "danger","path": "sns.regions.id.topics.id.Policy.Statement.id","rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.","references": null,"remediation": null,"service": "SNS"}},"regions": {"ap-northeast-1": {"id": "ap-northeast-1","name": "ap-northeast-1","region": "ap-northeast-1","topics": {},"topics_count": 0},"ap-northeast-2": {"id": "ap-northeast-2","name": "ap-northeast-2","region": "ap-northeast-2","topics": {},"topics_count": 0},"ap-northeast-3": {"id": "ap-northeast-3","name": "ap-northeast-3","region": "ap-northeast-3","topics": {},"topics_count": 0},"ap-south-1": {"id": "ap-south-1","name": "ap-south-1","region": "ap-south-1","topics": {},"topics_count": 0},"ap-southeast-1": {"id": "ap-southeast-1","name": "ap-southeast-1","region": "ap-southeast-1","topics": {},"topics_count": 0},"ap-southeast-2": {"id": "ap-southeast-2","name": "ap-southeast-2","region": "ap-southeast-2","topics": {},"topics_count": 0},"ca-central-1": {"id": "ca-central-1","name": "ca-central-1","region": "ca-central-1","topics": {},"topics_count": 0},"eu-central-1": {"id": "eu-central-1","name": "eu-central-1","region": "eu-central-1","topics": {},"topics_count": 0},"eu-north-1": {"id": "eu-north-1","name": "eu-north-1","region": "eu-north-1","topics": {},"topics_count": 0},"eu-west-1": {"id": "eu-west-1","name": "eu-west-1","region": "eu-west-1","topics": {},"topics_count": 0},"eu-west-2": {"id": "eu-west-2","name": "eu-west-2","region": "eu-west-2","topics": {},"topics_count": 0},"eu-west-3": {"id": "eu-west-3","name": "eu-west-3","region": "eu-west-3","topics": {},"topics_count": 0},"sa-east-1": {"id": "sa-east-1","name": "sa-east-1","region": "sa-east-1","topics": {},"topics_count": 0},"us-east-1": {"id": "us-east-1","name": "us-east-1","region": "us-east-1","topics": {},"topics_count": 0},"us-east-2": {"id": "us-east-2","name": "us-east-2","region": "us-east-2","topics": {},"topics_count": 0},"us-west-1": {"id": "us-west-1","name": "us-west-1","region": "us-west-1","topics": {},"topics_count": 0},"us-west-2": {"id": "us-west-2","name": "us-west-2","region": "us-west-2","topics": {},"topics_count": 0}},"regions_count": 17,"topics_count": 0},"sqs": {"filters": {},"findings": {"sqs-queue-world-ChangeMessageVisibility-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Statements","description": "ChangeMessageVisibility Authorized to All Principals","display_path": "sqs.regions.id.queues.id","flagged_items": 0,"items": [],"level": "danger","path": "sqs.regions.id.queues.id.Policy.Statement.id","rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.","references": null,"remediation": null,"service": "SQS"},"sqs-queue-world-DeleteMessage-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Statements","description": "DeleteMessage Authorized to All Principals","display_path": "sqs.regions.id.queues.id","flagged_items": 0,"items": [],"level": "danger","path": "sqs.regions.id.queues.id.Policy.Statement.id","rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.","references": null,"remediation": null,"service": "SQS"},"sqs-queue-world-GetQueueAttributes-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Statements","description": "GetQueueAttributes Authorized to All Principals","display_path": "sqs.regions.id.queues.id","flagged_items": 0,"items": [],"level": "warning","path": "sqs.regions.id.queues.id.Policy.Statement.id","rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.","references": null,"remediation": null,"service": "SQS"},"sqs-queue-world-GetQueueUrl-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Statements","description": "GetQueueUrl Authorized to All Principals","display_path": "sqs.regions.id.queues.id","flagged_items": 0,"items": [],"level": "warning","path": "sqs.regions.id.queues.id.Policy.Statement.id","rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.","references": null,"remediation": null,"service": "SQS"},"sqs-queue-world-PurgeQueue-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Statements","description": "PurgeQueue Authorized to All Principals","display_path": "sqs.regions.id.queues.id","flagged_items": 0,"items": [],"level": "danger","path": "sqs.regions.id.queues.id.Policy.Statement.id","rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.","references": null,"remediation": null,"service": "SQS"},"sqs-queue-world-ReceiveMessage-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Statements","description": "ReceiveMessage Authorized to All Principals","display_path": "sqs.regions.id.queues.id","flagged_items": 0,"items": [],"level": "danger","path": "sqs.regions.id.queues.id.Policy.Statement.id","rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.","references": null,"remediation": null,"service": "SQS"},"sqs-queue-world-SendMessage-policy": {"checked_items": 0,"compliance": null,"dashboard_name": "Statements","description": "SendMessage Authorized to All Principals","display_path": "sqs.regions.id.queues.id","flagged_items": 0,"items": [],"level": "danger","path": "sqs.regions.id.queues.id.Policy.Statement.id","rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.","references": null,"remediation": null,"service": "SQS"}},"queues_count": 0,"regions": {"ap-northeast-1": {"id": "ap-northeast-1","name": "ap-northeast-1","queues": {},"queues_count": 0,"region": "ap-northeast-1"},"ap-northeast-2": {"id": "ap-northeast-2","name": "ap-northeast-2","queues": {},"queues_count": 0,"region": "ap-northeast-2"},"ap-northeast-3": {"id": "ap-northeast-3","name": "ap-northeast-3","queues": {},"queues_count": 0,"region": "ap-northeast-3"},"ap-south-1": {"id": "ap-south-1","name": "ap-south-1","queues": {},"queues_count": 0,"region": "ap-south-1"},"ap-southeast-1": {"id": "ap-southeast-1","name": "ap-southeast-1","queues": {},"queues_count": 0,"region": "ap-southeast-1"},"ap-southeast-2": {"id": "ap-southeast-2","name": "ap-southeast-2","queues": {},"queues_count": 0,"region": "ap-southeast-2"},"ca-central-1": {"id": "ca-central-1","name": "ca-central-1","queues": {},"queues_count": 0,"region": "ca-central-1"},"eu-central-1": {"id": "eu-central-1","name": "eu-central-1","queues": {},"queues_count": 0,"region": "eu-central-1"},"eu-north-1": {"id": "eu-north-1","name": "eu-north-1","queues": {},"queues_count": 0,"region": "eu-north-1"},"eu-west-1": {"id": "eu-west-1","name": "eu-west-1","queues": {},"queues_count": 0,"region": "eu-west-1"},"eu-west-2": {"id": "eu-west-2","name": "eu-west-2","queues": {},"queues_count": 0,"region": "eu-west-2"},"eu-west-3": {"id": "eu-west-3","name": "eu-west-3","queues": {},"queues_count": 0,"region": "eu-west-3"},"sa-east-1": {"id": "sa-east-1","name": "sa-east-1","queues": {},"queues_count": 0,"region": "sa-east-1"},"us-east-1": {"id": "us-east-1","name": "us-east-1","queues": {},"queues_count": 0,"region": "us-east-1"},"us-east-2": {"id": "us-east-2","name": "us-east-2","queues": {},"queues_count": 0,"region": "us-east-2"},"us-west-1": {"id": "us-west-1","name": "us-west-1","queues": {},"queues_count": 0,"region": "us-west-1"},"us-west-2": {"id": "us-west-2","name": "us-west-2","queues": {},"queues_count": 0,"region": "us-west-2"}},"regions_count": 17},"vpc": {"filters": {},"findings": {"vpc-custom-network-acls-allow-all-egress": {"checked_items": 17,"compliance": null,"dashboard_name": "Network ACLs","description": "Network ACLs Allow All egress Traffic (custom)","flagged_items": 0,"id_suffix": "egress._GET_VALUE_AT_(vpc.regions.id.vpcs.id.network_acls.id.allow_all_egress_traffic)","items": [],"level": "warning","path": "vpc.regions.id.vpcs.id.network_acls.id","rationale": "Network ACLs are designed to provide a secondary layer of security. Adding a rule that allows all network traffic (all protocols, IPs, and destination) prior to any deny rule defeats the purpose of network ACLs.","references": null,"remediation": null,"service": "VPC"},"vpc-custom-network-acls-allow-all-ingress": {"checked_items": 17,"compliance": null,"dashboard_name": "Network ACLs","description": "Network ACLs Allow All ingress Traffic (custom)","flagged_items": 0,"id_suffix": "ingress._GET_VALUE_AT_(vpc.regions.id.vpcs.id.network_acls.id.allow_all_ingress_traffic)","items": [],"level": "warning","path": "vpc.regions.id.vpcs.id.network_acls.id","rationale": "Network ACLs are designed to provide a secondary layer of security. Adding a rule that allows all network traffic (all protocols, IPs, and source) prior to any deny rule defeats the purpose of network ACLs.","references": null,"remediation": null,"service": "VPC"},"vpc-default-network-acls-allow-all-egress": {"checked_items": 17,"compliance": null,"dashboard_name": "Network ACLs","description": "Network ACLs Allow All egress Traffic (default)","flagged_items": 17,"id_suffix": "egress._GET_VALUE_AT_(vpc.regions.id.vpcs.id.network_acls.id.allow_all_egress_traffic)","items": ["vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.network_acls.acl-c777e5a1.egress.100","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.network_acls.acl-75e1951e.egress.100","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.network_acls.acl-bb1b62d2.egress.100","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.network_acls.acl-a676adcd.egress.100","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.network_acls.acl-8787e0e1.egress.100","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.network_acls.acl-4e4dc228.egress.100","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.network_acls.acl-63e1ed0b.egress.100","vpc.regions.eu-central-1.vpcs.vpc-78b43312.network_acls.acl-6ebcec04.egress.100","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.network_acls.acl-dfb10ab6.egress.100","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.network_acls.acl-ed4be494.egress.100","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.network_acls.acl-003d0768.egress.100","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.network_acls.acl-c74e7dae.egress.100","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.network_acls.acl-43816e25.egress.100","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.network_acls.acl-f1a6ae8c.egress.100","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.network_acls.acl-b06507db.egress.100","vpc.regions.us-west-1.vpcs.vpc-6e6fa508.network_acls.acl-14a0c772.egress.100","vpc.regions.us-west-2.vpcs.vpc-d45709ac.network_acls.acl-f76adc8c.egress.100"],"level": "warning","path": "vpc.regions.id.vpcs.id.network_acls.id","rationale": "Network ACLs are designed to provide a secondary layer of security. Adding a rule that allows all network traffic (all protocols, IPs, and destination) prior to any deny rule defeats the purpose of network ACLs.","references": null,"remediation": null,"service": "VPC"},"vpc-default-network-acls-allow-all-ingress": {"checked_items": 17,"compliance": null,"dashboard_name": "Network ACLs","description": "Network ACLs Allow All ingress Traffic (default)","flagged_items": 17,"id_suffix": "ingress._GET_VALUE_AT_(vpc.regions.id.vpcs.id.network_acls.id.allow_all_ingress_traffic)","items": ["vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.network_acls.acl-c777e5a1.ingress.100","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.network_acls.acl-75e1951e.ingress.100","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.network_acls.acl-bb1b62d2.ingress.100","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.network_acls.acl-a676adcd.ingress.100","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.network_acls.acl-8787e0e1.ingress.100","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.network_acls.acl-4e4dc228.ingress.100","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.network_acls.acl-63e1ed0b.ingress.100","vpc.regions.eu-central-1.vpcs.vpc-78b43312.network_acls.acl-6ebcec04.ingress.100","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.network_acls.acl-dfb10ab6.ingress.100","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.network_acls.acl-ed4be494.ingress.100","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.network_acls.acl-003d0768.ingress.100","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.network_acls.acl-c74e7dae.ingress.100","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.network_acls.acl-43816e25.ingress.100","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.network_acls.acl-f1a6ae8c.ingress.100","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.network_acls.acl-b06507db.ingress.100","vpc.regions.us-west-1.vpcs.vpc-6e6fa508.network_acls.acl-14a0c772.ingress.100","vpc.regions.us-west-2.vpcs.vpc-d45709ac.network_acls.acl-f76adc8c.ingress.100"],"level": "warning","path": "vpc.regions.id.vpcs.id.network_acls.id","rationale": "Network ACLs are designed to provide a secondary layer of security. Adding a rule that allows all network traffic (all protocols, IPs, and source) prior to any deny rule defeats the purpose of network ACLs.","references": null,"remediation": null,"service": "VPC"},"vpc-network-acl-not-used": {"checked_items": 17,"compliance": null,"dashboard_name": "Network ACLs","description": "Unused Network ACLs","flagged_items": 0,"id_suffix": "unused","items": [],"level": "warning","path": "vpc.regions.id.vpcs.id.network_acls.id","rationale": "Maintaining unused resources increases risks of misconfigurations and increases the difficulty of audits.","references": null,"remediation": null,"service": "VPC"},"vpc-routing-tables-with-peering": {"checked_items": 0,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "4.5","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.4","version": "1.2.0"}],"dashboard_name": "Rulesets","description": "Routing Table with VPC Peering","flagged_items": 0,"id_suffix": "default_with_rules","items": [],"level": "warning","path": "vpc.regions.id.peering_connections.id","rationale": "Being highly selective in peering routing tables minimizes the impact of breach as resources outside of these routes are inaccessible to the peered VPC.","references": null,"remediation": "Ensure route tables contain the least number of subnets or hosts as is required to accomplish the purpose for peering","service": "VPC"},"vpc-subnet-with-allow-all-egress-acls": {"checked_items": 55,"compliance": null,"dashboard_name": "Subnets","description": "Subnet with \"Allow All\" egress NACLs","flagged_items": 55,"id_suffix": "bad_nacls","items": ["vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-7f50e154.bad_nacls","vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-a668c6ee.bad_nacls","vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-593d2502.bad_nacls","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-e6ad198d.bad_nacls","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-af6809d4.bad_nacls","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-8447addb.bad_nacls","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-cf001883.bad_nacls","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-4dcc0924.bad_nacls","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-546a8e2f.bad_nacls","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-c1b6118c.bad_nacls","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-f0fde498.bad_nacls","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-d3c151a8.bad_nacls","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-7d5a1431.bad_nacls","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-2506d06d.bad_nacls","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-a448d5fd.bad_nacls","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-b73197d1.bad_nacls","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-b3fe86eb.bad_nacls","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-0c0bc26a.bad_nacls","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-6cb44e24.bad_nacls","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-1cd98b74.bad_nacls","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-4f896210.bad_nacls","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-85711fff.bad_nacls","vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-ecc66390.bad_nacls","vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-55d77f19.bad_nacls","vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-292d4343.bad_nacls","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-1d972e74.bad_nacls","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-fe16ce85.bad_nacls","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-c98e7484.bad_nacls","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-b3a000e9.bad_nacls","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-b1c2a5d7.bad_nacls","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-214f3969.bad_nacls","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-edaf13a1.bad_nacls","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-e682ec9c.bad_nacls","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-43bf9d2a.bad_nacls","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-b309b8fe.bad_nacls","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-762a450d.bad_nacls","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-e9e1b480.bad_nacls","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-6a4dd723.bad_nacls","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-9aa5c1fc.bad_nacls","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-aaddbef1.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-6e61f24f.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-8c27ffbd.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-30be2f6f.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-77e07411.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-cbefcb86.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-7056187e.bad_nacls","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-fac76891.bad_nacls","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-81a1eccd.bad_nacls","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-18e60365.bad_nacls","vpc.regions.us-west-1.vpcs.vpc-6e6fa508.subnets.subnet-3162b36b.bad_nacls","vpc.regions.us-west-1.vpcs.vpc-6e6fa508.subnets.subnet-64f07402.bad_nacls","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-64dae84f.bad_nacls","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-113ce95b.bad_nacls","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-25f65d5d.bad_nacls","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-1075cf4d.bad_nacls"],"level": "warning","path": "vpc.regions.id.vpcs.id.subnets.id","rationale": "Network ACLs associated with subnets and VPCs should not allow all egress traffic.","references": null,"remediation": null,"service": "VPC"},"vpc-subnet-with-allow-all-ingress-acls": {"checked_items": 55,"compliance": null,"dashboard_name": "Subnets","description": "Subnet with \"Allow All\" ingress NACLs","flagged_items": 55,"id_suffix": "bad_nacls","items": ["vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-7f50e154.bad_nacls","vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-a668c6ee.bad_nacls","vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-593d2502.bad_nacls","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-e6ad198d.bad_nacls","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-af6809d4.bad_nacls","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-8447addb.bad_nacls","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-cf001883.bad_nacls","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-4dcc0924.bad_nacls","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-546a8e2f.bad_nacls","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-c1b6118c.bad_nacls","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-f0fde498.bad_nacls","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-d3c151a8.bad_nacls","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-7d5a1431.bad_nacls","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-2506d06d.bad_nacls","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-a448d5fd.bad_nacls","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-b73197d1.bad_nacls","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-b3fe86eb.bad_nacls","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-0c0bc26a.bad_nacls","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-6cb44e24.bad_nacls","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-1cd98b74.bad_nacls","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-4f896210.bad_nacls","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-85711fff.bad_nacls","vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-ecc66390.bad_nacls","vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-55d77f19.bad_nacls","vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-292d4343.bad_nacls","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-1d972e74.bad_nacls","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-fe16ce85.bad_nacls","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-c98e7484.bad_nacls","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-b3a000e9.bad_nacls","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-b1c2a5d7.bad_nacls","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-214f3969.bad_nacls","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-edaf13a1.bad_nacls","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-e682ec9c.bad_nacls","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-43bf9d2a.bad_nacls","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-b309b8fe.bad_nacls","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-762a450d.bad_nacls","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-e9e1b480.bad_nacls","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-6a4dd723.bad_nacls","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-9aa5c1fc.bad_nacls","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-aaddbef1.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-6e61f24f.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-8c27ffbd.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-30be2f6f.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-77e07411.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-cbefcb86.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-7056187e.bad_nacls","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-fac76891.bad_nacls","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-81a1eccd.bad_nacls","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-18e60365.bad_nacls","vpc.regions.us-west-1.vpcs.vpc-6e6fa508.subnets.subnet-3162b36b.bad_nacls","vpc.regions.us-west-1.vpcs.vpc-6e6fa508.subnets.subnet-64f07402.bad_nacls","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-64dae84f.bad_nacls","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-113ce95b.bad_nacls","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-25f65d5d.bad_nacls","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-1075cf4d.bad_nacls"],"level": "warning","path": "vpc.regions.id.vpcs.id.subnets.id","rationale": "Network ACLs associated with subnets and VPCs should not allow all ingress traffic.","references": null,"remediation": null,"service": "VPC"},"vpc-subnet-without-flow-log": {"checked_items": 55,"compliance": [{"name": "CIS Amazon Web Services Foundations","reference": "4.3","version": "1.0.0"},{"name": "CIS Amazon Web Services Foundations","reference": "4.3","version": "1.1.0"},{"name": "CIS Amazon Web Services Foundations","reference": "2.9","version": "1.2.0"}],"dashboard_name": "Subnets","description": "Subnet without a Flow Log","flagged_items": 55,"id_suffix": "no_flowlog","items": ["vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-7f50e154.no_flowlog","vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-a668c6ee.no_flowlog","vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-593d2502.no_flowlog","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-e6ad198d.no_flowlog","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-af6809d4.no_flowlog","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-8447addb.no_flowlog","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-cf001883.no_flowlog","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-4dcc0924.no_flowlog","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-546a8e2f.no_flowlog","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-c1b6118c.no_flowlog","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-f0fde498.no_flowlog","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-d3c151a8.no_flowlog","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-7d5a1431.no_flowlog","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-2506d06d.no_flowlog","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-a448d5fd.no_flowlog","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-b73197d1.no_flowlog","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-b3fe86eb.no_flowlog","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-0c0bc26a.no_flowlog","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-6cb44e24.no_flowlog","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-1cd98b74.no_flowlog","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-4f896210.no_flowlog","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-85711fff.no_flowlog","vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-ecc66390.no_flowlog","vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-55d77f19.no_flowlog","vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-292d4343.no_flowlog","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-1d972e74.no_flowlog","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-fe16ce85.no_flowlog","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-c98e7484.no_flowlog","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-b3a000e9.no_flowlog","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-b1c2a5d7.no_flowlog","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-214f3969.no_flowlog","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-edaf13a1.no_flowlog","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-e682ec9c.no_flowlog","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-43bf9d2a.no_flowlog","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-b309b8fe.no_flowlog","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-762a450d.no_flowlog","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-e9e1b480.no_flowlog","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-6a4dd723.no_flowlog","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-9aa5c1fc.no_flowlog","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-aaddbef1.no_flowlog","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-6e61f24f.no_flowlog","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-8c27ffbd.no_flowlog","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-30be2f6f.no_flowlog","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-77e07411.no_flowlog","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-cbefcb86.no_flowlog","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-7056187e.no_flowlog","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-fac76891.no_flowlog","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-81a1eccd.no_flowlog","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-18e60365.no_flowlog","vpc.regions.us-west-1.vpcs.vpc-6e6fa508.subnets.subnet-3162b36b.no_flowlog","vpc.regions.us-west-1.vpcs.vpc-6e6fa508.subnets.subnet-64f07402.no_flowlog","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-64dae84f.no_flowlog","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-113ce95b.no_flowlog","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-25f65d5d.no_flowlog","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-1075cf4d.no_flowlog"],"level": "warning","path": "vpc.regions.id.vpcs.id.subnets.id","rationale": "Flow logs enable the investigation of incidents involving unauthorized network traffic, such as an attacker exfiltrating data or pivoting to other hosts.","references": ["https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html"],"remediation": "Create a flow log for each subnet.","service": "VPC"}},"flow_logs_count": 0,"peering_connections_count": 0,"regions": {"ap-northeast-1": {"flow_logs": {},"flow_logs_count": 0,"id": "ap-northeast-1","name": "ap-northeast-1","peering_connections": {},"peering_connections_count": 0,"region": "ap-northeast-1","vpcs": {"vpc-0cbc506a": {"arn": "arn:aws:vpc:ap-northeast-1:430150006394:virtual-private-cloud/vpc-0cbc506a","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-0cbc506a","name": "vpc-0cbc506a","network_acls": {"acl-c777e5a1": {"Associations": [{"NetworkAclAssociationId": "aclassoc-31486e40","NetworkAclId": "acl-c777e5a1","SubnetId": "subnet-a668c6ee"},{"NetworkAclAssociationId": "aclassoc-4e486e3f","NetworkAclId": "acl-c777e5a1","SubnetId": "subnet-7f50e154"},{"NetworkAclAssociationId": "aclassoc-4f486e3e","NetworkAclId": "acl-c777e5a1","SubnetId": "subnet-593d2502"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-0cbc506a","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-c777e5a1","name": "acl-c777e5a1","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"network_acls_count": 1,"state": "available","subnets": {"subnet-593d2502": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-northeast-1c","AvailabilityZoneId": "apne1-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-northeast-1:430150006394:subnet/subnet-593d2502","VpcId": "vpc-0cbc506a","flow_logs": [],"id": "subnet-593d2502","name": "subnet-593d2502","network_acl": "acl-c777e5a1"},"subnet-7f50e154": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-northeast-1d","AvailabilityZoneId": "apne1-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-northeast-1:430150006394:subnet/subnet-7f50e154","VpcId": "vpc-0cbc506a","flow_logs": [],"id": "subnet-7f50e154","name": "subnet-7f50e154","network_acl": "acl-c777e5a1"},"subnet-a668c6ee": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-northeast-1a","AvailabilityZoneId": "apne1-az4","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-northeast-1:430150006394:subnet/subnet-a668c6ee","VpcId": "vpc-0cbc506a","flow_logs": [],"id": "subnet-a668c6ee","name": "subnet-a668c6ee","network_acl": "acl-c777e5a1"}},"subnets_count": 3}},"vpcs_count": 1},"ap-northeast-2": {"flow_logs": {},"flow_logs_count": 0,"id": "ap-northeast-2","name": "ap-northeast-2","peering_connections": {},"peering_connections_count": 0,"region": "ap-northeast-2","vpcs": {"vpc-73f44e18": {"arn": "arn:aws:vpc:ap-northeast-2:430150006394:virtual-private-cloud/vpc-73f44e18","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-73f44e18","name": "vpc-73f44e18","network_acls": {"acl-75e1951e": {"Associations": [{"NetworkAclAssociationId": "aclassoc-37937854","NetworkAclId": "acl-75e1951e","SubnetId": "subnet-e6ad198d"},{"NetworkAclAssociationId": "aclassoc-35937856","NetworkAclId": "acl-75e1951e","SubnetId": "subnet-cf001883"},{"NetworkAclAssociationId": "aclassoc-36937855","NetworkAclId": "acl-75e1951e","SubnetId": "subnet-af6809d4"},{"NetworkAclAssociationId": "aclassoc-34937857","NetworkAclId": "acl-75e1951e","SubnetId": "subnet-8447addb"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-73f44e18","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-75e1951e","name": "acl-75e1951e","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"network_acls_count": 1,"state": "available","subnets": {"subnet-8447addb": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-northeast-2d","AvailabilityZoneId": "apne2-az4","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.48.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-northeast-2:430150006394:subnet/subnet-8447addb","VpcId": "vpc-73f44e18","flow_logs": [],"id": "subnet-8447addb","name": "subnet-8447addb","network_acl": "acl-75e1951e"},"subnet-af6809d4": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-northeast-2b","AvailabilityZoneId": "apne2-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-northeast-2:430150006394:subnet/subnet-af6809d4","VpcId": "vpc-73f44e18","flow_logs": [],"id": "subnet-af6809d4","name": "subnet-af6809d4","network_acl": "acl-75e1951e"},"subnet-cf001883": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-northeast-2c","AvailabilityZoneId": "apne2-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-northeast-2:430150006394:subnet/subnet-cf001883","VpcId": "vpc-73f44e18","flow_logs": [],"id": "subnet-cf001883","name": "subnet-cf001883","network_acl": "acl-75e1951e"},"subnet-e6ad198d": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-northeast-2a","AvailabilityZoneId": "apne2-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-northeast-2:430150006394:subnet/subnet-e6ad198d","VpcId": "vpc-73f44e18","flow_logs": [],"id": "subnet-e6ad198d","name": "subnet-e6ad198d","network_acl": "acl-75e1951e"}},"subnets_count": 4}},"vpcs_count": 1},"ap-northeast-3": {"flow_logs": {},"flow_logs_count": 0,"id": "ap-northeast-3","name": "ap-northeast-3","peering_connections": {},"peering_connections_count": 0,"region": "ap-northeast-3","vpcs": {"vpc-47b7dd2e": {"arn": "arn:aws:vpc:ap-northeast-3:430150006394:virtual-private-cloud/vpc-47b7dd2e","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-47b7dd2e","name": "vpc-47b7dd2e","network_acls": {"acl-bb1b62d2": {"Associations": [{"NetworkAclAssociationId": "aclassoc-1953e271","NetworkAclId": "acl-bb1b62d2","SubnetId": "subnet-c1b6118c"},{"NetworkAclAssociationId": "aclassoc-1853e270","NetworkAclId": "acl-bb1b62d2","SubnetId": "subnet-4dcc0924"},{"NetworkAclAssociationId": "aclassoc-0753e26f","NetworkAclId": "acl-bb1b62d2","SubnetId": "subnet-546a8e2f"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-47b7dd2e","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-bb1b62d2","name": "acl-bb1b62d2","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"network_acls_count": 1,"state": "available","subnets": {"subnet-4dcc0924": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-northeast-3b","AvailabilityZoneId": "apne3-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-northeast-3:430150006394:subnet/subnet-4dcc0924","VpcId": "vpc-47b7dd2e","flow_logs": [],"id": "subnet-4dcc0924","name": "subnet-4dcc0924","network_acl": "acl-bb1b62d2"},"subnet-546a8e2f": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-northeast-3c","AvailabilityZoneId": "apne3-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-northeast-3:430150006394:subnet/subnet-546a8e2f","VpcId": "vpc-47b7dd2e","flow_logs": [],"id": "subnet-546a8e2f","name": "subnet-546a8e2f","network_acl": "acl-bb1b62d2"},"subnet-c1b6118c": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-northeast-3a","AvailabilityZoneId": "apne3-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-northeast-3:430150006394:subnet/subnet-c1b6118c","VpcId": "vpc-47b7dd2e","flow_logs": [],"id": "subnet-c1b6118c","name": "subnet-c1b6118c","network_acl": "acl-bb1b62d2"}},"subnets_count": 3}},"vpcs_count": 1},"ap-south-1": {"flow_logs": {},"flow_logs_count": 0,"id": "ap-south-1","name": "ap-south-1","peering_connections": {},"peering_connections_count": 0,"region": "ap-south-1","vpcs": {"vpc-2651a14d": {"arn": "arn:aws:vpc:ap-south-1:430150006394:virtual-private-cloud/vpc-2651a14d","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-2651a14d","name": "vpc-2651a14d","network_acls": {"acl-a676adcd": {"Associations": [{"NetworkAclAssociationId": "aclassoc-c9d2b0a8","NetworkAclId": "acl-a676adcd","SubnetId": "subnet-d3c151a8"},{"NetworkAclAssociationId": "aclassoc-c6d2b0a7","NetworkAclId": "acl-a676adcd","SubnetId": "subnet-7d5a1431"},{"NetworkAclAssociationId": "aclassoc-c8d2b0a9","NetworkAclId": "acl-a676adcd","SubnetId": "subnet-f0fde498"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-2651a14d","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-a676adcd","name": "acl-a676adcd","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"network_acls_count": 1,"state": "available","subnets": {"subnet-7d5a1431": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-south-1b","AvailabilityZoneId": "aps1-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-south-1:430150006394:subnet/subnet-7d5a1431","VpcId": "vpc-2651a14d","flow_logs": [],"id": "subnet-7d5a1431","name": "subnet-7d5a1431","network_acl": "acl-a676adcd"},"subnet-d3c151a8": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-south-1c","AvailabilityZoneId": "aps1-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-south-1:430150006394:subnet/subnet-d3c151a8","VpcId": "vpc-2651a14d","flow_logs": [],"id": "subnet-d3c151a8","name": "subnet-d3c151a8","network_acl": "acl-a676adcd"},"subnet-f0fde498": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-south-1a","AvailabilityZoneId": "aps1-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-south-1:430150006394:subnet/subnet-f0fde498","VpcId": "vpc-2651a14d","flow_logs": [],"id": "subnet-f0fde498","name": "subnet-f0fde498","network_acl": "acl-a676adcd"}},"subnets_count": 3}},"vpcs_count": 1},"ap-southeast-1": {"flow_logs": {},"flow_logs_count": 0,"id": "ap-southeast-1","name": "ap-southeast-1","peering_connections": {},"peering_connections_count": 0,"region": "ap-southeast-1","vpcs": {"vpc-04ed1062": {"arn": "arn:aws:vpc:ap-southeast-1:430150006394:virtual-private-cloud/vpc-04ed1062","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-04ed1062","name": "vpc-04ed1062","network_acls": {"acl-8787e0e1": {"Associations": [{"NetworkAclAssociationId": "aclassoc-a6b2e6d8","NetworkAclId": "acl-8787e0e1","SubnetId": "subnet-2506d06d"},{"NetworkAclAssociationId": "aclassoc-a8b2e6d6","NetworkAclId": "acl-8787e0e1","SubnetId": "subnet-a448d5fd"},{"NetworkAclAssociationId": "aclassoc-a9b2e6d7","NetworkAclId": "acl-8787e0e1","SubnetId": "subnet-b73197d1"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-04ed1062","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-8787e0e1","name": "acl-8787e0e1","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"network_acls_count": 1,"state": "available","subnets": {"subnet-2506d06d": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-southeast-1a","AvailabilityZoneId": "apse1-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-southeast-1:430150006394:subnet/subnet-2506d06d","VpcId": "vpc-04ed1062","flow_logs": [],"id": "subnet-2506d06d","name": "subnet-2506d06d","network_acl": "acl-8787e0e1"},"subnet-a448d5fd": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-southeast-1c","AvailabilityZoneId": "apse1-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-southeast-1:430150006394:subnet/subnet-a448d5fd","VpcId": "vpc-04ed1062","flow_logs": [],"id": "subnet-a448d5fd","name": "subnet-a448d5fd","network_acl": "acl-8787e0e1"},"subnet-b73197d1": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-southeast-1b","AvailabilityZoneId": "apse1-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-southeast-1:430150006394:subnet/subnet-b73197d1","VpcId": "vpc-04ed1062","flow_logs": [],"id": "subnet-b73197d1","name": "subnet-b73197d1","network_acl": "acl-8787e0e1"}},"subnets_count": 3}},"vpcs_count": 1},"ap-southeast-2": {"flow_logs": {},"flow_logs_count": 0,"id": "ap-southeast-2","name": "ap-southeast-2","peering_connections": {},"peering_connections_count": 0,"region": "ap-southeast-2","vpcs": {"vpc-5d22c33b": {"arn": "arn:aws:vpc:ap-southeast-2:430150006394:virtual-private-cloud/vpc-5d22c33b","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-5d22c33b","name": "vpc-5d22c33b","network_acls": {"acl-4e4dc228": {"Associations": [{"NetworkAclAssociationId": "aclassoc-fdeb7a8d","NetworkAclId": "acl-4e4dc228","SubnetId": "subnet-6cb44e24"},{"NetworkAclAssociationId": "aclassoc-fbeb7a8b","NetworkAclId": "acl-4e4dc228","SubnetId": "subnet-0c0bc26a"},{"NetworkAclAssociationId": "aclassoc-fceb7a8c","NetworkAclId": "acl-4e4dc228","SubnetId": "subnet-b3fe86eb"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-5d22c33b","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-4e4dc228","name": "acl-4e4dc228","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"network_acls_count": 1,"state": "available","subnets": {"subnet-0c0bc26a": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-southeast-2b","AvailabilityZoneId": "apse2-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-southeast-2:430150006394:subnet/subnet-0c0bc26a","VpcId": "vpc-5d22c33b","flow_logs": [],"id": "subnet-0c0bc26a","name": "subnet-0c0bc26a","network_acl": "acl-4e4dc228"},"subnet-6cb44e24": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-southeast-2a","AvailabilityZoneId": "apse2-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-southeast-2:430150006394:subnet/subnet-6cb44e24","VpcId": "vpc-5d22c33b","flow_logs": [],"id": "subnet-6cb44e24","name": "subnet-6cb44e24","network_acl": "acl-4e4dc228"},"subnet-b3fe86eb": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-southeast-2c","AvailabilityZoneId": "apse2-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-southeast-2:430150006394:subnet/subnet-b3fe86eb","VpcId": "vpc-5d22c33b","flow_logs": [],"id": "subnet-b3fe86eb","name": "subnet-b3fe86eb","network_acl": "acl-4e4dc228"}},"subnets_count": 3}},"vpcs_count": 1},"ca-central-1": {"flow_logs": {},"flow_logs_count": 0,"id": "ca-central-1","name": "ca-central-1","peering_connections": {},"peering_connections_count": 0,"region": "ca-central-1","vpcs": {"vpc-b5113ddd": {"arn": "arn:aws:vpc:ca-central-1:430150006394:virtual-private-cloud/vpc-b5113ddd","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-b5113ddd","name": "vpc-b5113ddd","network_acls": {"acl-63e1ed0b": {"Associations": [{"NetworkAclAssociationId": "aclassoc-31d33c50","NetworkAclId": "acl-63e1ed0b","SubnetId": "subnet-85711fff"},{"NetworkAclAssociationId": "aclassoc-33d33c52","NetworkAclId": "acl-63e1ed0b","SubnetId": "subnet-4f896210"},{"NetworkAclAssociationId": "aclassoc-30d33c51","NetworkAclId": "acl-63e1ed0b","SubnetId": "subnet-1cd98b74"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-b5113ddd","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-63e1ed0b","name": "acl-63e1ed0b","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"network_acls_count": 1,"state": "available","subnets": {"subnet-1cd98b74": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ca-central-1a","AvailabilityZoneId": "cac1-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ca-central-1:430150006394:subnet/subnet-1cd98b74","VpcId": "vpc-b5113ddd","flow_logs": [],"id": "subnet-1cd98b74","name": "subnet-1cd98b74","network_acl": "acl-63e1ed0b"},"subnet-4f896210": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ca-central-1d","AvailabilityZoneId": "cac1-az4","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ca-central-1:430150006394:subnet/subnet-4f896210","VpcId": "vpc-b5113ddd","flow_logs": [],"id": "subnet-4f896210","name": "subnet-4f896210","network_acl": "acl-63e1ed0b"},"subnet-85711fff": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ca-central-1b","AvailabilityZoneId": "cac1-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ca-central-1:430150006394:subnet/subnet-85711fff","VpcId": "vpc-b5113ddd","flow_logs": [],"id": "subnet-85711fff","name": "subnet-85711fff","network_acl": "acl-63e1ed0b"}},"subnets_count": 3}},"vpcs_count": 1},"eu-central-1": {"flow_logs": {},"flow_logs_count": 0,"id": "eu-central-1","name": "eu-central-1","peering_connections": {},"peering_connections_count": 0,"region": "eu-central-1","vpcs": {"vpc-78b43312": {"arn": "arn:aws:vpc:eu-central-1:430150006394:virtual-private-cloud/vpc-78b43312","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-78b43312","name": "vpc-78b43312","network_acls": {"acl-6ebcec04": {"Associations": [{"NetworkAclAssociationId": "aclassoc-36773353","NetworkAclId": "acl-6ebcec04","SubnetId": "subnet-55d77f19"},{"NetworkAclAssociationId": "aclassoc-31773354","NetworkAclId": "acl-6ebcec04","SubnetId": "subnet-292d4343"},{"NetworkAclAssociationId": "aclassoc-30773355","NetworkAclId": "acl-6ebcec04","SubnetId": "subnet-ecc66390"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-78b43312","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-6ebcec04","name": "acl-6ebcec04","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"network_acls_count": 1,"state": "available","subnets": {"subnet-292d4343": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-central-1a","AvailabilityZoneId": "euc1-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-central-1:430150006394:subnet/subnet-292d4343","VpcId": "vpc-78b43312","flow_logs": [],"id": "subnet-292d4343","name": "subnet-292d4343","network_acl": "acl-6ebcec04"},"subnet-55d77f19": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-central-1c","AvailabilityZoneId": "euc1-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-central-1:430150006394:subnet/subnet-55d77f19","VpcId": "vpc-78b43312","flow_logs": [],"id": "subnet-55d77f19","name": "subnet-55d77f19","network_acl": "acl-6ebcec04"},"subnet-ecc66390": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-central-1b","AvailabilityZoneId": "euc1-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-central-1:430150006394:subnet/subnet-ecc66390","VpcId": "vpc-78b43312","flow_logs": [],"id": "subnet-ecc66390","name": "subnet-ecc66390","network_acl": "acl-6ebcec04"}},"subnets_count": 3}},"vpcs_count": 1},"eu-north-1": {"flow_logs": {},"flow_logs_count": 0,"id": "eu-north-1","name": "eu-north-1","peering_connections": {},"peering_connections_count": 0,"region": "eu-north-1","vpcs": {"vpc-fa259d93": {"arn": "arn:aws:vpc:eu-north-1:430150006394:virtual-private-cloud/vpc-fa259d93","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-fa259d93","name": "vpc-fa259d93","network_acls": {"acl-dfb10ab6": {"Associations": [{"NetworkAclAssociationId": "aclassoc-8ed1b4e3","NetworkAclId": "acl-dfb10ab6","SubnetId": "subnet-1d972e74"},{"NetworkAclAssociationId": "aclassoc-89d1b4e4","NetworkAclId": "acl-dfb10ab6","SubnetId": "subnet-fe16ce85"},{"NetworkAclAssociationId": "aclassoc-8fd1b4e2","NetworkAclId": "acl-dfb10ab6","SubnetId": "subnet-c98e7484"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-fa259d93","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-dfb10ab6","name": "acl-dfb10ab6","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"network_acls_count": 1,"state": "available","subnets": {"subnet-1d972e74": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-north-1a","AvailabilityZoneId": "eun1-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-north-1:430150006394:subnet/subnet-1d972e74","VpcId": "vpc-fa259d93","flow_logs": [],"id": "subnet-1d972e74","name": "subnet-1d972e74","network_acl": "acl-dfb10ab6"},"subnet-c98e7484": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-north-1c","AvailabilityZoneId": "eun1-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-north-1:430150006394:subnet/subnet-c98e7484","VpcId": "vpc-fa259d93","flow_logs": [],"id": "subnet-c98e7484","name": "subnet-c98e7484","network_acl": "acl-dfb10ab6"},"subnet-fe16ce85": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-north-1b","AvailabilityZoneId": "eun1-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-north-1:430150006394:subnet/subnet-fe16ce85","VpcId": "vpc-fa259d93","flow_logs": [],"id": "subnet-fe16ce85","name": "subnet-fe16ce85","network_acl": "acl-dfb10ab6"}},"subnets_count": 3}},"vpcs_count": 1},"eu-west-1": {"flow_logs": {},"flow_logs_count": 0,"id": "eu-west-1","name": "eu-west-1","peering_connections": {},"peering_connections_count": 0,"region": "eu-west-1","vpcs": {"vpc-f24c7994": {"arn": "arn:aws:vpc:eu-west-1:430150006394:virtual-private-cloud/vpc-f24c7994","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-f24c7994","name": "vpc-f24c7994","network_acls": {"acl-ed4be494": {"Associations": [{"NetworkAclAssociationId": "aclassoc-5a508624","NetworkAclId": "acl-ed4be494","SubnetId": "subnet-b3a000e9"},{"NetworkAclAssociationId": "aclassoc-5d508623","NetworkAclId": "acl-ed4be494","SubnetId": "subnet-214f3969"},{"NetworkAclAssociationId": "aclassoc-5c508622","NetworkAclId": "acl-ed4be494","SubnetId": "subnet-b1c2a5d7"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-f24c7994","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-ed4be494","name": "acl-ed4be494","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"network_acls_count": 1,"state": "available","subnets": {"subnet-214f3969": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-west-1a","AvailabilityZoneId": "euw1-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-west-1:430150006394:subnet/subnet-214f3969","VpcId": "vpc-f24c7994","flow_logs": [],"id": "subnet-214f3969","name": "subnet-214f3969","network_acl": "acl-ed4be494"},"subnet-b1c2a5d7": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-west-1c","AvailabilityZoneId": "euw1-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-west-1:430150006394:subnet/subnet-b1c2a5d7","VpcId": "vpc-f24c7994","flow_logs": [],"id": "subnet-b1c2a5d7","name": "subnet-b1c2a5d7","network_acl": "acl-ed4be494"},"subnet-b3a000e9": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-west-1b","AvailabilityZoneId": "euw1-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-west-1:430150006394:subnet/subnet-b3a000e9","VpcId": "vpc-f24c7994","flow_logs": [],"id": "subnet-b3a000e9","name": "subnet-b3a000e9","network_acl": "acl-ed4be494"}},"subnets_count": 3}},"vpcs_count": 1},"eu-west-2": {"flow_logs": {},"flow_logs_count": 0,"id": "eu-west-2","name": "eu-west-2","peering_connections": {},"peering_connections_count": 0,"region": "eu-west-2","vpcs": {"vpc-3fa2fa57": {"arn": "arn:aws:vpc:eu-west-2:430150006394:virtual-private-cloud/vpc-3fa2fa57","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-3fa2fa57","name": "vpc-3fa2fa57","network_acls": {"acl-003d0768": {"Associations": [{"NetworkAclAssociationId": "aclassoc-e73eff86","NetworkAclId": "acl-003d0768","SubnetId": "subnet-43bf9d2a"},{"NetworkAclAssociationId": "aclassoc-e93eff88","NetworkAclId": "acl-003d0768","SubnetId": "subnet-edaf13a1"},{"NetworkAclAssociationId": "aclassoc-e63eff87","NetworkAclId": "acl-003d0768","SubnetId": "subnet-e682ec9c"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-3fa2fa57","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-003d0768","name": "acl-003d0768","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"network_acls_count": 1,"state": "available","subnets": {"subnet-43bf9d2a": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-west-2c","AvailabilityZoneId": "euw2-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-west-2:430150006394:subnet/subnet-43bf9d2a","VpcId": "vpc-3fa2fa57","flow_logs": [],"id": "subnet-43bf9d2a","name": "subnet-43bf9d2a","network_acl": "acl-003d0768"},"subnet-e682ec9c": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-west-2a","AvailabilityZoneId": "euw2-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-west-2:430150006394:subnet/subnet-e682ec9c","VpcId": "vpc-3fa2fa57","flow_logs": [],"id": "subnet-e682ec9c","name": "subnet-e682ec9c","network_acl": "acl-003d0768"},"subnet-edaf13a1": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-west-2b","AvailabilityZoneId": "euw2-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-west-2:430150006394:subnet/subnet-edaf13a1","VpcId": "vpc-3fa2fa57","flow_logs": [],"id": "subnet-edaf13a1","name": "subnet-edaf13a1","network_acl": "acl-003d0768"}},"subnets_count": 3}},"vpcs_count": 1},"eu-west-3": {"flow_logs": {},"flow_logs_count": 0,"id": "eu-west-3","name": "eu-west-3","peering_connections": {},"peering_connections_count": 0,"region": "eu-west-3","vpcs": {"vpc-87d3fdee": {"arn": "arn:aws:vpc:eu-west-3:430150006394:virtual-private-cloud/vpc-87d3fdee","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-87d3fdee","name": "vpc-87d3fdee","network_acls": {"acl-c74e7dae": {"Associations": [{"NetworkAclAssociationId": "aclassoc-de1211b6","NetworkAclId": "acl-c74e7dae","SubnetId": "subnet-762a450d"},{"NetworkAclAssociationId": "aclassoc-dd1211b5","NetworkAclId": "acl-c74e7dae","SubnetId": "subnet-e9e1b480"},{"NetworkAclAssociationId": "aclassoc-df1211b7","NetworkAclId": "acl-c74e7dae","SubnetId": "subnet-b309b8fe"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-87d3fdee","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-c74e7dae","name": "acl-c74e7dae","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"network_acls_count": 1,"state": "available","subnets": {"subnet-762a450d": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-west-3b","AvailabilityZoneId": "euw3-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-west-3:430150006394:subnet/subnet-762a450d","VpcId": "vpc-87d3fdee","flow_logs": [],"id": "subnet-762a450d","name": "subnet-762a450d","network_acl": "acl-c74e7dae"},"subnet-b309b8fe": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-west-3c","AvailabilityZoneId": "euw3-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-west-3:430150006394:subnet/subnet-b309b8fe","VpcId": "vpc-87d3fdee","flow_logs": [],"id": "subnet-b309b8fe","name": "subnet-b309b8fe","network_acl": "acl-c74e7dae"},"subnet-e9e1b480": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-west-3a","AvailabilityZoneId": "euw3-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-west-3:430150006394:subnet/subnet-e9e1b480","VpcId": "vpc-87d3fdee","flow_logs": [],"id": "subnet-e9e1b480","name": "subnet-e9e1b480","network_acl": "acl-c74e7dae"}},"subnets_count": 3}},"vpcs_count": 1},"sa-east-1": {"flow_logs": {},"flow_logs_count": 0,"id": "sa-east-1","name": "sa-east-1","peering_connections": {},"peering_connections_count": 0,"region": "sa-east-1","vpcs": {"vpc-b14fa4d7": {"arn": "arn:aws:vpc:sa-east-1:430150006394:virtual-private-cloud/vpc-b14fa4d7","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-b14fa4d7","name": "vpc-b14fa4d7","network_acls": {"acl-43816e25": {"Associations": [{"NetworkAclAssociationId": "aclassoc-7477890a","NetworkAclId": "acl-43816e25","SubnetId": "subnet-9aa5c1fc"},{"NetworkAclAssociationId": "aclassoc-7277890c","NetworkAclId": "acl-43816e25","SubnetId": "subnet-aaddbef1"},{"NetworkAclAssociationId": "aclassoc-7577890b","NetworkAclId": "acl-43816e25","SubnetId": "subnet-6a4dd723"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-b14fa4d7","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-43816e25","name": "acl-43816e25","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"network_acls_count": 1,"state": "available","subnets": {"subnet-6a4dd723": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "sa-east-1b","AvailabilityZoneId": "sae1-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:sa-east-1:430150006394:subnet/subnet-6a4dd723","VpcId": "vpc-b14fa4d7","flow_logs": [],"id": "subnet-6a4dd723","name": "subnet-6a4dd723","network_acl": "acl-43816e25"},"subnet-9aa5c1fc": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "sa-east-1a","AvailabilityZoneId": "sae1-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:sa-east-1:430150006394:subnet/subnet-9aa5c1fc","VpcId": "vpc-b14fa4d7","flow_logs": [],"id": "subnet-9aa5c1fc","name": "subnet-9aa5c1fc","network_acl": "acl-43816e25"},"subnet-aaddbef1": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "sa-east-1c","AvailabilityZoneId": "sae1-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:sa-east-1:430150006394:subnet/subnet-aaddbef1","VpcId": "vpc-b14fa4d7","flow_logs": [],"id": "subnet-aaddbef1","name": "subnet-aaddbef1","network_acl": "acl-43816e25"}},"subnets_count": 3}},"vpcs_count": 1},"us-east-1": {"flow_logs": {},"flow_logs_count": 0,"id": "us-east-1","name": "us-east-1","peering_connections": {},"peering_connections_count": 0,"region": "us-east-1","vpcs": {"vpc-ba1cbdc7": {"arn": "arn:aws:vpc:us-east-1:430150006394:virtual-private-cloud/vpc-ba1cbdc7","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-ba1cbdc7","name": "vpc-ba1cbdc7","network_acls": {"acl-f1a6ae8c": {"Associations": [{"NetworkAclAssociationId": "aclassoc-ad34c3ff","NetworkAclId": "acl-f1a6ae8c","SubnetId": "subnet-7056187e"},{"NetworkAclAssociationId": "aclassoc-af34c3fd","NetworkAclId": "acl-f1a6ae8c","SubnetId": "subnet-30be2f6f"},{"NetworkAclAssociationId": "aclassoc-ac34c3fe","NetworkAclId": "acl-f1a6ae8c","SubnetId": "subnet-8c27ffbd"},{"NetworkAclAssociationId": "aclassoc-5233c400","NetworkAclId": "acl-f1a6ae8c","SubnetId": "subnet-6e61f24f"},{"NetworkAclAssociationId": "aclassoc-ae34c3fc","NetworkAclId": "acl-f1a6ae8c","SubnetId": "subnet-cbefcb86"},{"NetworkAclAssociationId": "aclassoc-a934c3fb","NetworkAclId": "acl-f1a6ae8c","SubnetId": "subnet-77e07411"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-ba1cbdc7","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-f1a6ae8c","name": "acl-f1a6ae8c","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"network_acls_count": 1,"state": "available","subnets": {"subnet-30be2f6f": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-east-1c","AvailabilityZoneId": "use1-az6","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-east-1:430150006394:subnet/subnet-30be2f6f","VpcId": "vpc-ba1cbdc7","flow_logs": [],"id": "subnet-30be2f6f","name": "subnet-30be2f6f","network_acl": "acl-f1a6ae8c"},"subnet-6e61f24f": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-east-1a","AvailabilityZoneId": "use1-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.80.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-east-1:430150006394:subnet/subnet-6e61f24f","VpcId": "vpc-ba1cbdc7","flow_logs": [],"id": "subnet-6e61f24f","name": "subnet-6e61f24f","network_acl": "acl-f1a6ae8c"},"subnet-7056187e": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-east-1f","AvailabilityZoneId": "use1-az5","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.64.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-east-1:430150006394:subnet/subnet-7056187e","VpcId": "vpc-ba1cbdc7","flow_logs": [],"id": "subnet-7056187e","name": "subnet-7056187e","network_acl": "acl-f1a6ae8c"},"subnet-77e07411": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-east-1d","AvailabilityZoneId": "use1-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-east-1:430150006394:subnet/subnet-77e07411","VpcId": "vpc-ba1cbdc7","flow_logs": [],"id": "subnet-77e07411","name": "subnet-77e07411","network_acl": "acl-f1a6ae8c"},"subnet-8c27ffbd": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-east-1e","AvailabilityZoneId": "use1-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.48.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-east-1:430150006394:subnet/subnet-8c27ffbd","VpcId": "vpc-ba1cbdc7","flow_logs": [],"id": "subnet-8c27ffbd","name": "subnet-8c27ffbd","network_acl": "acl-f1a6ae8c"},"subnet-cbefcb86": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-east-1b","AvailabilityZoneId": "use1-az4","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-east-1:430150006394:subnet/subnet-cbefcb86","VpcId": "vpc-ba1cbdc7","flow_logs": [],"id": "subnet-cbefcb86","name": "subnet-cbefcb86","network_acl": "acl-f1a6ae8c"}},"subnets_count": 6}},"vpcs_count": 1},"us-east-2": {"flow_logs": {},"flow_logs_count": 0,"id": "us-east-2","name": "us-east-2","peering_connections": {},"peering_connections_count": 0,"region": "us-east-2","vpcs": {"vpc-e429ad8f": {"arn": "arn:aws:vpc:us-east-2:430150006394:virtual-private-cloud/vpc-e429ad8f","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-e429ad8f","name": "vpc-e429ad8f","network_acls": {"acl-b06507db": {"Associations": [{"NetworkAclAssociationId": "aclassoc-164f9a74","NetworkAclId": "acl-b06507db","SubnetId": "subnet-81a1eccd"},{"NetworkAclAssociationId": "aclassoc-114f9a73","NetworkAclId": "acl-b06507db","SubnetId": "subnet-18e60365"},{"NetworkAclAssociationId": "aclassoc-104f9a72","NetworkAclId": "acl-b06507db","SubnetId": "subnet-fac76891"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-e429ad8f","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-b06507db","name": "acl-b06507db","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"network_acls_count": 1,"state": "available","subnets": {"subnet-18e60365": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-east-2b","AvailabilityZoneId": "use2-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-east-2:430150006394:subnet/subnet-18e60365","VpcId": "vpc-e429ad8f","flow_logs": [],"id": "subnet-18e60365","name": "subnet-18e60365","network_acl": "acl-b06507db"},"subnet-81a1eccd": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-east-2c","AvailabilityZoneId": "use2-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-east-2:430150006394:subnet/subnet-81a1eccd","VpcId": "vpc-e429ad8f","flow_logs": [],"id": "subnet-81a1eccd","name": "subnet-81a1eccd","network_acl": "acl-b06507db"},"subnet-fac76891": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-east-2a","AvailabilityZoneId": "use2-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-east-2:430150006394:subnet/subnet-fac76891","VpcId": "vpc-e429ad8f","flow_logs": [],"id": "subnet-fac76891","name": "subnet-fac76891","network_acl": "acl-b06507db"}},"subnets_count": 3}},"vpcs_count": 1},"us-west-1": {"flow_logs": {},"flow_logs_count": 0,"id": "us-west-1","name": "us-west-1","peering_connections": {},"peering_connections_count": 0,"region": "us-west-1","vpcs": {"vpc-6e6fa508": {"arn": "arn:aws:vpc:us-west-1:430150006394:virtual-private-cloud/vpc-6e6fa508","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-6e6fa508","name": "vpc-6e6fa508","network_acls": {"acl-14a0c772": {"Associations": [{"NetworkAclAssociationId": "aclassoc-a9f7b7d5","NetworkAclId": "acl-14a0c772","SubnetId": "subnet-64f07402"},{"NetworkAclAssociationId": "aclassoc-a8f7b7d4","NetworkAclId": "acl-14a0c772","SubnetId": "subnet-3162b36b"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-6e6fa508","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-14a0c772","name": "acl-14a0c772","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"network_acls_count": 1,"state": "available","subnets": {"subnet-3162b36b": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-west-1c","AvailabilityZoneId": "usw1-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-west-1:430150006394:subnet/subnet-3162b36b","VpcId": "vpc-6e6fa508","flow_logs": [],"id": "subnet-3162b36b","name": "subnet-3162b36b","network_acl": "acl-14a0c772"},"subnet-64f07402": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-west-1a","AvailabilityZoneId": "usw1-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-west-1:430150006394:subnet/subnet-64f07402","VpcId": "vpc-6e6fa508","flow_logs": [],"id": "subnet-64f07402","name": "subnet-64f07402","network_acl": "acl-14a0c772"}},"subnets_count": 2}},"vpcs_count": 1},"us-west-2": {"flow_logs": {},"flow_logs_count": 0,"id": "us-west-2","name": "us-west-2","peering_connections": {},"peering_connections_count": 0,"region": "us-west-2","vpcs": {"vpc-d45709ac": {"arn": "arn:aws:vpc:us-west-2:430150006394:virtual-private-cloud/vpc-d45709ac","cidr_block": "172.31.0.0/16","default": true,"id": "vpc-d45709ac","name": "vpc-d45709ac","network_acls": {"acl-f76adc8c": {"Associations": [{"NetworkAclAssociationId": "aclassoc-5edb3d1c","NetworkAclId": "acl-f76adc8c","SubnetId": "subnet-1075cf4d"},{"NetworkAclAssociationId": "aclassoc-5ddb3d1f","NetworkAclId": "acl-f76adc8c","SubnetId": "subnet-64dae84f"},{"NetworkAclAssociationId": "aclassoc-5fdb3d1d","NetworkAclId": "acl-f76adc8c","SubnetId": "subnet-25f65d5d"},{"NetworkAclAssociationId": "aclassoc-5cdb3d1e","NetworkAclId": "acl-f76adc8c","SubnetId": "subnet-113ce95b"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-d45709ac","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-f76adc8c","name": "acl-f76adc8c","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"network_acls_count": 1,"state": "available","subnets": {"subnet-1075cf4d": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-west-2c","AvailabilityZoneId": "usw2-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-west-2:430150006394:subnet/subnet-1075cf4d","VpcId": "vpc-d45709ac","flow_logs": [],"id": "subnet-1075cf4d","name": "subnet-1075cf4d","network_acl": "acl-f76adc8c"},"subnet-113ce95b": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-west-2b","AvailabilityZoneId": "usw2-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-west-2:430150006394:subnet/subnet-113ce95b","VpcId": "vpc-d45709ac","flow_logs": [],"id": "subnet-113ce95b","name": "subnet-113ce95b","network_acl": "acl-f76adc8c"},"subnet-25f65d5d": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-west-2a","AvailabilityZoneId": "usw2-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-west-2:430150006394:subnet/subnet-25f65d5d","VpcId": "vpc-d45709ac","flow_logs": [],"id": "subnet-25f65d5d","name": "subnet-25f65d5d","network_acl": "acl-f76adc8c"},"subnet-64dae84f": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-west-2d","AvailabilityZoneId": "usw2-az4","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.48.0/20","CidrBlockv6": null,"DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-west-2:430150006394:subnet/subnet-64dae84f","VpcId": "vpc-d45709ac","flow_logs": [],"id": "subnet-64dae84f","name": "subnet-64dae84f","network_acl": "acl-f76adc8c"}},"subnets_count": 4}},"vpcs_count": 1}},"regions_count": 17}},"sg_map": {"sg-000c4c21c24f75b85": {"region": "eu-west-3","vpc_id": "vpc-87d3fdee"},"sg-02063087593480392": {"region": "eu-west-1","vpc_id": "vpc-f24c7994"},"sg-09c1e96a": {"region": "eu-north-1","vpc_id": "vpc-fa259d93"},"sg-0c59ae38c42100171": {"region": "eu-west-1","vpc_id": "vpc-f24c7994"},"sg-186a6a69": {"region": "eu-west-1","vpc_id": "vpc-f24c7994"},"sg-223b755a": {"region": "eu-west-2","vpc_id": "vpc-3fa2fa57"},"sg-3965844c": {"region": "sa-east-1","vpc_id": "vpc-b14fa4d7"},"sg-3e983346": {"region": "ap-south-1","vpc_id": "vpc-2651a14d"},"sg-4574a94e": {"region": "us-east-1","vpc_id": "vpc-ba1cbdc7"},"sg-4cc9d827": {"region": "eu-west-3","vpc_id": "vpc-87d3fdee"},"sg-62215504": {"region": "ca-central-1","vpc_id": "vpc-b5113ddd"},"sg-6569b32b": {"region": "ap-northeast-1","vpc_id": "vpc-0cbc506a"},"sg-71eb4839": {"region": "ap-southeast-1","vpc_id": "vpc-04ed1062"},"sg-778f4e3e": {"region": "us-west-1","vpc_id": "vpc-6e6fa508"},"sg-854e9bfe": {"region": "ap-northeast-2","vpc_id": "vpc-73f44e18"},"sg-8a48ccc0": {"region": "ap-southeast-2","vpc_id": "vpc-5d22c33b"},"sg-9be71df6": {"region": "ap-northeast-3","vpc_id": "vpc-47b7dd2e"},"sg-a81474db": {"region": "us-east-2","vpc_id": "vpc-e429ad8f"},"sg-a9b5628e": {"region": "us-west-2","vpc_id": "vpc-d45709ac"},"sg-c1194bbf": {"region": "eu-central-1","vpc_id": "vpc-78b43312"}},"subnet_map": {"subnet-0c0bc26a": {"region": "ap-southeast-2","vpc_id": "vpc-5d22c33b"},"subnet-1075cf4d": {"region": "us-west-2","vpc_id": "vpc-d45709ac"},"subnet-113ce95b": {"region": "us-west-2","vpc_id": "vpc-d45709ac"},"subnet-18e60365": {"region": "us-east-2","vpc_id": "vpc-e429ad8f"},"subnet-1cd98b74": {"region": "ca-central-1","vpc_id": "vpc-b5113ddd"},"subnet-1d972e74": {"region": "eu-north-1","vpc_id": "vpc-fa259d93"},"subnet-214f3969": {"region": "eu-west-1","vpc_id": "vpc-f24c7994"},"subnet-2506d06d": {"region": "ap-southeast-1","vpc_id": "vpc-04ed1062"},"subnet-25f65d5d": {"region": "us-west-2","vpc_id": "vpc-d45709ac"},"subnet-292d4343": {"region": "eu-central-1","vpc_id": "vpc-78b43312"},"subnet-30be2f6f": {"region": "us-east-1","vpc_id": "vpc-ba1cbdc7"},"subnet-3162b36b": {"region": "us-west-1","vpc_id": "vpc-6e6fa508"},"subnet-43bf9d2a": {"region": "eu-west-2","vpc_id": "vpc-3fa2fa57"},"subnet-4dcc0924": {"region": "ap-northeast-3","vpc_id": "vpc-47b7dd2e"},"subnet-4f896210": {"region": "ca-central-1","vpc_id": "vpc-b5113ddd"},"subnet-546a8e2f": {"region": "ap-northeast-3","vpc_id": "vpc-47b7dd2e"},"subnet-55d77f19": {"region": "eu-central-1","vpc_id": "vpc-78b43312"},"subnet-593d2502": {"region": "ap-northeast-1","vpc_id": "vpc-0cbc506a"},"subnet-64dae84f": {"region": "us-west-2","vpc_id": "vpc-d45709ac"},"subnet-64f07402": {"region": "us-west-1","vpc_id": "vpc-6e6fa508"},"subnet-6a4dd723": {"region": "sa-east-1","vpc_id": "vpc-b14fa4d7"},"subnet-6cb44e24": {"region": "ap-southeast-2","vpc_id": "vpc-5d22c33b"},"subnet-6e61f24f": {"region": "us-east-1","vpc_id": "vpc-ba1cbdc7"},"subnet-7056187e": {"region": "us-east-1","vpc_id": "vpc-ba1cbdc7"},"subnet-762a450d": {"region": "eu-west-3","vpc_id": "vpc-87d3fdee"},"subnet-77e07411": {"region": "us-east-1","vpc_id": "vpc-ba1cbdc7"},"subnet-7d5a1431": {"region": "ap-south-1","vpc_id": "vpc-2651a14d"},"subnet-7f50e154": {"region": "ap-northeast-1","vpc_id": "vpc-0cbc506a"},"subnet-81a1eccd": {"region": "us-east-2","vpc_id": "vpc-e429ad8f"},"subnet-8447addb": {"region": "ap-northeast-2","vpc_id": "vpc-73f44e18"},"subnet-85711fff": {"region": "ca-central-1","vpc_id": "vpc-b5113ddd"},"subnet-8c27ffbd": {"region": "us-east-1","vpc_id": "vpc-ba1cbdc7"},"subnet-9aa5c1fc": {"region": "sa-east-1","vpc_id": "vpc-b14fa4d7"},"subnet-a448d5fd": {"region": "ap-southeast-1","vpc_id": "vpc-04ed1062"},"subnet-a668c6ee": {"region": "ap-northeast-1","vpc_id": "vpc-0cbc506a"},"subnet-aaddbef1": {"region": "sa-east-1","vpc_id": "vpc-b14fa4d7"},"subnet-af6809d4": {"region": "ap-northeast-2","vpc_id": "vpc-73f44e18"},"subnet-b1c2a5d7": {"region": "eu-west-1","vpc_id": "vpc-f24c7994"},"subnet-b309b8fe": {"region": "eu-west-3","vpc_id": "vpc-87d3fdee"},"subnet-b3a000e9": {"region": "eu-west-1","vpc_id": "vpc-f24c7994"},"subnet-b3fe86eb": {"region": "ap-southeast-2","vpc_id": "vpc-5d22c33b"},"subnet-b73197d1": {"region": "ap-southeast-1","vpc_id": "vpc-04ed1062"},"subnet-c1b6118c": {"region": "ap-northeast-3","vpc_id": "vpc-47b7dd2e"},"subnet-c98e7484": {"region": "eu-north-1","vpc_id": "vpc-fa259d93"},"subnet-cbefcb86": {"region": "us-east-1","vpc_id": "vpc-ba1cbdc7"},"subnet-cf001883": {"region": "ap-northeast-2","vpc_id": "vpc-73f44e18"},"subnet-d3c151a8": {"region": "ap-south-1","vpc_id": "vpc-2651a14d"},"subnet-e682ec9c": {"region": "eu-west-2","vpc_id": "vpc-3fa2fa57"},"subnet-e6ad198d": {"region": "ap-northeast-2","vpc_id": "vpc-73f44e18"},"subnet-e9e1b480": {"region": "eu-west-3","vpc_id": "vpc-87d3fdee"},"subnet-ecc66390": {"region": "eu-central-1","vpc_id": "vpc-78b43312"},"subnet-edaf13a1": {"region": "eu-west-2","vpc_id": "vpc-3fa2fa57"},"subnet-f0fde498": {"region": "ap-south-1","vpc_id": "vpc-2651a14d"},"subnet-fac76891": {"region": "us-east-2","vpc_id": "vpc-e429ad8f"},"subnet-fe16ce85": {"region": "eu-north-1","vpc_id": "vpc-fa259d93"}}} +{ + "account_id": "430150006394", + "environment": null, + "last_run": { + "ruleset_about": "This ruleset consists of numerous rules that are considered standard by NCC Group. The rules enabled range from violations of well-known security best practices to gaps resulting from less-known security implications of provider-specific mechanisms. Additional rules exist, some of them requiring extra-parameters to be configured, and some of them being applicable to a limited number of users.", + "ruleset_name": "default", + "run_parameters": { + "excluded_regions": [], + "regions": [], + "services": [], + "skipped_services": [] + }, + "summary": { + "acm": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 2 + }, + "awslambda": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 1, + "rules_count": 0 + }, + "cloudformation": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 1 + }, + "cloudtrail": { + "checked_items": 16, + "flagged_items": 16, + "max_level": "danger", + "resources_count": 0, + "rules_count": 8 + }, + "cloudwatch": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 1 + }, + "config": { + "checked_items": 17, + "flagged_items": 17, + "max_level": "warning", + "resources_count": 0, + "rules_count": 1 + }, + "directconnect": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 0 + }, + "dynamodb": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 0 + }, + "ec2": { + "checked_items": 679, + "flagged_items": 100, + "max_level": "danger", + "resources_count": 20, + "rules_count": 28 + }, + "efs": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 0 + }, + "elasticache": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 0 + }, + "elb": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 3 + }, + "elbv2": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 5 + }, + "emr": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 0 + }, + "iam": { + "checked_items": 121, + "flagged_items": 14, + "max_level": "danger", + "resources_count": 22, + "rules_count": 36 + }, + "kms": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 1 + }, + "rds": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 17, + "rules_count": 8 + }, + "redshift": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 6 + }, + "route53": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 3 + }, + "s3": { + "checked_items": 26, + "flagged_items": 10, + "max_level": "warning", + "resources_count": 2, + "rules_count": 18 + }, + "secretsmanager": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 0 + }, + "ses": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 4 + }, + "sns": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 7 + }, + "sqs": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 7 + }, + "vpc": { + "checked_items": 250, + "flagged_items": 199, + "max_level": "warning", + "resources_count": 0, + "rules_count": 9 + } + }, + "time": "2021-10-01 20:47:09+0200", + "version": "5.10.2" + }, + "metadata": { + "analytics": { + "emr": { + "resources": { + "clusters": { + "callbacks": [ + [ + "match_security_groups_and_resources_callback", + { + "sg_id_attribute_name": "", + "sg_list_attribute_name": [ + "Ec2InstanceAttributes", + "EmrManagedMasterSecurityGroup" + ], + "status_path": [ + "Status", + "State" + ] + } + ], + [ + "match_security_groups_and_resources_callback", + { + "sg_id_attribute_name": "", + "sg_list_attribute_name": [ + "Ec2InstanceAttributes", + "EmrManagedSlaveSecurityGroup" + ], + "status_path": [ + "Status", + "State" + ] + } + ] + ], + "cols": 2, + "count": 0, + "full_path": "services.emr.regions.id.vpcs.id.clusters", + "path": "services.emr.regions.id.vpcs.id.clusters", + "script": "services.emr.regions.vpcs.clusters" + } + } + } + }, + "compute": { + "awslambda": { + "resources": { + "functions": { + "callbacks": [ + [ + "match_security_groups_and_resources_callback", + { + "sg_list_attribute_name": [ + "VpcConfig", + "SecurityGroupIds" + ], + "status_path": [ + "runtime" + ] + } + ] + ], + "count": 1, + "full_path": "services.awslambda.regions.id.functions", + "path": "services.awslambda.regions.id.functions", + "script": "services.awslambda.regions.functions" + } + } + }, + "ec2": { + "resources": { + "images": { + "cols": 2, + "count": 0, + "full_path": "services.ec2.regions.id.images", + "path": "services.ec2.regions.id.images", + "script": "services.ec2.regions.images" + }, + "instances": { + "callbacks": [ + [ + "match_instances_and_subnets_callback", + {} + ] + ], + "cols": 2, + "count": 0, + "full_path": "services.ec2.regions.id.vpcs.id.instances", + "path": "services.ec2.regions.id.vpcs.id.instances", + "script": "services.ec2.regions.vpcs.instances" + }, + "network_interfaces": { + "callbacks": [ + [ + "match_security_groups_and_resources_callback", + { + "sg_id_attribute_name": "GroupId", + "sg_list_attribute_name": [ + "Groups" + ] + } + ] + ], + "count": 0, + "full_path": "services.ec2.regions.id.vpcs.id.network_interfaces", + "hidden": true, + "path": "services.ec2.regions.id.vpcs.id.network_interfaces", + "script": "services.ec2.regions.vpcs.network_interfaces" + }, + "security_groups": { + "cols": 2, + "count": 20, + "full_path": "services.ec2.regions.id.vpcs.id.security_groups", + "path": "services.ec2.regions.id.vpcs.id.security_groups", + "script": "services.ec2.regions.vpcs.security_groups" + }, + "snapshots": { + "cols": 2, + "count": 0, + "full_path": "services.ec2.regions.id.snapshots", + "path": "services.ec2.regions.id.snapshots", + "script": "services.ec2.regions.snapshots" + }, + "volumes": { + "cols": 2, + "count": 0, + "full_path": "services.ec2.regions.id.volumes", + "path": "services.ec2.regions.id.volumes", + "script": "services.ec2.regions.volumes" + } + }, + "summaries": { + "external attack surface": { + "callbacks": [ + [ + "list_ec2_network_attack_surface_callback", + { + "path": "services.ec2.regions.id.vpcs.id.instances.id.network_interfaces.id.PrivateIpAddresses" + } + ] + ], + "cols": 1, + "path": "services.ec2.external_attack_surface" + } + } + }, + "elb": { + "resources": { + "elb_policies": { + "cols": 2, + "count": 0, + "full_path": "services.elb.regions.id.elb_policies", + "path": "services.elb.regions.id.elb_policies", + "script": "services.elb.regions.elb_policies" + }, + "elbs": { + "callbacks": [ + [ + "match_security_groups_and_resources_callback", + { + "sg_id_attribute_name": "GroupId", + "sg_list_attribute_name": [ + "security_groups" + ], + "status_path": [ + "Scheme" + ] + } + ], + [ + "get_lb_attack_surface", + {} + ] + ], + "cols": 2, + "count": 0, + "full_path": "services.elb.regions.id.vpcs.id.elbs", + "path": "services.elb.regions.id.vpcs.id.elbs", + "script": "services.elb.regions.vpcs.elbs" + } + }, + "summaries": { + "external attack surface": { + "cols": 1, + "path": "services.elb.external_attack_surface" + } + } + }, + "elbv2": { + "resources": { + "lbs": { + "callbacks": [ + [ + "match_security_groups_and_resources_callback", + { + "sg_id_attribute_name": "GroupId", + "sg_list_attribute_name": [ + "security_groups" + ], + "status_path": [ + "State", + "Code" + ] + } + ], + [ + "get_lb_attack_surface", + {} + ] + ], + "cols": 2, + "count": 0, + "full_path": "services.elbv2.regions.id.vpcs.id.lbs", + "path": "services.elbv2.regions.id.vpcs.id.lbs", + "script": "services.elbv2.regions.vpcs.lbs" + } + }, + "summaries": { + "external attack surface": { + "cols": 1, + "path": "services.elbv2.external_attack_surface" + } + } + }, + "summaries": { + "external attack surface": { + "callbacks": [ + [ + "merge", + { + "attribute": "external_attack_surface" + } + ] + ], + "cols": 1, + "path": "service_groups.compute.summaries.external_attack_surface" + } + } + }, + "containers": { + "ecr": { + "resources": { + "images": { + "cols": 2, + "path": "services.ecr.regions.id.images" + }, + "repositories": { + "cols": 2, + "path": "services.ecr.regions.id.repositories" + } + } + }, + "ecs": { + "resources": { + "clusters": { + "cols": 2, + "path": "services.ecs.regions.id.clusters" + }, + "regions": { + "cols": 2, + "path": "services.ecs.regions" + } + } + }, + "eks": { + "resources": { + "clusters": { + "cols": 2, + "path": "services.eks.regions.id.clusters" + } + } + } + }, + "database": { + "docdb": { + "resources": { + "clusters": { + "path": "services.docdb.regions.id.clusters" + } + } + }, + "dynamodb": { + "resources": { + "tables": { + "count": 0, + "full_path": "services.dynamodb.regions.id.tables", + "path": "services.dynamodb.regions.id.tables", + "script": "services.dynamodb.regions.tables" + } + } + }, + "elasticache": { + "resources": { + "clusters": { + "callbacks": [ + [ + "match_security_groups_and_resources_callback", + { + "sg_id_attribute_name": "SecurityGroupId", + "sg_list_attribute_name": [ + "SecurityGroups" + ], + "status_path": [ + "CacheClusterStatus" + ] + } + ], + [ + "get_db_attack_surface", + {} + ] + ], + "cols": 2, + "count": 0, + "full_path": "services.elasticache.regions.id.vpcs.id.clusters", + "path": "services.elasticache.regions.id.vpcs.id.clusters", + "script": "services.elasticache.regions.vpcs.clusters" + }, + "parameter_groups": { + "cols": 2, + "count": 216, + "full_path": "services.elasticache.regions.id.parameter_groups", + "path": "services.elasticache.regions.id.parameter_groups", + "script": "services.elasticache.regions.parameter_groups" + }, + "security_groups": { + "cols": 2, + "count": 0, + "full_path": "services.elasticache.regions.id.security_groups", + "no_exceptions": true, + "path": "services.elasticache.regions.id.security_groups", + "script": "services.elasticache.regions.security_groups" + }, + "subnet_groups": { + "cols": 2, + "count": 0, + "full_path": "services.elasticache.regions.id.vpcs.id.subnet_groups", + "path": "services.elasticache.regions.id.vpcs.id.subnet_groups", + "script": "services.elasticache.regions.vpcs.subnet_groups" + } + } + }, + "rds": { + "resources": { + "instances": { + "callbacks": [ + [ + "match_security_groups_and_resources_callback", + { + "sg_id_attribute_name": "VpcSecurityGroupId", + "sg_list_attribute_name": [ + "VpcSecurityGroups" + ], + "status_path": [ + "DBInstanceStatus" + ] + } + ], + [ + "get_db_attack_surface", + {} + ] + ], + "cols": 2, + "count": 0, + "full_path": "services.rds.regions.id.vpcs.id.instances", + "path": "services.rds.regions.id.vpcs.id.instances", + "script": "services.rds.regions.vpcs.instances" + }, + "parameter_groups": { + "cols": 2, + "count": 0, + "full_path": "services.rds.regions.id.parameter_groups", + "path": "services.rds.regions.id.parameter_groups", + "script": "services.rds.regions.parameter_groups" + }, + "security_groups": { + "cols": 2, + "count": 17, + "full_path": "services.rds.regions.id.security_groups", + "no_exceptions": true, + "path": "services.rds.regions.id.security_groups", + "script": "services.rds.regions.security_groups" + }, + "snapshots": { + "cols": 2, + "count": 0, + "full_path": "services.rds.regions.id.vpcs.id.snapshots", + "path": "services.rds.regions.id.vpcs.id.snapshots", + "script": "services.rds.regions.vpcs.snapshots" + }, + "subnet_groups": { + "cols": 2, + "count": 0, + "full_path": "services.rds.regions.id.vpcs.id.subnet_groups", + "path": "services.rds.regions.id.vpcs.id.subnet_groups", + "script": "services.rds.regions.vpcs.subnet_groups" + } + }, + "summaries": { + "external attack surface": { + "cols": 1, + "path": "services.rds.external_attack_surface" + } + } + }, + "redshift": { + "resources": { + "clusters": { + "callbacks": [ + [ + "match_security_groups_and_resources_callback", + { + "sg_id_attribute_name": "VpcSecurityGroupId", + "sg_list_attribute_name": [ + "VpcSecurityGroups" + ], + "status_path": [ + "ClusterStatus" + ] + } + ], + [ + "get_db_attack_surface", + {} + ] + ], + "cols": 2, + "count": 0, + "full_path": "services.redshift.regions.id.vpcs.id.clusters", + "path": "services.redshift.regions.id.vpcs.id.clusters", + "script": "services.redshift.regions.vpcs.clusters" + }, + "parameter_groups": { + "cols": 2, + "count": 0, + "full_path": "services.redshift.regions.id.parameter_groups", + "path": "services.redshift.regions.id.parameter_groups", + "script": "services.redshift.regions.parameter_groups" + }, + "security_groups": { + "cols": 2, + "count": 0, + "full_path": "services.redshift.regions.id.security_groups", + "path": "services.redshift.regions.id.security_groups", + "script": "services.redshift.regions.security_groups" + } + }, + "summaries": { + "external attack surface": { + "cols": 1, + "path": "services.redshift.external_attack_surface" + } + } + }, + "summaries": { + "external attack surface": { + "callbacks": [ + [ + "merge", + { + "attribute": "external_attack_surface" + } + ] + ], + "cols": 1, + "path": "service_groups.database.summaries.external_attack_surface" + } + } + }, + "management": { + "cloudformation": { + "resources": { + "stacks": { + "callbacks": [ + [ + "match_roles_and_cloudformation_stacks_callback", + {} + ] + ], + "cols": 2, + "count": 0, + "full_path": "services.cloudformation.regions.id.stacks", + "path": "services.cloudformation.regions.id.stacks", + "script": "services.cloudformation.regions.stacks" + } + } + }, + "cloudtrail": { + "resources": { + "regions": { + "cols": 2, + "count": 16, + "full_path": "services.cloudtrail.regions", + "path": "services.cloudtrail.regions", + "script": "services.cloudtrail.regions" + }, + "trails": { + "cols": 2, + "count": 0, + "full_path": "services.cloudtrail.regions.id.trails", + "path": "services.cloudtrail.regions.id.trails", + "script": "services.cloudtrail.regions.trails" + } + } + }, + "cloudwatch": { + "resources": { + "alarms": { + "cols": 2, + "count": 0, + "full_path": "services.cloudwatch.regions.id.alarms", + "path": "services.cloudwatch.regions.id.alarms", + "script": "services.cloudwatch.regions.alarms" + }, + "metric_filters": { + "cols": 2, + "count": 0, + "full_path": "services.cloudwatch.regions.id.metric_filters", + "path": "services.cloudwatch.regions.id.metric_filters", + "script": "services.cloudwatch.regions.metric_filters" + } + } + }, + "config": { + "resources": { + "recorders": { + "count": 0, + "full_path": "services.config.regions.id.recorders", + "path": "services.config.regions.id.recorders", + "script": "services.config.regions.recorders" + }, + "regions": { + "cols": 2, + "count": 17, + "full_path": "services.config.regions", + "path": "services.config.regions", + "script": "services.config.regions" + }, + "rules": { + "count": 0, + "full_path": "services.config.regions.id.rules", + "path": "services.config.regions.id.rules", + "script": "services.config.regions.rules" + } + } + } + }, + "messaging": { + "ses": { + "resources": { + "identities": { + "cols": 2, + "count": 0, + "full_path": "services.ses.regions.id.identities", + "path": "services.ses.regions.id.identities", + "script": "services.ses.regions.identities" + } + } + }, + "sns": { + "resources": { + "topics": { + "cols": 2, + "count": 0, + "full_path": "services.sns.regions.id.topics", + "path": "services.sns.regions.id.topics", + "script": "services.sns.regions.topics" + } + } + }, + "sqs": { + "resources": { + "queues": { + "cols": 2, + "count": 0, + "full_path": "services.sqs.regions.id.queues", + "path": "services.sqs.regions.id.queues", + "script": "services.sqs.regions.queues" + } + } + } + }, + "network": { + "directconnect": { + "resources": { + "connections": { + "cols": 2, + "count": 0, + "full_path": "services.directconnect.connections", + "path": "services.directconnect.connections", + "script": "services.directconnect.connections" + } + } + }, + "route53": { + "resources": { + "domains": { + "cols": 2, + "count": 0, + "full_path": "services.route53.regions.id.domains", + "path": "services.route53.regions.id.domains", + "script": "services.route53.regions.domains" + }, + "hosted_zones": { + "cols": 2, + "count": 0, + "full_path": "services.route53.regions.id.hosted_zones", + "path": "services.route53.regions.id.hosted_zones", + "script": "services.route53.regions.hosted_zones" + } + } + }, + "vpc": { + "resources": { + "flow_logs": { + "callbacks": [ + [ + "sort_vpc_flow_logs_callback", + {} + ], + [ + "match_roles_and_vpc_flowlogs_callback", + {} + ] + ], + "count": 0, + "full_path": "services.vpc.regions.id.flow_logs", + "path": "services.vpc.regions.id.flow_logs", + "script": "services.vpc.regions.flow_logs" + }, + "network_acls": { + "callbacks": [ + [ + "match_network_acls_and_subnets_callback", + {} + ], + [ + "process_network_acls_callback", + {} + ] + ], + "cols": 2, + "count": 17, + "full_path": "services.vpc.regions.id.vpcs.id.network_acls", + "path": "services.vpc.regions.id.vpcs.id.network_acls", + "script": "services.vpc.regions.vpcs.network_acls" + }, + "peering_connections": { + "callbacks": [ + [ + "process_vpc_peering_connections_callback", + {} + ] + ], + "count": 0, + "full_path": "services.vpc.regions.id.peering_connections", + "path": "services.vpc.regions.id.peering_connections", + "script": "services.vpc.regions.peering_connections" + }, + "subnets": { + "cols": 2, + "count": 55, + "full_path": "services.vpc.regions.id.vpcs.id.subnets", + "path": "services.vpc.regions.id.vpcs.id.subnets", + "script": "services.vpc.regions.vpcs.subnets" + }, + "vpcs": { + "cols": 2, + "count": 17, + "full_path": "services.vpc.regions.id.vpcs", + "path": "services.vpc.regions.id.vpcs", + "script": "services.vpc.regions.vpcs" + } + } + } + }, + "security": { + "acm": { + "resources": { + "certificates": { + "cols": 2, + "count": 0, + "full_path": "services.acm.regions.id.certificates", + "path": "services.acm.regions.id.certificates", + "script": "services.acm.regions.certificates" + } + } + }, + "cognito": { + "resources": { + "identity_pools": { + "cols": 2, + "path": "services.cognito.regions.id.identity_pools" + }, + "user_pools": { + "cols": 2, + "path": "services.cognito.regions.id.user_pools" + } + } + }, + "guardduty": { + "resources": { + "detectors": { + "path": "services.guardduty.regions.id.detectors" + }, + "regions": { + "cols": 2, + "path": "services.guardduty.regions" + } + } + }, + "iam": { + "resources": { + "credential_reports": { + "cols": 2, + "count": 2, + "full_path": "services.iam.credential_reports", + "path": "services.iam.credential_reports", + "script": "services.iam.credential_reports" + }, + "groups": { + "cols": 2, + "count": 1, + "full_path": "services.iam.groups", + "path": "services.iam.groups", + "script": "services.iam.groups" + }, + "policies": { + "cols": 2, + "count": 9, + "full_path": "services.iam.policies", + "path": "services.iam.policies", + "script": "services.iam.policies" + }, + "roles": { + "cols": 2, + "count": 9, + "full_path": "services.iam.roles", + "path": "services.iam.roles", + "script": "services.iam.roles" + }, + "users": { + "cols": 2, + "count": 1, + "full_path": "services.iam.users", + "path": "services.iam.users", + "script": "services.iam.users" + } + }, + "summaries": { + "password_policy": { + "cols": 1, + "path": "services.iam.password_policy" + }, + "permissions": { + "cols": 1, + "path": "services.iam.permissions" + } + } + }, + "kms": { + "resources": { + "keys": { + "count": 0, + "full_path": "services.kms.regions.id.keys", + "path": "services.kms.regions.id.keys", + "script": "services.kms.regions.keys" + } + } + }, + "secretsmanager": { + "resources": { + "secrets": { + "cols": 2, + "count": 0, + "full_path": "services.secretsmanager.regions.id.secrets", + "path": "services.secretsmanager.regions.id.secrets", + "script": "services.secretsmanager.regions.secrets" + } + } + } + }, + "storage": { + "efs": { + "hidden": true, + "resources": { + "file_systems": { + "callbacks": [ + [ + "match_security_groups_and_resources_callback", + { + "sg_list_attribute_name": [ + "security_groups" + ], + "status_path": [ + "LifeCycleState" + ] + } + ] + ], + "path": "services.efs.regions.id.file_systems" + } + } + }, + "s3": { + "resources": { + "buckets": { + "cols": 2, + "count": 2, + "full_path": "services.s3.buckets", + "path": "services.s3.buckets", + "script": "services.s3.buckets" + } + } + } + } + }, + "partition": "aws", + "provider_code": "aws", + "provider_name": "Amazon Web Services", + "result_format": "json", + "service_groups": { + "compute": { + "summaries": { + "external_attack_surface": {} + } + }, + "database": { + "summaries": { + "external_attack_surface": {} + } + } + }, + "service_list": [ + "acm", + "awslambda", + "cloudformation", + "cloudtrail", + "cloudwatch", + "config", + "directconnect", + "dynamodb", + "ec2", + "efs", + "elasticache", + "elb", + "elbv2", + "emr", + "iam", + "kms", + "rds", + "redshift", + "route53", + "s3", + "ses", + "sns", + "sqs", + "vpc", + "secretsmanager" + ], + "services": { + "acm": { + "certificates_count": 0, + "filters": {}, + "findings": { + "acm-certificate-with-close-expiration-date": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Certificates", + "description": "ACM Certificate Expiring in Less Than 7 Days", + "flagged_items": 0, + "id_suffix": "NotAfter", + "items": [], + "level": "warning", + "path": "acm.regions.id.certificates.id", + "rationale": "Ensure that certificates which are in use are not about to expire.", + "references": null, + "remediation": null, + "service": "ACM" + }, + "acm-certificate-with-transparency-logging-disabled": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Certificates", + "description": "ACM Certificate with Transparency Logging Set to Disabled", + "flagged_items": 0, + "id_suffix": "CertificateTransparencyLoggingPreference", + "items": [], + "level": "warning", + "path": "acm.regions.id.certificates.id", + "rationale": "Disabling Transparency Logging may result in browsers not trusting your certificate. As of April 30 2018, Google Chrome no longer trusts public SSL/TLS certificates that are not recorded in a certificate transparency log. Transparency Logging should be enabled as a best practice.", + "references": [ + "https://aws.amazon.com/blogs/security/how-to-get-ready-for-certificate-transparency/" + ], + "remediation": null, + "service": "ACM" + } + }, + "regions": { + "ap-northeast-1": { + "certificates": {}, + "certificates_count": 0, + "id": "ap-northeast-1", + "name": "ap-northeast-1", + "region": "ap-northeast-1" + }, + "ap-northeast-2": { + "certificates": {}, + "certificates_count": 0, + "id": "ap-northeast-2", + "name": "ap-northeast-2", + "region": "ap-northeast-2" + }, + "ap-northeast-3": { + "certificates": {}, + "certificates_count": 0, + "id": "ap-northeast-3", + "name": "ap-northeast-3", + "region": "ap-northeast-3" + }, + "ap-south-1": { + "certificates": {}, + "certificates_count": 0, + "id": "ap-south-1", + "name": "ap-south-1", + "region": "ap-south-1" + }, + "ap-southeast-1": { + "certificates": {}, + "certificates_count": 0, + "id": "ap-southeast-1", + "name": "ap-southeast-1", + "region": "ap-southeast-1" + }, + "ap-southeast-2": { + "certificates": {}, + "certificates_count": 0, + "id": "ap-southeast-2", + "name": "ap-southeast-2", + "region": "ap-southeast-2" + }, + "ca-central-1": { + "certificates": {}, + "certificates_count": 0, + "id": "ca-central-1", + "name": "ca-central-1", + "region": "ca-central-1" + }, + "eu-central-1": { + "certificates": {}, + "certificates_count": 0, + "id": "eu-central-1", + "name": "eu-central-1", + "region": "eu-central-1" + }, + "eu-north-1": { + "certificates": {}, + "certificates_count": 0, + "id": "eu-north-1", + "name": "eu-north-1", + "region": "eu-north-1" + }, + "eu-west-1": { + "certificates": {}, + "certificates_count": 0, + "id": "eu-west-1", + "name": "eu-west-1", + "region": "eu-west-1" + }, + "eu-west-2": { + "certificates": {}, + "certificates_count": 0, + "id": "eu-west-2", + "name": "eu-west-2", + "region": "eu-west-2" + }, + "eu-west-3": { + "certificates": {}, + "certificates_count": 0, + "id": "eu-west-3", + "name": "eu-west-3", + "region": "eu-west-3" + }, + "sa-east-1": { + "certificates": {}, + "certificates_count": 0, + "id": "sa-east-1", + "name": "sa-east-1", + "region": "sa-east-1" + }, + "us-east-1": { + "certificates": {}, + "certificates_count": 0, + "id": "us-east-1", + "name": "us-east-1", + "region": "us-east-1" + }, + "us-east-2": { + "certificates": {}, + "certificates_count": 0, + "id": "us-east-2", + "name": "us-east-2", + "region": "us-east-2" + }, + "us-west-1": { + "certificates": {}, + "certificates_count": 0, + "id": "us-west-1", + "name": "us-west-1", + "region": "us-west-1" + }, + "us-west-2": { + "certificates": {}, + "certificates_count": 0, + "id": "us-west-2", + "name": "us-west-2", + "region": "us-west-2" + } + }, + "regions_count": 17 + }, + "awslambda": { + "filters": {}, + "findings": {}, + "functions_count": 1, + "regions": { + "ap-northeast-1": { + "functions": {}, + "functions_count": 0, + "id": "ap-northeast-1", + "name": "ap-northeast-1", + "region": "ap-northeast-1" + }, + "ap-northeast-2": { + "functions": {}, + "functions_count": 0, + "id": "ap-northeast-2", + "name": "ap-northeast-2", + "region": "ap-northeast-2" + }, + "ap-northeast-3": { + "functions": {}, + "functions_count": 0, + "id": "ap-northeast-3", + "name": "ap-northeast-3", + "region": "ap-northeast-3" + }, + "ap-south-1": { + "functions": {}, + "functions_count": 0, + "id": "ap-south-1", + "name": "ap-south-1", + "region": "ap-south-1" + }, + "ap-southeast-1": { + "functions": {}, + "functions_count": 0, + "id": "ap-southeast-1", + "name": "ap-southeast-1", + "region": "ap-southeast-1" + }, + "ap-southeast-2": { + "functions": {}, + "functions_count": 0, + "id": "ap-southeast-2", + "name": "ap-southeast-2", + "region": "ap-southeast-2" + }, + "ca-central-1": { + "functions": {}, + "functions_count": 0, + "id": "ca-central-1", + "name": "ca-central-1", + "region": "ca-central-1" + }, + "eu-central-1": { + "functions": {}, + "functions_count": 0, + "id": "eu-central-1", + "name": "eu-central-1", + "region": "eu-central-1" + }, + "eu-north-1": { + "functions": {}, + "functions_count": 0, + "id": "eu-north-1", + "name": "eu-north-1", + "region": "eu-north-1" + }, + "eu-west-1": { + "functions": { + "load-wikipedia": { + "access_policy": { + "Id": "default", + "Statement": [], + "Version": "2012-10-17" + }, + "arn": "arn:aws:lambda:eu-west-1:430150006394:function:load-wikipedia", + "code_sha256": "txY7sj38mwfot6uoeqMhNs4P/VycimyJcRBdlDBTyik=", + "code_size": 506, + "description": "", + "env_variable_names": [], + "env_variable_values": [], + "env_variables": [], + "execution_role": { + "Arn": "arn:aws:iam::430150006394:role/service-role/load-wikipedia", + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "CreateDate": "2019-01-23 17:01:24+00:00", + "MaxSessionDuration": 3600, + "Path": "/service-role/", + "RoleId": "AROAJY5MNJYDKGD2UIATQ", + "RoleLastUsed": {}, + "RoleName": "load-wikipedia", + "policies": [ + { + "Document": { + "Statement": [ + { + "Action": "logs:CreateLogGroup", + "Effect": "Allow", + "Resource": "arn:aws:logs:eu-west-1:430150006394:*" + }, + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:eu-west-1:430150006394:log-group:/aws/lambda/load-wikipedia:*" + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyArn": "arn:aws:iam::430150006394:policy/service-role/AWSLambdaBasicExecutionRole-676647ec-377e-496c-8355-37f23bf12c85", + "PolicyName": "AWSLambdaBasicExecutionRole-676647ec-377e-496c-8355-37f23bf12c85" + } + ], + "policy_statements": [ + { + "Action": "logs:CreateLogGroup", + "Effect": "Allow", + "Resource": "arn:aws:logs:eu-west-1:430150006394:*" + }, + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:eu-west-1:430150006394:log-group:/aws/lambda/load-wikipedia:*" + ] + } + ] + }, + "handler": "lambda_function.lambda_handler", + "last_modified": "2019-01-25T17:47:21.038+0000", + "memory_size": 128, + "name": "load-wikipedia", + "region": "eu-west-1", + "revision_id": "9ec6c002-9048-4d53-a4c2-001e406827b3", + "role_arn": "arn:aws:iam::430150006394:role/service-role/load-wikipedia", + "runtime": "python2.7", + "timeout": 3, + "tracing_config": { + "Mode": "PassThrough" + }, + "version": "$LATEST" + } + }, + "functions_count": 1, + "id": "eu-west-1", + "name": "eu-west-1", + "region": "eu-west-1" + }, + "eu-west-2": { + "functions": {}, + "functions_count": 0, + "id": "eu-west-2", + "name": "eu-west-2", + "region": "eu-west-2" + }, + "eu-west-3": { + "functions": {}, + "functions_count": 0, + "id": "eu-west-3", + "name": "eu-west-3", + "region": "eu-west-3" + }, + "sa-east-1": { + "functions": {}, + "functions_count": 0, + "id": "sa-east-1", + "name": "sa-east-1", + "region": "sa-east-1" + }, + "us-east-1": { + "functions": {}, + "functions_count": 0, + "id": "us-east-1", + "name": "us-east-1", + "region": "us-east-1" + }, + "us-east-2": { + "functions": {}, + "functions_count": 0, + "id": "us-east-2", + "name": "us-east-2", + "region": "us-east-2" + }, + "us-west-1": { + "functions": {}, + "functions_count": 0, + "id": "us-west-1", + "name": "us-west-1", + "region": "us-west-1" + }, + "us-west-2": { + "functions": {}, + "functions_count": 0, + "id": "us-west-2", + "name": "us-west-2", + "region": "us-west-2" + } + }, + "regions_count": 17 + }, + "cloudformation": { + "filters": {}, + "findings": { + "cloudformation-stack-with-role": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Stacks", + "description": "Role Passed to Stack", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "cloudformation.regions.id.stacks.id", + "rationale": "Passing a role to CloudFormation stacks may result in privilege escalation because IAM users with privileges within the CloudFormation scope implicitly inherit the stack's role's permissions. Consequently, it should be ensured that the IAM privileges assigned to the stack's role follow the principle of least privilege.", + "references": [ + "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/best-practices.html" + ], + "remediation": null, + "service": "CloudFormation" + } + }, + "regions": { + "ap-northeast-1": { + "id": "ap-northeast-1", + "name": "ap-northeast-1", + "region": "ap-northeast-1", + "stacks": {}, + "stacks_count": 0 + }, + "ap-northeast-2": { + "id": "ap-northeast-2", + "name": "ap-northeast-2", + "region": "ap-northeast-2", + "stacks": {}, + "stacks_count": 0 + }, + "ap-northeast-3": { + "id": "ap-northeast-3", + "name": "ap-northeast-3", + "region": "ap-northeast-3", + "stacks": {}, + "stacks_count": 0 + }, + "ap-south-1": { + "id": "ap-south-1", + "name": "ap-south-1", + "region": "ap-south-1", + "stacks": {}, + "stacks_count": 0 + }, + "ap-southeast-1": { + "id": "ap-southeast-1", + "name": "ap-southeast-1", + "region": "ap-southeast-1", + "stacks": {}, + "stacks_count": 0 + }, + "ap-southeast-2": { + "id": "ap-southeast-2", + "name": "ap-southeast-2", + "region": "ap-southeast-2", + "stacks": {}, + "stacks_count": 0 + }, + "ca-central-1": { + "id": "ca-central-1", + "name": "ca-central-1", + "region": "ca-central-1", + "stacks": {}, + "stacks_count": 0 + }, + "eu-central-1": { + "id": "eu-central-1", + "name": "eu-central-1", + "region": "eu-central-1", + "stacks": {}, + "stacks_count": 0 + }, + "eu-north-1": { + "id": "eu-north-1", + "name": "eu-north-1", + "region": "eu-north-1", + "stacks": {}, + "stacks_count": 0 + }, + "eu-west-1": { + "id": "eu-west-1", + "name": "eu-west-1", + "region": "eu-west-1", + "stacks": {}, + "stacks_count": 0 + }, + "eu-west-2": { + "id": "eu-west-2", + "name": "eu-west-2", + "region": "eu-west-2", + "stacks": {}, + "stacks_count": 0 + }, + "eu-west-3": { + "id": "eu-west-3", + "name": "eu-west-3", + "region": "eu-west-3", + "stacks": {}, + "stacks_count": 0 + }, + "sa-east-1": { + "id": "sa-east-1", + "name": "sa-east-1", + "region": "sa-east-1", + "stacks": {}, + "stacks_count": 0 + }, + "us-east-1": { + "id": "us-east-1", + "name": "us-east-1", + "region": "us-east-1", + "stacks": {}, + "stacks_count": 0 + }, + "us-east-2": { + "id": "us-east-2", + "name": "us-east-2", + "region": "us-east-2", + "stacks": {}, + "stacks_count": 0 + }, + "us-west-1": { + "id": "us-west-1", + "name": "us-west-1", + "region": "us-west-1", + "stacks": {}, + "stacks_count": 0 + }, + "us-west-2": { + "id": "us-west-2", + "name": "us-west-2", + "region": "us-west-2", + "stacks": {}, + "stacks_count": 0 + } + }, + "regions_count": 17, + "stacks_count": 0 + }, + "cloudtrail": { + "DuplicatedGlobalServiceEvents": false, + "IncludeGlobalServiceEvents": false, + "filters": {}, + "findings": { + "cloudtrail-duplicated-global-services-logging": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Configurations", + "description": "Global Service Logging Duplicated", + "flagged_items": 0, + "id_suffix": "IncludeGlobalServiceEvents", + "items": [], + "level": "warning", + "path": "cloudtrail.regions.id.trails.id", + "rationale": "Global service logging is enabled in multiple Trails. While this does not jeopardize the security of the environment, duplicated entries in logs increase the difficulty to investigate potential incidents.", + "references": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-concepts.html#cloudtrail-concepts-global-service-events" + ], + "remediation": null, + "service": "CloudTrail" + }, + "cloudtrail-no-cloudwatch-integration": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.4", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.4", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.4", + "version": "1.2.0" + } + ], + "dashboard_name": "Configurations", + "description": "Trail Is Not Integrated with CloudWatch", + "display_path": "cloudtrail.regions.id.trails.id", + "flagged_items": 0, + "id_suffix": "TrailCloudwatchNoIntegration", + "items": [], + "level": "warning", + "path": "cloudtrail.regions.id.trails.id", + "rationale": "The lack of integration with CloudWatch hinders ral-time and historic activity logging as well as not allowing the configuration of alarms and notifications for anomalous account activity.", + "references": null, + "remediation": "Configure each Trail to have a CloudWatch Logs group attached", + "service": "CloudTrail" + }, + "cloudtrail-no-data-logging": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Configurations", + "description": "Data Events Logging Not Configured", + "display_path": "cloudtrail.regions.id.trails.id", + "flagged_items": 0, + "id_suffix": "cloudtrail-data-events-disabled", + "items": [], + "level": "warning", + "path": "cloudtrail.regions.id.trails.id", + "rationale": "CloudTrail Data Logging is not configured, which means that S3 access and Lambda invocations are not logged.

Note: S3 bucket logging can be used in place of CloudTrail data events for S3. If that is the case, logs for Lambda invocations may still be missing.", + "references": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/logging-data-events-with-cloudtrail.html" + ], + "remediation": null, + "service": "CloudTrail" + }, + "cloudtrail-no-encryption-with-kms": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.7", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.7", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.7", + "version": "1.2.0" + } + ], + "dashboard_name": "Configurations", + "description": "CloudTrail Logs Not Encrypted with KMS Customer Master Keys (CMKs)", + "display_path": "cloudtrail.regions.id.trails.id", + "flagged_items": 0, + "id_suffix": "cloudtrail-kms-key-unused", + "items": [], + "level": "danger", + "path": "cloudtrail.regions.id.trails.id", + "rationale": "Not encrypting CloudTrail logs with SSE-KMS affects the confidentiality of the log data.", + "references": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/encrypting-cloudtrail-log-files-with-aws-kms.html" + ], + "remediation": "Ensure each Trail is encrypted with a KMS key", + "service": "CloudTrail" + }, + "cloudtrail-no-global-services-logging": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Configurations", + "description": "Global Service Logging Disabled", + "flagged_items": 0, + "id_suffix": "IncludeGlobalServiceEvents", + "items": [], + "level": "danger", + "path": "cloudtrail.regions.id.trails.id", + "rationale": "API activity for global services such as IAM and STS is not logged. Investigation of incidents will be incomplete due to the lack of information.", + "references": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-concepts.html#cloudtrail-concepts-global-service-events" + ], + "remediation": null, + "service": "CloudTrail" + }, + "cloudtrail-no-log-file-validation": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.2", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.2", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.2", + "version": "1.2.0" + } + ], + "dashboard_name": "Configurations", + "description": "Log File Validation Is Disabled", + "display_path": "cloudtrail.regions.id.trails.id", + "flagged_items": 0, + "id_suffix": "LogFileValidationDisabled", + "items": [], + "level": "danger", + "path": "cloudtrail.regions.id.trails.id", + "rationale": "The lack of log file validation prevents from verifying the integrity of CloudTrail log files.", + "references": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-log-file-validation-intro.html" + ], + "remediation": "Ensure that each Trail has Enable log file validation set to Yes", + "service": "CloudTrail" + }, + "cloudtrail-no-logging": { + "checked_items": 0, + "class_suffix": "IsLogging", + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.1", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.1", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.1", + "version": "1.2.0" + } + ], + "dashboard_name": "Configurations", + "description": "Disabled Trails", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "cloudtrail.regions.id.trails.id", + "rationale": "Logging is disabled for a given Trail. Depending on the configuration, logs for important API activity may be missing.", + "references": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/best-practices-security.html" + ], + "remediation": "Configure all Trails to enable Logging, set Apply trail to all regions and ensure that Read/Write Events are set to ALL", + "service": "CloudTrail" + }, + "cloudtrail-not-configured": { + "checked_items": 16, + "compliance": null, + "dashboard_name": "Regions", + "description": "CloudTrail Service Not Configured", + "flagged_items": 16, + "id_suffix": "NotConfigured", + "items": [ + "cloudtrail.regions.ap-northeast-1.NotConfigured", + "cloudtrail.regions.ap-northeast-2.NotConfigured", + "cloudtrail.regions.ap-south-1.NotConfigured", + "cloudtrail.regions.ap-southeast-1.NotConfigured", + "cloudtrail.regions.ap-southeast-2.NotConfigured", + "cloudtrail.regions.ca-central-1.NotConfigured", + "cloudtrail.regions.eu-central-1.NotConfigured", + "cloudtrail.regions.eu-north-1.NotConfigured", + "cloudtrail.regions.eu-west-1.NotConfigured", + "cloudtrail.regions.eu-west-2.NotConfigured", + "cloudtrail.regions.eu-west-3.NotConfigured", + "cloudtrail.regions.sa-east-1.NotConfigured", + "cloudtrail.regions.us-east-1.NotConfigured", + "cloudtrail.regions.us-east-2.NotConfigured", + "cloudtrail.regions.us-west-1.NotConfigured", + "cloudtrail.regions.us-west-2.NotConfigured" + ], + "level": "danger", + "path": "cloudtrail.regions.id", + "rationale": "CloudTrail is not configured, which means that API activity is not logged.", + "references": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/best-practices-security.html" + ], + "remediation": null, + "service": "CloudTrail" + } + }, + "regions": { + "ap-northeast-1": { + "id": "ap-northeast-1", + "name": "ap-northeast-1", + "region": "ap-northeast-1", + "trails": {}, + "trails_count": 0 + }, + "ap-northeast-2": { + "id": "ap-northeast-2", + "name": "ap-northeast-2", + "region": "ap-northeast-2", + "trails": {}, + "trails_count": 0 + }, + "ap-south-1": { + "id": "ap-south-1", + "name": "ap-south-1", + "region": "ap-south-1", + "trails": {}, + "trails_count": 0 + }, + "ap-southeast-1": { + "id": "ap-southeast-1", + "name": "ap-southeast-1", + "region": "ap-southeast-1", + "trails": {}, + "trails_count": 0 + }, + "ap-southeast-2": { + "id": "ap-southeast-2", + "name": "ap-southeast-2", + "region": "ap-southeast-2", + "trails": {}, + "trails_count": 0 + }, + "ca-central-1": { + "id": "ca-central-1", + "name": "ca-central-1", + "region": "ca-central-1", + "trails": {}, + "trails_count": 0 + }, + "eu-central-1": { + "id": "eu-central-1", + "name": "eu-central-1", + "region": "eu-central-1", + "trails": {}, + "trails_count": 0 + }, + "eu-north-1": { + "id": "eu-north-1", + "name": "eu-north-1", + "region": "eu-north-1", + "trails": {}, + "trails_count": 0 + }, + "eu-west-1": { + "id": "eu-west-1", + "name": "eu-west-1", + "region": "eu-west-1", + "trails": {}, + "trails_count": 0 + }, + "eu-west-2": { + "id": "eu-west-2", + "name": "eu-west-2", + "region": "eu-west-2", + "trails": {}, + "trails_count": 0 + }, + "eu-west-3": { + "id": "eu-west-3", + "name": "eu-west-3", + "region": "eu-west-3", + "trails": {}, + "trails_count": 0 + }, + "sa-east-1": { + "id": "sa-east-1", + "name": "sa-east-1", + "region": "sa-east-1", + "trails": {}, + "trails_count": 0 + }, + "us-east-1": { + "id": "us-east-1", + "name": "us-east-1", + "region": "us-east-1", + "trails": {}, + "trails_count": 0 + }, + "us-east-2": { + "id": "us-east-2", + "name": "us-east-2", + "region": "us-east-2", + "trails": {}, + "trails_count": 0 + }, + "us-west-1": { + "id": "us-west-1", + "name": "us-west-1", + "region": "us-west-1", + "trails": {}, + "trails_count": 0 + }, + "us-west-2": { + "id": "us-west-2", + "name": "us-west-2", + "region": "us-west-2", + "trails": {}, + "trails_count": 0 + } + }, + "regions_count": 16, + "trails_count": 0 + }, + "cloudwatch": { + "alarms_count": 0, + "filters": {}, + "findings": { + "cloudwatch-alarm-without-actions": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Alarms", + "description": "Alarm without Action", + "flagged_items": 0, + "id_suffix": "NoActions", + "items": [], + "level": "warning", + "path": "cloudwatch.regions.id.alarms.id", + "rationale": "Each alarm should have at least one action", + "references": [ + "https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html" + ], + "remediation": null, + "service": "CloudWatch" + } + }, + "metric_filters_count": 0, + "regions": { + "ap-northeast-1": { + "alarms": {}, + "alarms_count": 0, + "id": "ap-northeast-1", + "metric_filters": {}, + "metric_filters_count": 0, + "metric_filters_pattern_checks": { + "aws_configuration_changes": false, + "cloudtrail_configuration_changes": false, + "cmk_deletion": false, + "console_authentication_failures": false, + "console_login_mfa": false, + "iam_policy_changes": false, + "nacl_changes": false, + "network_gateways_changes": false, + "root_usage": false, + "route_table_changes": false, + "s3_policy_changes": false, + "security_group_changes": false, + "unauthorized_api_calls": false, + "vpc_changes": false + }, + "name": "ap-northeast-1", + "region": "ap-northeast-1" + }, + "ap-northeast-2": { + "alarms": {}, + "alarms_count": 0, + "id": "ap-northeast-2", + "metric_filters": {}, + "metric_filters_count": 0, + "metric_filters_pattern_checks": { + "aws_configuration_changes": false, + "cloudtrail_configuration_changes": false, + "cmk_deletion": false, + "console_authentication_failures": false, + "console_login_mfa": false, + "iam_policy_changes": false, + "nacl_changes": false, + "network_gateways_changes": false, + "root_usage": false, + "route_table_changes": false, + "s3_policy_changes": false, + "security_group_changes": false, + "unauthorized_api_calls": false, + "vpc_changes": false + }, + "name": "ap-northeast-2", + "region": "ap-northeast-2" + }, + "ap-northeast-3": { + "alarms": {}, + "alarms_count": 0, + "id": "ap-northeast-3", + "metric_filters": {}, + "metric_filters_count": 0, + "metric_filters_pattern_checks": { + "aws_configuration_changes": false, + "cloudtrail_configuration_changes": false, + "cmk_deletion": false, + "console_authentication_failures": false, + "console_login_mfa": false, + "iam_policy_changes": false, + "nacl_changes": false, + "network_gateways_changes": false, + "root_usage": false, + "route_table_changes": false, + "s3_policy_changes": false, + "security_group_changes": false, + "unauthorized_api_calls": false, + "vpc_changes": false + }, + "name": "ap-northeast-3", + "region": "ap-northeast-3" + }, + "ap-south-1": { + "alarms": {}, + "alarms_count": 0, + "id": "ap-south-1", + "metric_filters": {}, + "metric_filters_count": 0, + "metric_filters_pattern_checks": { + "aws_configuration_changes": false, + "cloudtrail_configuration_changes": false, + "cmk_deletion": false, + "console_authentication_failures": false, + "console_login_mfa": false, + "iam_policy_changes": false, + "nacl_changes": false, + "network_gateways_changes": false, + "root_usage": false, + "route_table_changes": false, + "s3_policy_changes": false, + "security_group_changes": false, + "unauthorized_api_calls": false, + "vpc_changes": false + }, + "name": "ap-south-1", + "region": "ap-south-1" + }, + "ap-southeast-1": { + "alarms": {}, + "alarms_count": 0, + "id": "ap-southeast-1", + "metric_filters": {}, + "metric_filters_count": 0, + "metric_filters_pattern_checks": { + "aws_configuration_changes": false, + "cloudtrail_configuration_changes": false, + "cmk_deletion": false, + "console_authentication_failures": false, + "console_login_mfa": false, + "iam_policy_changes": false, + "nacl_changes": false, + "network_gateways_changes": false, + "root_usage": false, + "route_table_changes": false, + "s3_policy_changes": false, + "security_group_changes": false, + "unauthorized_api_calls": false, + "vpc_changes": false + }, + "name": "ap-southeast-1", + "region": "ap-southeast-1" + }, + "ap-southeast-2": { + "alarms": {}, + "alarms_count": 0, + "id": "ap-southeast-2", + "metric_filters": {}, + "metric_filters_count": 0, + "metric_filters_pattern_checks": { + "aws_configuration_changes": false, + "cloudtrail_configuration_changes": false, + "cmk_deletion": false, + "console_authentication_failures": false, + "console_login_mfa": false, + "iam_policy_changes": false, + "nacl_changes": false, + "network_gateways_changes": false, + "root_usage": false, + "route_table_changes": false, + "s3_policy_changes": false, + "security_group_changes": false, + "unauthorized_api_calls": false, + "vpc_changes": false + }, + "name": "ap-southeast-2", + "region": "ap-southeast-2" + }, + "ca-central-1": { + "alarms": {}, + "alarms_count": 0, + "id": "ca-central-1", + "metric_filters": {}, + "metric_filters_count": 0, + "metric_filters_pattern_checks": { + "aws_configuration_changes": false, + "cloudtrail_configuration_changes": false, + "cmk_deletion": false, + "console_authentication_failures": false, + "console_login_mfa": false, + "iam_policy_changes": false, + "nacl_changes": false, + "network_gateways_changes": false, + "root_usage": false, + "route_table_changes": false, + "s3_policy_changes": false, + "security_group_changes": false, + "unauthorized_api_calls": false, + "vpc_changes": false + }, + "name": "ca-central-1", + "region": "ca-central-1" + }, + "eu-central-1": { + "alarms": {}, + "alarms_count": 0, + "id": "eu-central-1", + "metric_filters": {}, + "metric_filters_count": 0, + "metric_filters_pattern_checks": { + "aws_configuration_changes": false, + "cloudtrail_configuration_changes": false, + "cmk_deletion": false, + "console_authentication_failures": false, + "console_login_mfa": false, + "iam_policy_changes": false, + "nacl_changes": false, + "network_gateways_changes": false, + "root_usage": false, + "route_table_changes": false, + "s3_policy_changes": false, + "security_group_changes": false, + "unauthorized_api_calls": false, + "vpc_changes": false + }, + "name": "eu-central-1", + "region": "eu-central-1" + }, + "eu-north-1": { + "alarms": {}, + "alarms_count": 0, + "id": "eu-north-1", + "metric_filters": {}, + "metric_filters_count": 0, + "metric_filters_pattern_checks": { + "aws_configuration_changes": false, + "cloudtrail_configuration_changes": false, + "cmk_deletion": false, + "console_authentication_failures": false, + "console_login_mfa": false, + "iam_policy_changes": false, + "nacl_changes": false, + "network_gateways_changes": false, + "root_usage": false, + "route_table_changes": false, + "s3_policy_changes": false, + "security_group_changes": false, + "unauthorized_api_calls": false, + "vpc_changes": false + }, + "name": "eu-north-1", + "region": "eu-north-1" + }, + "eu-west-1": { + "alarms": {}, + "alarms_count": 0, + "id": "eu-west-1", + "metric_filters": {}, + "metric_filters_count": 0, + "metric_filters_pattern_checks": { + "aws_configuration_changes": false, + "cloudtrail_configuration_changes": false, + "cmk_deletion": false, + "console_authentication_failures": false, + "console_login_mfa": false, + "iam_policy_changes": false, + "nacl_changes": false, + "network_gateways_changes": false, + "root_usage": false, + "route_table_changes": false, + "s3_policy_changes": false, + "security_group_changes": false, + "unauthorized_api_calls": false, + "vpc_changes": false + }, + "name": "eu-west-1", + "region": "eu-west-1" + }, + "eu-west-2": { + "alarms": {}, + "alarms_count": 0, + "id": "eu-west-2", + "metric_filters": {}, + "metric_filters_count": 0, + "metric_filters_pattern_checks": { + "aws_configuration_changes": false, + "cloudtrail_configuration_changes": false, + "cmk_deletion": false, + "console_authentication_failures": false, + "console_login_mfa": false, + "iam_policy_changes": false, + "nacl_changes": false, + "network_gateways_changes": false, + "root_usage": false, + "route_table_changes": false, + "s3_policy_changes": false, + "security_group_changes": false, + "unauthorized_api_calls": false, + "vpc_changes": false + }, + "name": "eu-west-2", + "region": "eu-west-2" + }, + "eu-west-3": { + "alarms": {}, + "alarms_count": 0, + "id": "eu-west-3", + "metric_filters": {}, + "metric_filters_count": 0, + "metric_filters_pattern_checks": { + "aws_configuration_changes": false, + "cloudtrail_configuration_changes": false, + "cmk_deletion": false, + "console_authentication_failures": false, + "console_login_mfa": false, + "iam_policy_changes": false, + "nacl_changes": false, + "network_gateways_changes": false, + "root_usage": false, + "route_table_changes": false, + "s3_policy_changes": false, + "security_group_changes": false, + "unauthorized_api_calls": false, + "vpc_changes": false + }, + "name": "eu-west-3", + "region": "eu-west-3" + }, + "sa-east-1": { + "alarms": {}, + "alarms_count": 0, + "id": "sa-east-1", + "metric_filters": {}, + "metric_filters_count": 0, + "metric_filters_pattern_checks": { + "aws_configuration_changes": false, + "cloudtrail_configuration_changes": false, + "cmk_deletion": false, + "console_authentication_failures": false, + "console_login_mfa": false, + "iam_policy_changes": false, + "nacl_changes": false, + "network_gateways_changes": false, + "root_usage": false, + "route_table_changes": false, + "s3_policy_changes": false, + "security_group_changes": false, + "unauthorized_api_calls": false, + "vpc_changes": false + }, + "name": "sa-east-1", + "region": "sa-east-1" + }, + "us-east-1": { + "alarms": {}, + "alarms_count": 0, + "id": "us-east-1", + "metric_filters": {}, + "metric_filters_count": 0, + "metric_filters_pattern_checks": { + "aws_configuration_changes": false, + "cloudtrail_configuration_changes": false, + "cmk_deletion": false, + "console_authentication_failures": false, + "console_login_mfa": false, + "iam_policy_changes": false, + "nacl_changes": false, + "network_gateways_changes": false, + "root_usage": false, + "route_table_changes": false, + "s3_policy_changes": false, + "security_group_changes": false, + "unauthorized_api_calls": false, + "vpc_changes": false + }, + "name": "us-east-1", + "region": "us-east-1" + }, + "us-east-2": { + "alarms": {}, + "alarms_count": 0, + "id": "us-east-2", + "metric_filters": {}, + "metric_filters_count": 0, + "metric_filters_pattern_checks": { + "aws_configuration_changes": false, + "cloudtrail_configuration_changes": false, + "cmk_deletion": false, + "console_authentication_failures": false, + "console_login_mfa": false, + "iam_policy_changes": false, + "nacl_changes": false, + "network_gateways_changes": false, + "root_usage": false, + "route_table_changes": false, + "s3_policy_changes": false, + "security_group_changes": false, + "unauthorized_api_calls": false, + "vpc_changes": false + }, + "name": "us-east-2", + "region": "us-east-2" + }, + "us-west-1": { + "alarms": {}, + "alarms_count": 0, + "id": "us-west-1", + "metric_filters": {}, + "metric_filters_count": 0, + "metric_filters_pattern_checks": { + "aws_configuration_changes": false, + "cloudtrail_configuration_changes": false, + "cmk_deletion": false, + "console_authentication_failures": false, + "console_login_mfa": false, + "iam_policy_changes": false, + "nacl_changes": false, + "network_gateways_changes": false, + "root_usage": false, + "route_table_changes": false, + "s3_policy_changes": false, + "security_group_changes": false, + "unauthorized_api_calls": false, + "vpc_changes": false + }, + "name": "us-west-1", + "region": "us-west-1" + }, + "us-west-2": { + "alarms": {}, + "alarms_count": 0, + "id": "us-west-2", + "metric_filters": {}, + "metric_filters_count": 0, + "metric_filters_pattern_checks": { + "aws_configuration_changes": false, + "cloudtrail_configuration_changes": false, + "cmk_deletion": false, + "console_authentication_failures": false, + "console_login_mfa": false, + "iam_policy_changes": false, + "nacl_changes": false, + "network_gateways_changes": false, + "root_usage": false, + "route_table_changes": false, + "s3_policy_changes": false, + "security_group_changes": false, + "unauthorized_api_calls": false, + "vpc_changes": false + }, + "name": "us-west-2", + "region": "us-west-2" + } + }, + "regions_count": 17 + }, + "config": { + "filters": {}, + "findings": { + "config-recorder-not-configured": { + "checked_items": 17, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.5", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.5", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.5", + "version": "1.2.0" + } + ], + "dashboard_name": "Regions", + "description": "AWS Config Not Enabled", + "flagged_items": 17, + "id_suffix": "NotConfigured", + "items": [ + "config.regions.ap-northeast-1.NotConfigured", + "config.regions.ap-northeast-2.NotConfigured", + "config.regions.ap-northeast-3.NotConfigured", + "config.regions.ap-south-1.NotConfigured", + "config.regions.ap-southeast-1.NotConfigured", + "config.regions.ap-southeast-2.NotConfigured", + "config.regions.ca-central-1.NotConfigured", + "config.regions.eu-central-1.NotConfigured", + "config.regions.eu-north-1.NotConfigured", + "config.regions.eu-west-1.NotConfigured", + "config.regions.eu-west-2.NotConfigured", + "config.regions.eu-west-3.NotConfigured", + "config.regions.sa-east-1.NotConfigured", + "config.regions.us-east-1.NotConfigured", + "config.regions.us-east-2.NotConfigured", + "config.regions.us-west-1.NotConfigured", + "config.regions.us-west-2.NotConfigured" + ], + "level": "warning", + "path": "config.regions.id", + "rationale": "No AWS Config recorders are configured, which means that changes in AWS resource configuration are not logged. This hinders security analysis, resource change tracking and compliance auditing.", + "references": [ + "https://aws.amazon.com/blogs/mt/aws-config-best-practices/" + ], + "remediation": "Enable AWS Config in all regions, define the resources you want to record in each region and include global resources (IAM resources)", + "service": "Config" + } + }, + "recorders_count": 0, + "regions": { + "ap-northeast-1": { + "id": "ap-northeast-1", + "name": "ap-northeast-1", + "recorders": {}, + "recorders_count": 0, + "region": "ap-northeast-1", + "rules": {}, + "rules_count": 0 + }, + "ap-northeast-2": { + "id": "ap-northeast-2", + "name": "ap-northeast-2", + "recorders": {}, + "recorders_count": 0, + "region": "ap-northeast-2", + "rules": {}, + "rules_count": 0 + }, + "ap-northeast-3": { + "id": "ap-northeast-3", + "name": "ap-northeast-3", + "recorders": {}, + "recorders_count": 0, + "region": "ap-northeast-3", + "rules": {}, + "rules_count": 0 + }, + "ap-south-1": { + "id": "ap-south-1", + "name": "ap-south-1", + "recorders": {}, + "recorders_count": 0, + "region": "ap-south-1", + "rules": {}, + "rules_count": 0 + }, + "ap-southeast-1": { + "id": "ap-southeast-1", + "name": "ap-southeast-1", + "recorders": {}, + "recorders_count": 0, + "region": "ap-southeast-1", + "rules": {}, + "rules_count": 0 + }, + "ap-southeast-2": { + "id": "ap-southeast-2", + "name": "ap-southeast-2", + "recorders": {}, + "recorders_count": 0, + "region": "ap-southeast-2", + "rules": {}, + "rules_count": 0 + }, + "ca-central-1": { + "id": "ca-central-1", + "name": "ca-central-1", + "recorders": {}, + "recorders_count": 0, + "region": "ca-central-1", + "rules": {}, + "rules_count": 0 + }, + "eu-central-1": { + "id": "eu-central-1", + "name": "eu-central-1", + "recorders": {}, + "recorders_count": 0, + "region": "eu-central-1", + "rules": {}, + "rules_count": 0 + }, + "eu-north-1": { + "id": "eu-north-1", + "name": "eu-north-1", + "recorders": {}, + "recorders_count": 0, + "region": "eu-north-1", + "rules": {}, + "rules_count": 0 + }, + "eu-west-1": { + "id": "eu-west-1", + "name": "eu-west-1", + "recorders": {}, + "recorders_count": 0, + "region": "eu-west-1", + "rules": {}, + "rules_count": 0 + }, + "eu-west-2": { + "id": "eu-west-2", + "name": "eu-west-2", + "recorders": {}, + "recorders_count": 0, + "region": "eu-west-2", + "rules": {}, + "rules_count": 0 + }, + "eu-west-3": { + "id": "eu-west-3", + "name": "eu-west-3", + "recorders": {}, + "recorders_count": 0, + "region": "eu-west-3", + "rules": {}, + "rules_count": 0 + }, + "sa-east-1": { + "id": "sa-east-1", + "name": "sa-east-1", + "recorders": {}, + "recorders_count": 0, + "region": "sa-east-1", + "rules": {}, + "rules_count": 0 + }, + "us-east-1": { + "id": "us-east-1", + "name": "us-east-1", + "recorders": {}, + "recorders_count": 0, + "region": "us-east-1", + "rules": {}, + "rules_count": 0 + }, + "us-east-2": { + "id": "us-east-2", + "name": "us-east-2", + "recorders": {}, + "recorders_count": 0, + "region": "us-east-2", + "rules": {}, + "rules_count": 0 + }, + "us-west-1": { + "id": "us-west-1", + "name": "us-west-1", + "recorders": {}, + "recorders_count": 0, + "region": "us-west-1", + "rules": {}, + "rules_count": 0 + }, + "us-west-2": { + "id": "us-west-2", + "name": "us-west-2", + "recorders": {}, + "recorders_count": 0, + "region": "us-west-2", + "rules": {}, + "rules_count": 0 + } + }, + "regions_count": 17, + "rules_count": 0 + }, + "directconnect": { + "connections_count": 0, + "filters": {}, + "findings": {}, + "regions": { + "ap-northeast-1": { + "connections": {}, + "connections_count": 0, + "id": "ap-northeast-1", + "name": "ap-northeast-1", + "region": "ap-northeast-1" + }, + "ap-northeast-2": { + "connections": {}, + "connections_count": 0, + "id": "ap-northeast-2", + "name": "ap-northeast-2", + "region": "ap-northeast-2" + }, + "ap-northeast-3": { + "connections": {}, + "connections_count": 0, + "id": "ap-northeast-3", + "name": "ap-northeast-3", + "region": "ap-northeast-3" + }, + "ap-south-1": { + "connections": {}, + "connections_count": 0, + "id": "ap-south-1", + "name": "ap-south-1", + "region": "ap-south-1" + }, + "ap-southeast-1": { + "connections": {}, + "connections_count": 0, + "id": "ap-southeast-1", + "name": "ap-southeast-1", + "region": "ap-southeast-1" + }, + "ap-southeast-2": { + "connections": {}, + "connections_count": 0, + "id": "ap-southeast-2", + "name": "ap-southeast-2", + "region": "ap-southeast-2" + }, + "ca-central-1": { + "connections": {}, + "connections_count": 0, + "id": "ca-central-1", + "name": "ca-central-1", + "region": "ca-central-1" + }, + "eu-central-1": { + "connections": {}, + "connections_count": 0, + "id": "eu-central-1", + "name": "eu-central-1", + "region": "eu-central-1" + }, + "eu-north-1": { + "connections": {}, + "connections_count": 0, + "id": "eu-north-1", + "name": "eu-north-1", + "region": "eu-north-1" + }, + "eu-west-1": { + "connections": {}, + "connections_count": 0, + "id": "eu-west-1", + "name": "eu-west-1", + "region": "eu-west-1" + }, + "eu-west-2": { + "connections": {}, + "connections_count": 0, + "id": "eu-west-2", + "name": "eu-west-2", + "region": "eu-west-2" + }, + "eu-west-3": { + "connections": {}, + "connections_count": 0, + "id": "eu-west-3", + "name": "eu-west-3", + "region": "eu-west-3" + }, + "sa-east-1": { + "connections": {}, + "connections_count": 0, + "id": "sa-east-1", + "name": "sa-east-1", + "region": "sa-east-1" + }, + "us-east-1": { + "connections": {}, + "connections_count": 0, + "id": "us-east-1", + "name": "us-east-1", + "region": "us-east-1" + }, + "us-east-2": { + "connections": {}, + "connections_count": 0, + "id": "us-east-2", + "name": "us-east-2", + "region": "us-east-2" + }, + "us-west-1": { + "connections": {}, + "connections_count": 0, + "id": "us-west-1", + "name": "us-west-1", + "region": "us-west-1" + }, + "us-west-2": { + "connections": {}, + "connections_count": 0, + "id": "us-west-2", + "name": "us-west-2", + "region": "us-west-2" + } + }, + "regions_count": 17 + }, + "dynamodb": { + "filters": {}, + "findings": {}, + "regions": { + "ap-northeast-1": { + "id": "ap-northeast-1", + "name": "ap-northeast-1", + "region": "ap-northeast-1", + "tables": {}, + "tables_count": 0 + }, + "ap-northeast-2": { + "id": "ap-northeast-2", + "name": "ap-northeast-2", + "region": "ap-northeast-2", + "tables": {}, + "tables_count": 0 + }, + "ap-northeast-3": { + "id": "ap-northeast-3", + "name": "ap-northeast-3", + "region": "ap-northeast-3", + "tables": {}, + "tables_count": 0 + }, + "ap-south-1": { + "id": "ap-south-1", + "name": "ap-south-1", + "region": "ap-south-1", + "tables": {}, + "tables_count": 0 + }, + "ap-southeast-1": { + "id": "ap-southeast-1", + "name": "ap-southeast-1", + "region": "ap-southeast-1", + "tables": {}, + "tables_count": 0 + }, + "ap-southeast-2": { + "id": "ap-southeast-2", + "name": "ap-southeast-2", + "region": "ap-southeast-2", + "tables": {}, + "tables_count": 0 + }, + "ca-central-1": { + "id": "ca-central-1", + "name": "ca-central-1", + "region": "ca-central-1", + "tables": {}, + "tables_count": 0 + }, + "eu-central-1": { + "id": "eu-central-1", + "name": "eu-central-1", + "region": "eu-central-1", + "tables": {}, + "tables_count": 0 + }, + "eu-north-1": { + "id": "eu-north-1", + "name": "eu-north-1", + "region": "eu-north-1", + "tables": {}, + "tables_count": 0 + }, + "eu-west-1": { + "id": "eu-west-1", + "name": "eu-west-1", + "region": "eu-west-1", + "tables": {}, + "tables_count": 0 + }, + "eu-west-2": { + "id": "eu-west-2", + "name": "eu-west-2", + "region": "eu-west-2", + "tables": {}, + "tables_count": 0 + }, + "eu-west-3": { + "id": "eu-west-3", + "name": "eu-west-3", + "region": "eu-west-3", + "tables": {}, + "tables_count": 0 + }, + "sa-east-1": { + "id": "sa-east-1", + "name": "sa-east-1", + "region": "sa-east-1", + "tables": {}, + "tables_count": 0 + }, + "us-east-1": { + "id": "us-east-1", + "name": "us-east-1", + "region": "us-east-1", + "tables": {}, + "tables_count": 0 + }, + "us-east-2": { + "id": "us-east-2", + "name": "us-east-2", + "region": "us-east-2", + "tables": {}, + "tables_count": 0 + }, + "us-west-1": { + "id": "us-west-1", + "name": "us-west-1", + "region": "us-west-1", + "tables": {}, + "tables_count": 0 + }, + "us-west-2": { + "id": "us-west-2", + "name": "us-west-2", + "region": "us-west-2", + "tables": {}, + "tables_count": 0 + } + }, + "regions_count": 17, + "tables_count": 0 + }, + "ec2": { + "filters": { + "ec2-instance-with-open-nacls": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "ENIs", + "description": "Public instance with open NACLs", + "display_path": "ec2.regions.id.vpcs.id.instances.id", + "flagged_items": 0, + "items": [], + "level": "", + "path": "ec2.regions.id.vpcs.id.instances.id.network_interfaces.id", + "rationale": "", + "references": null, + "remediation": null, + "service": "EC2" + }, + "ec2-security-group-with-public-cidr-grant": { + "checked_items": 6, + "compliance": null, + "dashboard_name": "Rules", + "description": "Security group whitelists public CIDRs", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 6, + "items": [ + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.0-65535.cidrs.0.CIDR", + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.0.CIDR", + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.1.CIDR", + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.2.CIDR", + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.3.CIDR", + "ec2.regions.eu-west-3.vpcs.vpc-87d3fdee.security_groups.sg-000c4c21c24f75b85.rules.ingress.protocols.TCP.ports.22.cidrs.0.CIDR" + ], + "level": "", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.ingress.protocols.id.ports.id.cidrs.id.CIDR", + "rationale": null, + "references": null, + "remediation": null, + "service": "EC2" + } + }, + "findings": { + "ec2-ami-public": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Images", + "description": "Publicly Accessible AMI", + "flagged_items": 0, + "id_suffix": "image_is_public", + "items": [], + "level": "danger", + "path": "ec2.regions.id.images.id", + "rationale": "AMIs should never intentionally be made public. If they need to be shared this can be done with specific AWS accounts.", + "references": [ + "https://aws.amazon.com/security/security-bulletins/reminder-about-safely-sharing-and-using-public-amis/" + ], + "remediation": null, + "service": "EC2" + }, + "ec2-default-security-group-in-use": { + "checked_items": 20, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.4", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.4", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.3", + "version": "1.2.0" + } + ], + "dashboard_name": "Security groups", + "description": "Default Security Groups in Use", + "flagged_items": 0, + "id_suffix": "default_in_use", + "items": [], + "level": "warning", + "path": "ec2.regions.id.vpcs.id.security_groups.id", + "rationale": "The use of default security groups can indicate a lack of intentional enforcement of the principle of least privilege. Use custom security groups to ensure you are properly minimizing privilege and access.", + "references": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-cis-controls-4.3" + ], + "remediation": "Ensure resources are not within default security groups. Instead, create a custom security group tailored to each resource needs.", + "service": "EC2" + }, + "ec2-default-security-group-with-rules": { + "checked_items": 40, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.4", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.4", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.3", + "version": "1.2.0" + } + ], + "dashboard_name": "Rulesets", + "description": "Non-empty Rulesets for Default Security Groups", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 34, + "id_suffix": "default_with_rules", + "items": [ + "ec2.regions.ap-northeast-1.vpcs.vpc-0cbc506a.security_groups.sg-6569b32b.rules.ingress.default_with_rules", + "ec2.regions.ap-northeast-1.vpcs.vpc-0cbc506a.security_groups.sg-6569b32b.rules.egress.default_with_rules", + "ec2.regions.ap-northeast-2.vpcs.vpc-73f44e18.security_groups.sg-854e9bfe.rules.ingress.default_with_rules", + "ec2.regions.ap-northeast-2.vpcs.vpc-73f44e18.security_groups.sg-854e9bfe.rules.egress.default_with_rules", + "ec2.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.security_groups.sg-9be71df6.rules.ingress.default_with_rules", + "ec2.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.security_groups.sg-9be71df6.rules.egress.default_with_rules", + "ec2.regions.ap-south-1.vpcs.vpc-2651a14d.security_groups.sg-3e983346.rules.ingress.default_with_rules", + "ec2.regions.ap-south-1.vpcs.vpc-2651a14d.security_groups.sg-3e983346.rules.egress.default_with_rules", + "ec2.regions.ap-southeast-1.vpcs.vpc-04ed1062.security_groups.sg-71eb4839.rules.ingress.default_with_rules", + "ec2.regions.ap-southeast-1.vpcs.vpc-04ed1062.security_groups.sg-71eb4839.rules.egress.default_with_rules", + "ec2.regions.ap-southeast-2.vpcs.vpc-5d22c33b.security_groups.sg-8a48ccc0.rules.ingress.default_with_rules", + "ec2.regions.ap-southeast-2.vpcs.vpc-5d22c33b.security_groups.sg-8a48ccc0.rules.egress.default_with_rules", + "ec2.regions.ca-central-1.vpcs.vpc-b5113ddd.security_groups.sg-62215504.rules.ingress.default_with_rules", + "ec2.regions.ca-central-1.vpcs.vpc-b5113ddd.security_groups.sg-62215504.rules.egress.default_with_rules", + "ec2.regions.eu-central-1.vpcs.vpc-78b43312.security_groups.sg-c1194bbf.rules.ingress.default_with_rules", + "ec2.regions.eu-central-1.vpcs.vpc-78b43312.security_groups.sg-c1194bbf.rules.egress.default_with_rules", + "ec2.regions.eu-north-1.vpcs.vpc-fa259d93.security_groups.sg-09c1e96a.rules.ingress.default_with_rules", + "ec2.regions.eu-north-1.vpcs.vpc-fa259d93.security_groups.sg-09c1e96a.rules.egress.default_with_rules", + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-186a6a69.rules.ingress.default_with_rules", + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-186a6a69.rules.egress.default_with_rules", + "ec2.regions.eu-west-2.vpcs.vpc-3fa2fa57.security_groups.sg-223b755a.rules.ingress.default_with_rules", + "ec2.regions.eu-west-2.vpcs.vpc-3fa2fa57.security_groups.sg-223b755a.rules.egress.default_with_rules", + "ec2.regions.eu-west-3.vpcs.vpc-87d3fdee.security_groups.sg-4cc9d827.rules.ingress.default_with_rules", + "ec2.regions.eu-west-3.vpcs.vpc-87d3fdee.security_groups.sg-4cc9d827.rules.egress.default_with_rules", + "ec2.regions.sa-east-1.vpcs.vpc-b14fa4d7.security_groups.sg-3965844c.rules.ingress.default_with_rules", + "ec2.regions.sa-east-1.vpcs.vpc-b14fa4d7.security_groups.sg-3965844c.rules.egress.default_with_rules", + "ec2.regions.us-east-1.vpcs.vpc-ba1cbdc7.security_groups.sg-4574a94e.rules.ingress.default_with_rules", + "ec2.regions.us-east-1.vpcs.vpc-ba1cbdc7.security_groups.sg-4574a94e.rules.egress.default_with_rules", + "ec2.regions.us-east-2.vpcs.vpc-e429ad8f.security_groups.sg-a81474db.rules.ingress.default_with_rules", + "ec2.regions.us-east-2.vpcs.vpc-e429ad8f.security_groups.sg-a81474db.rules.egress.default_with_rules", + "ec2.regions.us-west-1.vpcs.vpc-6e6fa508.security_groups.sg-778f4e3e.rules.ingress.default_with_rules", + "ec2.regions.us-west-1.vpcs.vpc-6e6fa508.security_groups.sg-778f4e3e.rules.egress.default_with_rules", + "ec2.regions.us-west-2.vpcs.vpc-d45709ac.security_groups.sg-a9b5628e.rules.ingress.default_with_rules", + "ec2.regions.us-west-2.vpcs.vpc-d45709ac.security_groups.sg-a9b5628e.rules.egress.default_with_rules" + ], + "level": "warning", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id", + "rationale": "The default security group created in each VPC comes with rules allowing all inbound traffic from instances assigned to the same security group, as well as all outbound traffic. In order to improve system hardening, you should remove all rules from the default security groups so that they restricts all traffic. Should an instance be created without custom security groups, it will inherit the default security group and be unable to communicate with other instances within the VPC until the required custom security groups are assigned.", + "references": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-cis-controls-4.3" + ], + "remediation": "Ensure the default security group of every VPC restricts all traffic", + "service": "EC2" + }, + "ec2-ebs-snapshot-not-encrypted": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Snapshots", + "description": "EBS Snapshot Not Encrypted", + "flagged_items": 0, + "id_suffix": "encrypted", + "items": [], + "level": "danger", + "path": "ec2.regions.id.snapshots.id", + "rationale": "Data-at-rest should be encrypted.", + "references": [ + "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html" + ], + "remediation": null, + "service": "EC2" + }, + "ec2-ebs-snapshot-public": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Snapshots", + "description": "Public EBS Snapshot", + "flagged_items": 0, + "id_suffix": "public", + "items": [], + "level": "danger", + "path": "ec2.regions.id.snapshots.id", + "rationale": "Snapshots should never be public, as this risks exposing sensitive data.", + "references": [ + "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-modifying-snapshot-permissions.html" + ], + "remediation": null, + "service": "EC2" + }, + "ec2-ebs-volume-not-encrypted": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Volumes", + "description": "EBS Volume Not Encrypted", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "ec2.regions.id.volumes.id", + "rationale": "Enabling encryption of EBS volumes ensures that data is encrypted both at-rest and in-transit (between an instance and its attached EBS storage).", + "references": [ + "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html" + ], + "remediation": null, + "service": "EC2" + }, + "ec2-instance-with-user-data-secrets": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Instances", + "description": "Potential Secret in Instance User Data", + "flagged_items": 0, + "id_suffix": "potential_secrets", + "items": [], + "level": "danger", + "path": "ec2.regions.id.vpcs.id.instances.id", + "rationale": "It was detected that the EC2 instance was configured with user data, which could potentially include secrets. Although user data can only be accessed from within the instance itself, the data is not protected by cryptographic methods. Anyone who can access the instance can view its metadata. It should therefore be ensured that sensitive data, such as passwords and SSH keys, are not stored as user data.", + "references": [ + "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html" + ], + "remediation": null, + "service": "EC2" + }, + "ec2-security-group-opens-DNS-port-to-all": { + "checked_items": 26, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.2.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.2.0" + } + ], + "dashboard_name": "Rules", + "description": "Security Group Opens DNS Port to All", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR", + "rationale": "The security group was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.", + "references": null, + "remediation": "Remove the inbound rules that expose open ports", + "service": "EC2" + }, + "ec2-security-group-opens-MongoDB-port-to-all": { + "checked_items": 26, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.2.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.2.0" + } + ], + "dashboard_name": "Rules", + "description": "Security Group Opens MongoDB Port to All", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR", + "rationale": "The security group was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.", + "references": null, + "remediation": "Remove the inbound rules that expose open ports", + "service": "EC2" + }, + "ec2-security-group-opens-MsSQL-port-to-all": { + "checked_items": 26, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.2.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.2.0" + } + ], + "dashboard_name": "Rules", + "description": "Security Group Opens MsSQL Port to All", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR", + "rationale": "The security group was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.", + "references": null, + "remediation": "Remove the inbound rules that expose open ports", + "service": "EC2" + }, + "ec2-security-group-opens-MySQL-port-to-all": { + "checked_items": 26, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.2.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.2.0" + } + ], + "dashboard_name": "Rules", + "description": "Security Group Opens MySQL Port to All", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR", + "rationale": "The security group was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.", + "references": null, + "remediation": "Remove the inbound rules that expose open ports", + "service": "EC2" + }, + "ec2-security-group-opens-NFS-port-to-all": { + "checked_items": 26, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.2.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.2.0" + } + ], + "dashboard_name": "Rules", + "description": "Security Group Opens NFS Port to All", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR", + "rationale": "The security group was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.", + "references": null, + "remediation": "Remove the inbound rules that expose open ports", + "service": "EC2" + }, + "ec2-security-group-opens-Oracle DB-port-to-all": { + "checked_items": 26, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.2.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.2.0" + } + ], + "dashboard_name": "Rules", + "description": "Security Group Opens Oracle DB Port to All", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR", + "rationale": "The security group was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.", + "references": null, + "remediation": "Remove the inbound rules that expose open ports", + "service": "EC2" + }, + "ec2-security-group-opens-PostgreSQL-port-to-all": { + "checked_items": 26, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.2.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.2.0" + } + ], + "dashboard_name": "Rules", + "description": "Security Group Opens PostgreSQL Port to All", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR", + "rationale": "The security group was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.", + "references": null, + "remediation": "Remove the inbound rules that expose open ports", + "service": "EC2" + }, + "ec2-security-group-opens-RDP-port-to-all": { + "checked_items": 26, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.2.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.2.0" + } + ], + "dashboard_name": "Rules", + "description": "Security Group Opens RDP Port to All", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR", + "rationale": "The security group was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.", + "references": null, + "remediation": "Remove the inbound rules that expose open ports", + "service": "EC2" + }, + "ec2-security-group-opens-SMTP-port-to-all": { + "checked_items": 26, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.2.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.2.0" + } + ], + "dashboard_name": "Rules", + "description": "Security Group Opens SMTP Port to All", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR", + "rationale": "The security group was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.", + "references": null, + "remediation": "Remove the inbound rules that expose open ports", + "service": "EC2" + }, + "ec2-security-group-opens-SSH-port-to-all": { + "checked_items": 26, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.1", + "version": "1.2.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.2", + "version": "1.2.0" + } + ], + "dashboard_name": "Rules", + "description": "Security Group Opens SSH Port to All", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR", + "rationale": "The security group was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.", + "references": null, + "remediation": "Remove the inbound rules that expose open ports", + "service": "EC2" + }, + "ec2-security-group-opens-TCP-port-to-all": { + "checked_items": 26, + "compliance": null, + "dashboard_name": "Rules", + "description": "Security Group Opens TCP Port to All", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR", + "rationale": "The security group was found to be exposing a port to all source addresses. Ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.", + "references": null, + "remediation": null, + "service": "EC2" + }, + "ec2-security-group-opens-UDP-port-to-all": { + "checked_items": 26, + "compliance": null, + "dashboard_name": "Rules", + "description": "Security Group Opens UDP Port to All", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR", + "rationale": "The security group was found to be exposing a port to all source addresses. Ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.", + "references": null, + "remediation": null, + "service": "EC2" + }, + "ec2-security-group-opens-all-ports": { + "checked_items": 45, + "compliance": null, + "dashboard_name": "Rules", + "description": "Security Group Opens All Ports", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 21, + "items": [ + "ec2.regions.ap-northeast-1.vpcs.vpc-0cbc506a.security_groups.sg-6569b32b.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.ap-northeast-2.vpcs.vpc-73f44e18.security_groups.sg-854e9bfe.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.security_groups.sg-9be71df6.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.ap-south-1.vpcs.vpc-2651a14d.security_groups.sg-3e983346.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.ap-southeast-1.vpcs.vpc-04ed1062.security_groups.sg-71eb4839.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.ap-southeast-2.vpcs.vpc-5d22c33b.security_groups.sg-8a48ccc0.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.ca-central-1.vpcs.vpc-b5113ddd.security_groups.sg-62215504.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.eu-central-1.vpcs.vpc-78b43312.security_groups.sg-c1194bbf.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.eu-north-1.vpcs.vpc-fa259d93.security_groups.sg-09c1e96a.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-02063087593480392.rules.ingress.protocols.TCP.ports.0-65535", + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-02063087593480392.rules.ingress.protocols.UDP.ports.0-65535", + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.0-65535", + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.UDP.ports.0-65535", + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-186a6a69.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.eu-west-2.vpcs.vpc-3fa2fa57.security_groups.sg-223b755a.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.eu-west-3.vpcs.vpc-87d3fdee.security_groups.sg-4cc9d827.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.sa-east-1.vpcs.vpc-b14fa4d7.security_groups.sg-3965844c.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.us-east-1.vpcs.vpc-ba1cbdc7.security_groups.sg-4574a94e.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.us-east-2.vpcs.vpc-e429ad8f.security_groups.sg-a81474db.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.us-west-1.vpcs.vpc-6e6fa508.security_groups.sg-778f4e3e.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.us-west-2.vpcs.vpc-d45709ac.security_groups.sg-a9b5628e.rules.ingress.protocols.ALL.ports.1-65535" + ], + "level": "warning", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id", + "rationale": "It was detected that all ports in the security group are open, which creates a wider attack surface for resources assigned to it. Open ports should be reduced to the minimum needed to correctly operate.", + "references": null, + "remediation": null, + "service": "EC2" + }, + "ec2-security-group-opens-all-ports-to-all": { + "checked_items": 26, + "compliance": null, + "dashboard_name": "Rules", + "description": "Security Group Opens All Ports to All", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR", + "rationale": "It was detected that all ports in the security group are open, and any source IP address could send traffic to these ports, which creates a wider attack surface for resources assigned to it. Open ports should be reduced to the minimum needed to correctly operate and, when possible, source address restrictions should be implemented.", + "references": null, + "remediation": null, + "service": "EC2" + }, + "ec2-security-group-opens-all-ports-to-self": { + "checked_items": 29, + "compliance": null, + "dashboard_name": "Rules", + "description": "Unrestricted Network Traffic within Security Group", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 21, + "items": [ + "ec2.regions.ap-northeast-1.vpcs.vpc-0cbc506a.security_groups.sg-6569b32b.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0", + "ec2.regions.ap-northeast-2.vpcs.vpc-73f44e18.security_groups.sg-854e9bfe.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0", + "ec2.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.security_groups.sg-9be71df6.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0", + "ec2.regions.ap-south-1.vpcs.vpc-2651a14d.security_groups.sg-3e983346.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0", + "ec2.regions.ap-southeast-1.vpcs.vpc-04ed1062.security_groups.sg-71eb4839.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0", + "ec2.regions.ap-southeast-2.vpcs.vpc-5d22c33b.security_groups.sg-8a48ccc0.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0", + "ec2.regions.ca-central-1.vpcs.vpc-b5113ddd.security_groups.sg-62215504.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0", + "ec2.regions.eu-central-1.vpcs.vpc-78b43312.security_groups.sg-c1194bbf.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0", + "ec2.regions.eu-north-1.vpcs.vpc-fa259d93.security_groups.sg-09c1e96a.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0", + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-02063087593480392.rules.ingress.protocols.TCP.ports.0-65535.security_groups.0", + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-02063087593480392.rules.ingress.protocols.UDP.ports.0-65535.security_groups.1", + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.0-65535.security_groups.1", + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.UDP.ports.0-65535.security_groups.0", + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-186a6a69.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0", + "ec2.regions.eu-west-2.vpcs.vpc-3fa2fa57.security_groups.sg-223b755a.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0", + "ec2.regions.eu-west-3.vpcs.vpc-87d3fdee.security_groups.sg-4cc9d827.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0", + "ec2.regions.sa-east-1.vpcs.vpc-b14fa4d7.security_groups.sg-3965844c.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0", + "ec2.regions.us-east-1.vpcs.vpc-ba1cbdc7.security_groups.sg-4574a94e.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0", + "ec2.regions.us-east-2.vpcs.vpc-e429ad8f.security_groups.sg-a81474db.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0", + "ec2.regions.us-west-1.vpcs.vpc-6e6fa508.security_groups.sg-778f4e3e.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0", + "ec2.regions.us-west-2.vpcs.vpc-d45709ac.security_groups.sg-a9b5628e.rules.ingress.protocols.ALL.ports.1-65535.security_groups.0" + ], + "level": "warning", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.security_groups.id", + "rationale": "This configuration goes against organizational policies.", + "references": null, + "remediation": null, + "service": "EC2" + }, + "ec2-security-group-opens-icmp-to-all": { + "checked_items": 26, + "compliance": null, + "dashboard_name": "Rules", + "description": "Security Group Allows ICMP Traffic to All", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR", + "rationale": "ICMP traffic was allowed to the resources assigned to this security group without restriction of the source address. This could potentially be leveraged by an attacker trying to perform an attack or gather information about the deployed infrastructure.", + "references": null, + "remediation": null, + "service": "EC2" + }, + "ec2-security-group-opens-plaintext-port-FTP": { + "checked_items": 45, + "compliance": null, + "dashboard_name": "Rules", + "description": "Security Group Opens FTP Port", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id", + "rationale": "Ports associated with plaintext protocols have been found to be open in this security group. Plaintext protocols should be replaced with more secure alternatives, as the data in transit may be monitored and could, potentially, be subject to tampering.", + "references": null, + "remediation": null, + "service": "EC2" + }, + "ec2-security-group-opens-plaintext-port-Telnet": { + "checked_items": 45, + "compliance": null, + "dashboard_name": "Rules", + "description": "Security Group Opens Telnet Port", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id", + "rationale": "Ports associated with plaintext protocols have been found to be open in this security group. Plaintext protocols should be replaced with more secure alternatives, as the data in transit may be monitored and could, potentially, be subject to tampering.", + "references": null, + "remediation": null, + "service": "EC2" + }, + "ec2-security-group-opens-port-range": { + "checked_items": 45, + "compliance": null, + "dashboard_name": "Rules", + "description": "Security Group Uses Port Range", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 17, + "items": [ + "ec2.regions.ap-northeast-1.vpcs.vpc-0cbc506a.security_groups.sg-6569b32b.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.ap-northeast-2.vpcs.vpc-73f44e18.security_groups.sg-854e9bfe.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.security_groups.sg-9be71df6.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.ap-south-1.vpcs.vpc-2651a14d.security_groups.sg-3e983346.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.ap-southeast-1.vpcs.vpc-04ed1062.security_groups.sg-71eb4839.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.ap-southeast-2.vpcs.vpc-5d22c33b.security_groups.sg-8a48ccc0.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.ca-central-1.vpcs.vpc-b5113ddd.security_groups.sg-62215504.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.eu-central-1.vpcs.vpc-78b43312.security_groups.sg-c1194bbf.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.eu-north-1.vpcs.vpc-fa259d93.security_groups.sg-09c1e96a.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-186a6a69.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.eu-west-2.vpcs.vpc-3fa2fa57.security_groups.sg-223b755a.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.eu-west-3.vpcs.vpc-87d3fdee.security_groups.sg-4cc9d827.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.sa-east-1.vpcs.vpc-b14fa4d7.security_groups.sg-3965844c.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.us-east-1.vpcs.vpc-ba1cbdc7.security_groups.sg-4574a94e.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.us-east-2.vpcs.vpc-e429ad8f.security_groups.sg-a81474db.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.us-west-1.vpcs.vpc-6e6fa508.security_groups.sg-778f4e3e.rules.ingress.protocols.ALL.ports.1-65535", + "ec2.regions.us-west-2.vpcs.vpc-d45709ac.security_groups.sg-a9b5628e.rules.ingress.protocols.ALL.ports.1-65535" + ], + "level": "warning", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id", + "rationale": "It was found that the security group was using port ranges. Sometimes, ranges could include unintended ports that should not be exposed. As a result, when possible, explicit port lists should be used instead", + "references": null, + "remediation": null, + "service": "EC2" + }, + "ec2-security-group-whitelists-aws": { + "checked_items": 26, + "compliance": null, + "dashboard_name": "Rules", + "description": "Security Group Whitelists AWS CIDRs", + "display_path": "ec2.regions.id.vpcs.id.security_groups.id", + "flagged_items": 4, + "items": [ + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.0.CIDR", + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.1.CIDR", + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.2.CIDR", + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.3.CIDR" + ], + "level": "danger", + "path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR", + "rationale": "The AWS IP ranges contain addresses which can be assigned to EC2 instances in any AWS account, as well as services which can be used to interact with any AWS account. Consequently, allowing these ranges potentially exposes your AWS account to external interactions.", + "references": null, + "remediation": null, + "service": "EC2" + }, + "ec2-unused-security-group": { + "checked_items": 20, + "compliance": null, + "dashboard_name": "Security groups", + "description": "Unused Security Group", + "flagged_items": 3, + "items": [ + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-02063087593480392", + "ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171", + "ec2.regions.eu-west-3.vpcs.vpc-87d3fdee.security_groups.sg-000c4c21c24f75b85" + ], + "level": "warning", + "path": "ec2.regions.id.vpcs.id.security_groups.id", + "rationale": " Non-default security groups were defined which were unused and may not be required. This being the case, their existence in the configuration increases the risk that they may be inappropriately assigned. The unused security groups should be reviewed and removed if no longer required.", + "references": [ + "https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html" + ], + "remediation": null, + "service": "EC2" + } + }, + "images_count": 0, + "instances_count": 0, + "network_interfaces_count": 0, + "number_of_regions_with_instances": 0, + "regions": { + "ap-northeast-1": { + "id": "ap-northeast-1", + "images": {}, + "images_count": 0, + "instances_availability_zones": 0, + "instances_count": 0, + "name": "ap-northeast-1", + "network_interfaces_count": 0, + "region": "ap-northeast-1", + "security_groups_count": 1, + "snapshots": {}, + "snapshots_count": 0, + "volumes": {}, + "volumes_count": 0, + "vpcs": { + "vpc-0cbc506a": { + "arn": "arn:aws:vpc:ap-northeast-1:430150006394:virtual-private-cloud/vpc-0cbc506a", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-0cbc506a", + "instances": {}, + "instances_count": 0, + "name": "vpc-0cbc506a", + "network_interfaces": {}, + "network_interfaces_count": 0, + "security_groups": { + "sg-6569b32b": { + "arn": "arn:aws:ec2:ap-northeast-1:430150006394:security-group/sg-6569b32b", + "description": "default VPC security group", + "id": "sg-6569b32b", + "is_default_configuration": true, + "name": "default", + "owner_id": "430150006394", + "rules": { + "egress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "cidrs": [ + { + "CIDR": "0.0.0.0/0" + } + ] + } + } + } + } + }, + "ingress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "security_groups": [ + { + "GroupId": "sg-6569b32b", + "GroupName": "default", + "UserId": "430150006394" + } + ] + } + } + } + } + } + } + } + }, + "security_groups_count": 1, + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ap-northeast-2": { + "id": "ap-northeast-2", + "images": {}, + "images_count": 0, + "instances_availability_zones": 0, + "instances_count": 0, + "name": "ap-northeast-2", + "network_interfaces_count": 0, + "region": "ap-northeast-2", + "security_groups_count": 1, + "snapshots": {}, + "snapshots_count": 0, + "volumes": {}, + "volumes_count": 0, + "vpcs": { + "vpc-73f44e18": { + "arn": "arn:aws:vpc:ap-northeast-2:430150006394:virtual-private-cloud/vpc-73f44e18", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-73f44e18", + "instances": {}, + "instances_count": 0, + "name": "vpc-73f44e18", + "network_interfaces": {}, + "network_interfaces_count": 0, + "security_groups": { + "sg-854e9bfe": { + "arn": "arn:aws:ec2:ap-northeast-2:430150006394:security-group/sg-854e9bfe", + "description": "default VPC security group", + "id": "sg-854e9bfe", + "is_default_configuration": true, + "name": "default", + "owner_id": "430150006394", + "rules": { + "egress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "cidrs": [ + { + "CIDR": "0.0.0.0/0" + } + ] + } + } + } + } + }, + "ingress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "security_groups": [ + { + "GroupId": "sg-854e9bfe", + "GroupName": "default", + "UserId": "430150006394" + } + ] + } + } + } + } + } + } + } + }, + "security_groups_count": 1, + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ap-northeast-3": { + "id": "ap-northeast-3", + "images": {}, + "images_count": 0, + "instances_availability_zones": 0, + "instances_count": 0, + "name": "ap-northeast-3", + "network_interfaces_count": 0, + "region": "ap-northeast-3", + "security_groups_count": 1, + "snapshots": {}, + "snapshots_count": 0, + "volumes": {}, + "volumes_count": 0, + "vpcs": { + "vpc-47b7dd2e": { + "arn": "arn:aws:vpc:ap-northeast-3:430150006394:virtual-private-cloud/vpc-47b7dd2e", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-47b7dd2e", + "instances": {}, + "instances_count": 0, + "name": "vpc-47b7dd2e", + "network_interfaces": {}, + "network_interfaces_count": 0, + "security_groups": { + "sg-9be71df6": { + "arn": "arn:aws:ec2:ap-northeast-3:430150006394:security-group/sg-9be71df6", + "description": "default VPC security group", + "id": "sg-9be71df6", + "is_default_configuration": true, + "name": "default", + "owner_id": "430150006394", + "rules": { + "egress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "cidrs": [ + { + "CIDR": "0.0.0.0/0" + } + ] + } + } + } + } + }, + "ingress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "security_groups": [ + { + "GroupId": "sg-9be71df6", + "GroupName": "default", + "UserId": "430150006394" + } + ] + } + } + } + } + } + } + } + }, + "security_groups_count": 1, + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ap-south-1": { + "id": "ap-south-1", + "images": {}, + "images_count": 0, + "instances_availability_zones": 0, + "instances_count": 0, + "name": "ap-south-1", + "network_interfaces_count": 0, + "region": "ap-south-1", + "security_groups_count": 1, + "snapshots": {}, + "snapshots_count": 0, + "volumes": {}, + "volumes_count": 0, + "vpcs": { + "vpc-2651a14d": { + "arn": "arn:aws:vpc:ap-south-1:430150006394:virtual-private-cloud/vpc-2651a14d", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-2651a14d", + "instances": {}, + "instances_count": 0, + "name": "vpc-2651a14d", + "network_interfaces": {}, + "network_interfaces_count": 0, + "security_groups": { + "sg-3e983346": { + "arn": "arn:aws:ec2:ap-south-1:430150006394:security-group/sg-3e983346", + "description": "default VPC security group", + "id": "sg-3e983346", + "is_default_configuration": true, + "name": "default", + "owner_id": "430150006394", + "rules": { + "egress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "cidrs": [ + { + "CIDR": "0.0.0.0/0" + } + ] + } + } + } + } + }, + "ingress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "security_groups": [ + { + "GroupId": "sg-3e983346", + "GroupName": "default", + "UserId": "430150006394" + } + ] + } + } + } + } + } + } + } + }, + "security_groups_count": 1, + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ap-southeast-1": { + "id": "ap-southeast-1", + "images": {}, + "images_count": 0, + "instances_availability_zones": 0, + "instances_count": 0, + "name": "ap-southeast-1", + "network_interfaces_count": 0, + "region": "ap-southeast-1", + "security_groups_count": 1, + "snapshots": {}, + "snapshots_count": 0, + "volumes": {}, + "volumes_count": 0, + "vpcs": { + "vpc-04ed1062": { + "arn": "arn:aws:vpc:ap-southeast-1:430150006394:virtual-private-cloud/vpc-04ed1062", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-04ed1062", + "instances": {}, + "instances_count": 0, + "name": "vpc-04ed1062", + "network_interfaces": {}, + "network_interfaces_count": 0, + "security_groups": { + "sg-71eb4839": { + "arn": "arn:aws:ec2:ap-southeast-1:430150006394:security-group/sg-71eb4839", + "description": "default VPC security group", + "id": "sg-71eb4839", + "is_default_configuration": true, + "name": "default", + "owner_id": "430150006394", + "rules": { + "egress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "cidrs": [ + { + "CIDR": "0.0.0.0/0" + } + ] + } + } + } + } + }, + "ingress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "security_groups": [ + { + "GroupId": "sg-71eb4839", + "GroupName": "default", + "UserId": "430150006394" + } + ] + } + } + } + } + } + } + } + }, + "security_groups_count": 1, + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ap-southeast-2": { + "id": "ap-southeast-2", + "images": {}, + "images_count": 0, + "instances_availability_zones": 0, + "instances_count": 0, + "name": "ap-southeast-2", + "network_interfaces_count": 0, + "region": "ap-southeast-2", + "security_groups_count": 1, + "snapshots": {}, + "snapshots_count": 0, + "volumes": {}, + "volumes_count": 0, + "vpcs": { + "vpc-5d22c33b": { + "arn": "arn:aws:vpc:ap-southeast-2:430150006394:virtual-private-cloud/vpc-5d22c33b", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-5d22c33b", + "instances": {}, + "instances_count": 0, + "name": "vpc-5d22c33b", + "network_interfaces": {}, + "network_interfaces_count": 0, + "security_groups": { + "sg-8a48ccc0": { + "arn": "arn:aws:ec2:ap-southeast-2:430150006394:security-group/sg-8a48ccc0", + "description": "default VPC security group", + "id": "sg-8a48ccc0", + "is_default_configuration": true, + "name": "default", + "owner_id": "430150006394", + "rules": { + "egress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "cidrs": [ + { + "CIDR": "0.0.0.0/0" + } + ] + } + } + } + } + }, + "ingress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "security_groups": [ + { + "GroupId": "sg-8a48ccc0", + "GroupName": "default", + "UserId": "430150006394" + } + ] + } + } + } + } + } + } + } + }, + "security_groups_count": 1, + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ca-central-1": { + "id": "ca-central-1", + "images": {}, + "images_count": 0, + "instances_availability_zones": 0, + "instances_count": 0, + "name": "ca-central-1", + "network_interfaces_count": 0, + "region": "ca-central-1", + "security_groups_count": 1, + "snapshots": {}, + "snapshots_count": 0, + "volumes": {}, + "volumes_count": 0, + "vpcs": { + "vpc-b5113ddd": { + "arn": "arn:aws:vpc:ca-central-1:430150006394:virtual-private-cloud/vpc-b5113ddd", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-b5113ddd", + "instances": {}, + "instances_count": 0, + "name": "vpc-b5113ddd", + "network_interfaces": {}, + "network_interfaces_count": 0, + "security_groups": { + "sg-62215504": { + "arn": "arn:aws:ec2:ca-central-1:430150006394:security-group/sg-62215504", + "description": "default VPC security group", + "id": "sg-62215504", + "is_default_configuration": true, + "name": "default", + "owner_id": "430150006394", + "rules": { + "egress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "cidrs": [ + { + "CIDR": "0.0.0.0/0" + } + ] + } + } + } + } + }, + "ingress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "security_groups": [ + { + "GroupId": "sg-62215504", + "GroupName": "default", + "UserId": "430150006394" + } + ] + } + } + } + } + } + } + } + }, + "security_groups_count": 1, + "state": "available" + } + }, + "vpcs_count": 1 + }, + "eu-central-1": { + "id": "eu-central-1", + "images": {}, + "images_count": 0, + "instances_availability_zones": 0, + "instances_count": 0, + "name": "eu-central-1", + "network_interfaces_count": 0, + "region": "eu-central-1", + "security_groups_count": 1, + "snapshots": {}, + "snapshots_count": 0, + "volumes": {}, + "volumes_count": 0, + "vpcs": { + "vpc-78b43312": { + "arn": "arn:aws:vpc:eu-central-1:430150006394:virtual-private-cloud/vpc-78b43312", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-78b43312", + "instances": {}, + "instances_count": 0, + "name": "vpc-78b43312", + "network_interfaces": {}, + "network_interfaces_count": 0, + "security_groups": { + "sg-c1194bbf": { + "arn": "arn:aws:ec2:eu-central-1:430150006394:security-group/sg-c1194bbf", + "description": "default VPC security group", + "id": "sg-c1194bbf", + "is_default_configuration": true, + "name": "default", + "owner_id": "430150006394", + "rules": { + "egress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "cidrs": [ + { + "CIDR": "0.0.0.0/0" + } + ] + } + } + } + } + }, + "ingress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "security_groups": [ + { + "GroupId": "sg-c1194bbf", + "GroupName": "default", + "UserId": "430150006394" + } + ] + } + } + } + } + } + } + } + }, + "security_groups_count": 1, + "state": "available" + } + }, + "vpcs_count": 1 + }, + "eu-north-1": { + "id": "eu-north-1", + "images": {}, + "images_count": 0, + "instances_availability_zones": 0, + "instances_count": 0, + "name": "eu-north-1", + "network_interfaces_count": 0, + "region": "eu-north-1", + "security_groups_count": 1, + "snapshots": {}, + "snapshots_count": 0, + "volumes": {}, + "volumes_count": 0, + "vpcs": { + "vpc-fa259d93": { + "arn": "arn:aws:vpc:eu-north-1:430150006394:virtual-private-cloud/vpc-fa259d93", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-fa259d93", + "instances": {}, + "instances_count": 0, + "name": "vpc-fa259d93", + "network_interfaces": {}, + "network_interfaces_count": 0, + "security_groups": { + "sg-09c1e96a": { + "arn": "arn:aws:ec2:eu-north-1:430150006394:security-group/sg-09c1e96a", + "description": "default VPC security group", + "id": "sg-09c1e96a", + "is_default_configuration": true, + "name": "default", + "owner_id": "430150006394", + "rules": { + "egress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "cidrs": [ + { + "CIDR": "0.0.0.0/0" + } + ] + } + } + } + } + }, + "ingress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "security_groups": [ + { + "GroupId": "sg-09c1e96a", + "GroupName": "default", + "UserId": "430150006394" + } + ] + } + } + } + } + } + } + } + }, + "security_groups_count": 1, + "state": "available" + } + }, + "vpcs_count": 1 + }, + "eu-west-1": { + "id": "eu-west-1", + "images": {}, + "images_count": 0, + "instances_availability_zones": 0, + "instances_count": 0, + "name": "eu-west-1", + "network_interfaces_count": 0, + "region": "eu-west-1", + "security_groups_count": 3, + "snapshots": {}, + "snapshots_count": 0, + "volumes": {}, + "volumes_count": 0, + "vpcs": { + "vpc-f24c7994": { + "arn": "arn:aws:vpc:eu-west-1:430150006394:virtual-private-cloud/vpc-f24c7994", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-f24c7994", + "instances": {}, + "instances_count": 0, + "name": "vpc-f24c7994", + "network_interfaces": {}, + "network_interfaces_count": 0, + "security_groups": { + "sg-02063087593480392": { + "arn": "arn:aws:ec2:eu-west-1:430150006394:security-group/sg-02063087593480392", + "description": "Slave group for Elastic MapReduce created on 2019-01-26T08:00:38.387Z", + "id": "sg-02063087593480392", + "is_default_configuration": false, + "name": "ElasticMapReduce-slave", + "owner_id": "430150006394", + "rules": { + "egress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "cidrs": [ + { + "CIDR": "0.0.0.0/0" + } + ] + } + } + } + } + }, + "ingress": { + "count": 6, + "protocols": { + "ICMP": { + "ports": { + "ALL": { + "security_groups": [ + { + "GroupId": "sg-0c59ae38c42100171", + "GroupName": "ElasticMapReduce-master", + "UserId": "430150006394" + }, + { + "GroupId": "sg-02063087593480392", + "GroupName": "ElasticMapReduce-slave", + "UserId": "430150006394" + } + ] + } + } + }, + "TCP": { + "ports": { + "0-65535": { + "security_groups": [ + { + "GroupId": "sg-02063087593480392", + "GroupName": "ElasticMapReduce-slave", + "UserId": "430150006394" + }, + { + "GroupId": "sg-0c59ae38c42100171", + "GroupName": "ElasticMapReduce-master", + "UserId": "430150006394" + } + ] + } + } + }, + "UDP": { + "ports": { + "0-65535": { + "security_groups": [ + { + "GroupId": "sg-0c59ae38c42100171", + "GroupName": "ElasticMapReduce-master", + "UserId": "430150006394" + }, + { + "GroupId": "sg-02063087593480392", + "GroupName": "ElasticMapReduce-slave", + "UserId": "430150006394" + } + ] + } + } + } + } + } + } + }, + "sg-0c59ae38c42100171": { + "arn": "arn:aws:ec2:eu-west-1:430150006394:security-group/sg-0c59ae38c42100171", + "description": "Master group for Elastic MapReduce created on 2019-01-26T08:00:38.387Z", + "id": "sg-0c59ae38c42100171", + "is_default_configuration": false, + "name": "ElasticMapReduce-master", + "owner_id": "430150006394", + "rules": { + "egress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "cidrs": [ + { + "CIDR": "0.0.0.0/0" + } + ] + } + } + } + } + }, + "ingress": { + "count": 11, + "protocols": { + "ICMP": { + "ports": { + "ALL": { + "security_groups": [ + { + "GroupId": "sg-0c59ae38c42100171", + "GroupName": "ElasticMapReduce-master", + "UserId": "430150006394" + }, + { + "GroupId": "sg-02063087593480392", + "GroupName": "ElasticMapReduce-slave", + "UserId": "430150006394" + } + ] + } + } + }, + "TCP": { + "ports": { + "8443": { + "cidrs": [ + { + "CIDR": "54.239.99.0/24" + }, + { + "CIDR": "54.240.197.0/24" + }, + { + "CIDR": "87.238.80.64/29" + }, + { + "CIDR": "87.238.84.64/29" + } + ] + }, + "0-65535": { + "cidrs": [ + { + "CIDR": "88.171.207.128/30" + } + ], + "security_groups": [ + { + "GroupId": "sg-02063087593480392", + "GroupName": "ElasticMapReduce-slave", + "UserId": "430150006394" + }, + { + "GroupId": "sg-0c59ae38c42100171", + "GroupName": "ElasticMapReduce-master", + "UserId": "430150006394" + } + ] + } + } + }, + "UDP": { + "ports": { + "0-65535": { + "security_groups": [ + { + "GroupId": "sg-0c59ae38c42100171", + "GroupName": "ElasticMapReduce-master", + "UserId": "430150006394" + }, + { + "GroupId": "sg-02063087593480392", + "GroupName": "ElasticMapReduce-slave", + "UserId": "430150006394" + } + ] + } + } + } + } + } + } + }, + "sg-186a6a69": { + "arn": "arn:aws:ec2:eu-west-1:430150006394:security-group/sg-186a6a69", + "description": "default VPC security group", + "id": "sg-186a6a69", + "is_default_configuration": true, + "name": "default", + "owner_id": "430150006394", + "rules": { + "egress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "cidrs": [ + { + "CIDR": "0.0.0.0/0" + } + ] + } + } + } + } + }, + "ingress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "security_groups": [ + { + "GroupId": "sg-186a6a69", + "GroupName": "default", + "UserId": "430150006394" + } + ] + } + } + } + } + } + } + } + }, + "security_groups_count": 3, + "state": "available" + } + }, + "vpcs_count": 1 + }, + "eu-west-2": { + "id": "eu-west-2", + "images": {}, + "images_count": 0, + "instances_availability_zones": 0, + "instances_count": 0, + "name": "eu-west-2", + "network_interfaces_count": 0, + "region": "eu-west-2", + "security_groups_count": 1, + "snapshots": {}, + "snapshots_count": 0, + "volumes": {}, + "volumes_count": 0, + "vpcs": { + "vpc-3fa2fa57": { + "arn": "arn:aws:vpc:eu-west-2:430150006394:virtual-private-cloud/vpc-3fa2fa57", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-3fa2fa57", + "instances": {}, + "instances_count": 0, + "name": "vpc-3fa2fa57", + "network_interfaces": {}, + "network_interfaces_count": 0, + "security_groups": { + "sg-223b755a": { + "arn": "arn:aws:ec2:eu-west-2:430150006394:security-group/sg-223b755a", + "description": "default VPC security group", + "id": "sg-223b755a", + "is_default_configuration": true, + "name": "default", + "owner_id": "430150006394", + "rules": { + "egress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "cidrs": [ + { + "CIDR": "0.0.0.0/0" + } + ] + } + } + } + } + }, + "ingress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "security_groups": [ + { + "GroupId": "sg-223b755a", + "GroupName": "default", + "UserId": "430150006394" + } + ] + } + } + } + } + } + } + } + }, + "security_groups_count": 1, + "state": "available" + } + }, + "vpcs_count": 1 + }, + "eu-west-3": { + "id": "eu-west-3", + "images": {}, + "images_count": 0, + "instances_availability_zones": 0, + "instances_count": 0, + "name": "eu-west-3", + "network_interfaces_count": 0, + "region": "eu-west-3", + "security_groups_count": 2, + "snapshots": {}, + "snapshots_count": 0, + "volumes": {}, + "volumes_count": 0, + "vpcs": { + "vpc-87d3fdee": { + "arn": "arn:aws:vpc:eu-west-3:430150006394:virtual-private-cloud/vpc-87d3fdee", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-87d3fdee", + "instances": {}, + "instances_count": 0, + "name": "vpc-87d3fdee", + "network_interfaces": {}, + "network_interfaces_count": 0, + "security_groups": { + "sg-000c4c21c24f75b85": { + "arn": "arn:aws:ec2:eu-west-3:430150006394:security-group/sg-000c4c21c24f75b85", + "description": "launch-wizard-1 created 2019-12-23T12:17:14.882+01:00", + "id": "sg-000c4c21c24f75b85", + "is_default_configuration": false, + "name": "launch-wizard-1", + "owner_id": "430150006394", + "rules": { + "egress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "cidrs": [ + { + "CIDR": "0.0.0.0/0" + } + ] + } + } + } + } + }, + "ingress": { + "count": 1, + "protocols": { + "TCP": { + "ports": { + "22": { + "cidrs": [ + { + "CIDR": "86.250.138.62/32" + } + ] + } + } + } + } + } + } + }, + "sg-4cc9d827": { + "arn": "arn:aws:ec2:eu-west-3:430150006394:security-group/sg-4cc9d827", + "description": "default VPC security group", + "id": "sg-4cc9d827", + "is_default_configuration": true, + "name": "default", + "owner_id": "430150006394", + "rules": { + "egress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "cidrs": [ + { + "CIDR": "0.0.0.0/0" + } + ] + } + } + } + } + }, + "ingress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "security_groups": [ + { + "GroupId": "sg-4cc9d827", + "GroupName": "default", + "UserId": "430150006394" + } + ] + } + } + } + } + } + } + } + }, + "security_groups_count": 2, + "state": "available" + } + }, + "vpcs_count": 1 + }, + "sa-east-1": { + "id": "sa-east-1", + "images": {}, + "images_count": 0, + "instances_availability_zones": 0, + "instances_count": 0, + "name": "sa-east-1", + "network_interfaces_count": 0, + "region": "sa-east-1", + "security_groups_count": 1, + "snapshots": {}, + "snapshots_count": 0, + "volumes": {}, + "volumes_count": 0, + "vpcs": { + "vpc-b14fa4d7": { + "arn": "arn:aws:vpc:sa-east-1:430150006394:virtual-private-cloud/vpc-b14fa4d7", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-b14fa4d7", + "instances": {}, + "instances_count": 0, + "name": "vpc-b14fa4d7", + "network_interfaces": {}, + "network_interfaces_count": 0, + "security_groups": { + "sg-3965844c": { + "arn": "arn:aws:ec2:sa-east-1:430150006394:security-group/sg-3965844c", + "description": "default VPC security group", + "id": "sg-3965844c", + "is_default_configuration": true, + "name": "default", + "owner_id": "430150006394", + "rules": { + "egress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "cidrs": [ + { + "CIDR": "0.0.0.0/0" + } + ] + } + } + } + } + }, + "ingress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "security_groups": [ + { + "GroupId": "sg-3965844c", + "GroupName": "default", + "UserId": "430150006394" + } + ] + } + } + } + } + } + } + } + }, + "security_groups_count": 1, + "state": "available" + } + }, + "vpcs_count": 1 + }, + "us-east-1": { + "id": "us-east-1", + "images": {}, + "images_count": 0, + "instances_availability_zones": 0, + "instances_count": 0, + "name": "us-east-1", + "network_interfaces_count": 0, + "region": "us-east-1", + "security_groups_count": 1, + "snapshots": {}, + "snapshots_count": 0, + "volumes": {}, + "volumes_count": 0, + "vpcs": { + "vpc-ba1cbdc7": { + "arn": "arn:aws:vpc:us-east-1:430150006394:virtual-private-cloud/vpc-ba1cbdc7", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-ba1cbdc7", + "instances": {}, + "instances_count": 0, + "name": "vpc-ba1cbdc7", + "network_interfaces": {}, + "network_interfaces_count": 0, + "security_groups": { + "sg-4574a94e": { + "arn": "arn:aws:ec2:us-east-1:430150006394:security-group/sg-4574a94e", + "description": "default VPC security group", + "id": "sg-4574a94e", + "is_default_configuration": true, + "name": "default", + "owner_id": "430150006394", + "rules": { + "egress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "cidrs": [ + { + "CIDR": "0.0.0.0/0" + } + ] + } + } + } + } + }, + "ingress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "security_groups": [ + { + "GroupId": "sg-4574a94e", + "GroupName": "default", + "UserId": "430150006394" + } + ] + } + } + } + } + } + } + } + }, + "security_groups_count": 1, + "state": "available" + } + }, + "vpcs_count": 1 + }, + "us-east-2": { + "id": "us-east-2", + "images": {}, + "images_count": 0, + "instances_availability_zones": 0, + "instances_count": 0, + "name": "us-east-2", + "network_interfaces_count": 0, + "region": "us-east-2", + "security_groups_count": 1, + "snapshots": {}, + "snapshots_count": 0, + "volumes": {}, + "volumes_count": 0, + "vpcs": { + "vpc-e429ad8f": { + "arn": "arn:aws:vpc:us-east-2:430150006394:virtual-private-cloud/vpc-e429ad8f", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-e429ad8f", + "instances": {}, + "instances_count": 0, + "name": "vpc-e429ad8f", + "network_interfaces": {}, + "network_interfaces_count": 0, + "security_groups": { + "sg-a81474db": { + "arn": "arn:aws:ec2:us-east-2:430150006394:security-group/sg-a81474db", + "description": "default VPC security group", + "id": "sg-a81474db", + "is_default_configuration": true, + "name": "default", + "owner_id": "430150006394", + "rules": { + "egress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "cidrs": [ + { + "CIDR": "0.0.0.0/0" + } + ] + } + } + } + } + }, + "ingress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "security_groups": [ + { + "GroupId": "sg-a81474db", + "GroupName": "default", + "UserId": "430150006394" + } + ] + } + } + } + } + } + } + } + }, + "security_groups_count": 1, + "state": "available" + } + }, + "vpcs_count": 1 + }, + "us-west-1": { + "id": "us-west-1", + "images": {}, + "images_count": 0, + "instances_availability_zones": 0, + "instances_count": 0, + "name": "us-west-1", + "network_interfaces_count": 0, + "region": "us-west-1", + "security_groups_count": 1, + "snapshots": {}, + "snapshots_count": 0, + "volumes": {}, + "volumes_count": 0, + "vpcs": { + "vpc-6e6fa508": { + "arn": "arn:aws:vpc:us-west-1:430150006394:virtual-private-cloud/vpc-6e6fa508", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-6e6fa508", + "instances": {}, + "instances_count": 0, + "name": "vpc-6e6fa508", + "network_interfaces": {}, + "network_interfaces_count": 0, + "security_groups": { + "sg-778f4e3e": { + "arn": "arn:aws:ec2:us-west-1:430150006394:security-group/sg-778f4e3e", + "description": "default VPC security group", + "id": "sg-778f4e3e", + "is_default_configuration": true, + "name": "default", + "owner_id": "430150006394", + "rules": { + "egress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "cidrs": [ + { + "CIDR": "0.0.0.0/0" + } + ] + } + } + } + } + }, + "ingress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "security_groups": [ + { + "GroupId": "sg-778f4e3e", + "GroupName": "default", + "UserId": "430150006394" + } + ] + } + } + } + } + } + } + } + }, + "security_groups_count": 1, + "state": "available" + } + }, + "vpcs_count": 1 + }, + "us-west-2": { + "id": "us-west-2", + "images": {}, + "images_count": 0, + "instances_availability_zones": 0, + "instances_count": 0, + "name": "us-west-2", + "network_interfaces_count": 0, + "region": "us-west-2", + "security_groups_count": 1, + "snapshots": {}, + "snapshots_count": 0, + "volumes": {}, + "volumes_count": 0, + "vpcs": { + "vpc-d45709ac": { + "arn": "arn:aws:vpc:us-west-2:430150006394:virtual-private-cloud/vpc-d45709ac", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-d45709ac", + "instances": {}, + "instances_count": 0, + "name": "vpc-d45709ac", + "network_interfaces": {}, + "network_interfaces_count": 0, + "security_groups": { + "sg-a9b5628e": { + "arn": "arn:aws:ec2:us-west-2:430150006394:security-group/sg-a9b5628e", + "description": "default VPC security group", + "id": "sg-a9b5628e", + "is_default_configuration": true, + "name": "default", + "owner_id": "430150006394", + "rules": { + "egress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "cidrs": [ + { + "CIDR": "0.0.0.0/0" + } + ] + } + } + } + } + }, + "ingress": { + "count": 1, + "protocols": { + "ALL": { + "ports": { + "1-65535": { + "security_groups": [ + { + "GroupId": "sg-a9b5628e", + "GroupName": "default", + "UserId": "430150006394" + } + ] + } + } + } + } + } + } + } + }, + "security_groups_count": 1, + "state": "available" + } + }, + "vpcs_count": 1 + } + }, + "regions_count": 17, + "security_groups_count": 20, + "snapshots_count": 0, + "volumes_count": 0 + }, + "efs": { + "filesystems_count": 0, + "filters": {}, + "findings": {}, + "regions": { + "ap-northeast-1": { + "filesystems": {}, + "filesystems_count": 0, + "id": "ap-northeast-1", + "name": "ap-northeast-1", + "region": "ap-northeast-1" + }, + "ap-northeast-2": { + "filesystems": {}, + "filesystems_count": 0, + "id": "ap-northeast-2", + "name": "ap-northeast-2", + "region": "ap-northeast-2" + }, + "ap-northeast-3": { + "filesystems": {}, + "filesystems_count": 0, + "id": "ap-northeast-3", + "name": "ap-northeast-3", + "region": "ap-northeast-3" + }, + "ap-south-1": { + "filesystems": {}, + "filesystems_count": 0, + "id": "ap-south-1", + "name": "ap-south-1", + "region": "ap-south-1" + }, + "ap-southeast-1": { + "filesystems": {}, + "filesystems_count": 0, + "id": "ap-southeast-1", + "name": "ap-southeast-1", + "region": "ap-southeast-1" + }, + "ap-southeast-2": { + "filesystems": {}, + "filesystems_count": 0, + "id": "ap-southeast-2", + "name": "ap-southeast-2", + "region": "ap-southeast-2" + }, + "ca-central-1": { + "filesystems": {}, + "filesystems_count": 0, + "id": "ca-central-1", + "name": "ca-central-1", + "region": "ca-central-1" + }, + "eu-central-1": { + "filesystems": {}, + "filesystems_count": 0, + "id": "eu-central-1", + "name": "eu-central-1", + "region": "eu-central-1" + }, + "eu-north-1": { + "filesystems": {}, + "filesystems_count": 0, + "id": "eu-north-1", + "name": "eu-north-1", + "region": "eu-north-1" + }, + "eu-west-1": { + "filesystems": {}, + "filesystems_count": 0, + "id": "eu-west-1", + "name": "eu-west-1", + "region": "eu-west-1" + }, + "eu-west-2": { + "filesystems": {}, + "filesystems_count": 0, + "id": "eu-west-2", + "name": "eu-west-2", + "region": "eu-west-2" + }, + "eu-west-3": { + "filesystems": {}, + "filesystems_count": 0, + "id": "eu-west-3", + "name": "eu-west-3", + "region": "eu-west-3" + }, + "sa-east-1": { + "filesystems": {}, + "filesystems_count": 0, + "id": "sa-east-1", + "name": "sa-east-1", + "region": "sa-east-1" + }, + "us-east-1": { + "filesystems": {}, + "filesystems_count": 0, + "id": "us-east-1", + "name": "us-east-1", + "region": "us-east-1" + }, + "us-east-2": { + "filesystems": {}, + "filesystems_count": 0, + "id": "us-east-2", + "name": "us-east-2", + "region": "us-east-2" + }, + "us-west-1": { + "filesystems": {}, + "filesystems_count": 0, + "id": "us-west-1", + "name": "us-west-1", + "region": "us-west-1" + }, + "us-west-2": { + "filesystems": {}, + "filesystems_count": 0, + "id": "us-west-2", + "name": "us-west-2", + "region": "us-west-2" + } + }, + "regions_count": 17 + }, + "elasticache": { + "clusters_count": 0, + "filters": {}, + "findings": {}, + "regions": { + "ap-northeast-1": { + "clusters_count": 0, + "id": "ap-northeast-1", + "name": "ap-northeast-1", + "parameter_groups": { + "02e3d792a7e00a39f3c9fa0bb0445e86d7644525": { + "ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.redis3.2.cluster.on", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Customized default parameter group for redis3.2 with cluster mode on", + "IsGlobal": false, + "id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525", + "name": "default.redis3.2.cluster.on" + }, + "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": { + "ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.memcached1.4", + "CacheParameterGroupFamily": "memcached1.4", + "Description": "Default parameter group for memcached1.4", + "IsGlobal": false, + "id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124", + "name": "default.memcached1.4" + }, + "1a65eec91cd66eb16ba40e781620d9320ec1733f": { + "ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.redis6.x.cluster.on", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Customized default parameter group for redis6.x with cluster mode on", + "IsGlobal": false, + "id": "1a65eec91cd66eb16ba40e781620d9320ec1733f", + "name": "default.redis6.x.cluster.on" + }, + "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": { + "ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.redis2.8", + "CacheParameterGroupFamily": "redis2.8", + "Description": "Default parameter group for redis2.8", + "IsGlobal": false, + "id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e", + "name": "default.redis2.8" + }, + "51584be5be0c6c6af057229afd341d592a55bf0e": { + "ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.memcached1.6", + "CacheParameterGroupFamily": "memcached1.6", + "Description": "Default parameter group for memcached1.6", + "IsGlobal": false, + "id": "51584be5be0c6c6af057229afd341d592a55bf0e", + "name": "default.memcached1.6" + }, + "533bd3e057f46120794828b5c797b3fe8aab1336": { + "ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.redis2.6", + "CacheParameterGroupFamily": "redis2.6", + "Description": "Default parameter group for redis2.6", + "IsGlobal": false, + "id": "533bd3e057f46120794828b5c797b3fe8aab1336", + "name": "default.redis2.6" + }, + "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": { + "ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.redis3.2", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Default parameter group for redis3.2", + "IsGlobal": false, + "id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3", + "name": "default.redis3.2" + }, + "6e3786a6f55135ca99b9432b0059a35deb2ae908": { + "ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.redis5.0", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Default parameter group for redis5.0", + "IsGlobal": false, + "id": "6e3786a6f55135ca99b9432b0059a35deb2ae908", + "name": "default.redis5.0" + }, + "89dee6407112ff413de0345de376d45c799f0028": { + "ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.redis4.0.cluster.on", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Customized default parameter group for redis4.0 with cluster mode on", + "IsGlobal": false, + "id": "89dee6407112ff413de0345de376d45c799f0028", + "name": "default.redis4.0.cluster.on" + }, + "92d124b9a74567482361fe34e367ac8bf5c02e0b": { + "ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.redis6.x", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Default parameter group for redis6.x", + "IsGlobal": false, + "id": "92d124b9a74567482361fe34e367ac8bf5c02e0b", + "name": "default.redis6.x" + }, + "a64a576f220009cfa7c322c46fc92d32a85a4978": { + "ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.redis5.0.cluster.on", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Customized default parameter group for redis5.0 with cluster mode on", + "IsGlobal": false, + "id": "a64a576f220009cfa7c322c46fc92d32a85a4978", + "name": "default.redis5.0.cluster.on" + }, + "c954e04f298cd030c6fde9c32c8365d1b9f76fb4": { + "ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.redis4.0", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Default parameter group for redis4.0", + "IsGlobal": false, + "id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4", + "name": "default.redis4.0" + }, + "e0934919fe4741105df762ae57b738fea22ebc40": { + "ARN": "arn:aws:elasticache:ap-northeast-1:430150006394:parametergroup:default.memcached1.5", + "CacheParameterGroupFamily": "memcached1.5", + "Description": "Default parameter group for memcached1.5", + "IsGlobal": false, + "id": "e0934919fe4741105df762ae57b738fea22ebc40", + "name": "default.memcached1.5" + } + }, + "parameter_groups_count": 13, + "region": "ap-northeast-1", + "security_groups": {}, + "security_groups_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-0cbc506a": { + "arn": "arn:aws:vpc:ap-northeast-1:430150006394:virtual-private-cloud/vpc-0cbc506a", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-0cbc506a", + "name": "vpc-0cbc506a", + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "ap-northeast-2": { + "clusters_count": 0, + "id": "ap-northeast-2", + "name": "ap-northeast-2", + "parameter_groups": { + "02e3d792a7e00a39f3c9fa0bb0445e86d7644525": { + "ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.redis3.2.cluster.on", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Customized default parameter group for redis3.2 with cluster mode on", + "IsGlobal": false, + "id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525", + "name": "default.redis3.2.cluster.on" + }, + "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": { + "ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.memcached1.4", + "CacheParameterGroupFamily": "memcached1.4", + "Description": "Default parameter group for memcached1.4", + "IsGlobal": false, + "id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124", + "name": "default.memcached1.4" + }, + "1a65eec91cd66eb16ba40e781620d9320ec1733f": { + "ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.redis6.x.cluster.on", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Customized default parameter group for redis6.x with cluster mode on", + "IsGlobal": false, + "id": "1a65eec91cd66eb16ba40e781620d9320ec1733f", + "name": "default.redis6.x.cluster.on" + }, + "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": { + "ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.redis2.8", + "CacheParameterGroupFamily": "redis2.8", + "Description": "Default parameter group for redis2.8", + "IsGlobal": false, + "id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e", + "name": "default.redis2.8" + }, + "51584be5be0c6c6af057229afd341d592a55bf0e": { + "ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.memcached1.6", + "CacheParameterGroupFamily": "memcached1.6", + "Description": "Default parameter group for memcached1.6", + "IsGlobal": false, + "id": "51584be5be0c6c6af057229afd341d592a55bf0e", + "name": "default.memcached1.6" + }, + "533bd3e057f46120794828b5c797b3fe8aab1336": { + "ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.redis2.6", + "CacheParameterGroupFamily": "redis2.6", + "Description": "Default parameter group for redis2.6", + "IsGlobal": false, + "id": "533bd3e057f46120794828b5c797b3fe8aab1336", + "name": "default.redis2.6" + }, + "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": { + "ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.redis3.2", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Default parameter group for redis3.2", + "IsGlobal": false, + "id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3", + "name": "default.redis3.2" + }, + "6e3786a6f55135ca99b9432b0059a35deb2ae908": { + "ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.redis5.0", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Default parameter group for redis5.0", + "IsGlobal": false, + "id": "6e3786a6f55135ca99b9432b0059a35deb2ae908", + "name": "default.redis5.0" + }, + "89dee6407112ff413de0345de376d45c799f0028": { + "ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.redis4.0.cluster.on", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Customized default parameter group for redis4.0 with cluster mode on", + "IsGlobal": false, + "id": "89dee6407112ff413de0345de376d45c799f0028", + "name": "default.redis4.0.cluster.on" + }, + "92d124b9a74567482361fe34e367ac8bf5c02e0b": { + "ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.redis6.x", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Default parameter group for redis6.x", + "IsGlobal": false, + "id": "92d124b9a74567482361fe34e367ac8bf5c02e0b", + "name": "default.redis6.x" + }, + "a64a576f220009cfa7c322c46fc92d32a85a4978": { + "ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.redis5.0.cluster.on", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Customized default parameter group for redis5.0 with cluster mode on", + "IsGlobal": false, + "id": "a64a576f220009cfa7c322c46fc92d32a85a4978", + "name": "default.redis5.0.cluster.on" + }, + "c954e04f298cd030c6fde9c32c8365d1b9f76fb4": { + "ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.redis4.0", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Default parameter group for redis4.0", + "IsGlobal": false, + "id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4", + "name": "default.redis4.0" + }, + "e0934919fe4741105df762ae57b738fea22ebc40": { + "ARN": "arn:aws:elasticache:ap-northeast-2:430150006394:parametergroup:default.memcached1.5", + "CacheParameterGroupFamily": "memcached1.5", + "Description": "Default parameter group for memcached1.5", + "IsGlobal": false, + "id": "e0934919fe4741105df762ae57b738fea22ebc40", + "name": "default.memcached1.5" + } + }, + "parameter_groups_count": 13, + "region": "ap-northeast-2", + "security_groups": {}, + "security_groups_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-73f44e18": { + "arn": "arn:aws:vpc:ap-northeast-2:430150006394:virtual-private-cloud/vpc-73f44e18", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-73f44e18", + "name": "vpc-73f44e18", + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "ap-northeast-3": { + "clusters_count": 0, + "id": "ap-northeast-3", + "name": "ap-northeast-3", + "parameter_groups": { + "02e3d792a7e00a39f3c9fa0bb0445e86d7644525": { + "ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.redis3.2.cluster.on", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Customized default parameter group for redis3.2 with cluster mode on", + "IsGlobal": false, + "id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525", + "name": "default.redis3.2.cluster.on" + }, + "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": { + "ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.memcached1.4", + "CacheParameterGroupFamily": "memcached1.4", + "Description": "Default parameter group for memcached1.4", + "IsGlobal": false, + "id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124", + "name": "default.memcached1.4" + }, + "1a65eec91cd66eb16ba40e781620d9320ec1733f": { + "ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.redis6.x.cluster.on", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Customized default parameter group for redis6.x with cluster mode on", + "IsGlobal": false, + "id": "1a65eec91cd66eb16ba40e781620d9320ec1733f", + "name": "default.redis6.x.cluster.on" + }, + "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": { + "ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.redis2.8", + "CacheParameterGroupFamily": "redis2.8", + "Description": "Default parameter group for redis2.8", + "IsGlobal": false, + "id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e", + "name": "default.redis2.8" + }, + "51584be5be0c6c6af057229afd341d592a55bf0e": { + "ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.memcached1.6", + "CacheParameterGroupFamily": "memcached1.6", + "Description": "Default parameter group for memcached1.6", + "IsGlobal": false, + "id": "51584be5be0c6c6af057229afd341d592a55bf0e", + "name": "default.memcached1.6" + }, + "533bd3e057f46120794828b5c797b3fe8aab1336": { + "ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.redis2.6", + "CacheParameterGroupFamily": "redis2.6", + "Description": "Default parameter group for redis2.6", + "IsGlobal": false, + "id": "533bd3e057f46120794828b5c797b3fe8aab1336", + "name": "default.redis2.6" + }, + "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": { + "ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.redis3.2", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Default parameter group for redis3.2", + "IsGlobal": false, + "id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3", + "name": "default.redis3.2" + }, + "6e3786a6f55135ca99b9432b0059a35deb2ae908": { + "ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.redis5.0", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Default parameter group for redis5.0", + "IsGlobal": false, + "id": "6e3786a6f55135ca99b9432b0059a35deb2ae908", + "name": "default.redis5.0" + }, + "89dee6407112ff413de0345de376d45c799f0028": { + "ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.redis4.0.cluster.on", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Customized default parameter group for redis4.0 with cluster mode on", + "IsGlobal": false, + "id": "89dee6407112ff413de0345de376d45c799f0028", + "name": "default.redis4.0.cluster.on" + }, + "92d124b9a74567482361fe34e367ac8bf5c02e0b": { + "ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.redis6.x", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Default parameter group for redis6.x", + "IsGlobal": false, + "id": "92d124b9a74567482361fe34e367ac8bf5c02e0b", + "name": "default.redis6.x" + }, + "a64a576f220009cfa7c322c46fc92d32a85a4978": { + "ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.redis5.0.cluster.on", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Customized default parameter group for redis5.0 with cluster mode on", + "IsGlobal": false, + "id": "a64a576f220009cfa7c322c46fc92d32a85a4978", + "name": "default.redis5.0.cluster.on" + }, + "c954e04f298cd030c6fde9c32c8365d1b9f76fb4": { + "ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.redis4.0", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Default parameter group for redis4.0", + "IsGlobal": false, + "id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4", + "name": "default.redis4.0" + }, + "e0934919fe4741105df762ae57b738fea22ebc40": { + "ARN": "arn:aws:elasticache:ap-northeast-3:430150006394:parametergroup:default.memcached1.5", + "CacheParameterGroupFamily": "memcached1.5", + "Description": "Default parameter group for memcached1.5", + "IsGlobal": false, + "id": "e0934919fe4741105df762ae57b738fea22ebc40", + "name": "default.memcached1.5" + } + }, + "parameter_groups_count": 13, + "region": "ap-northeast-3", + "security_groups": {}, + "security_groups_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-47b7dd2e": { + "arn": "arn:aws:vpc:ap-northeast-3:430150006394:virtual-private-cloud/vpc-47b7dd2e", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-47b7dd2e", + "name": "vpc-47b7dd2e", + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "ap-south-1": { + "clusters_count": 0, + "id": "ap-south-1", + "name": "ap-south-1", + "parameter_groups": { + "02e3d792a7e00a39f3c9fa0bb0445e86d7644525": { + "ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.redis3.2.cluster.on", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Customized default parameter group for redis3.2 with cluster mode on", + "IsGlobal": false, + "id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525", + "name": "default.redis3.2.cluster.on" + }, + "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": { + "ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.memcached1.4", + "CacheParameterGroupFamily": "memcached1.4", + "Description": "Default parameter group for memcached1.4", + "IsGlobal": false, + "id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124", + "name": "default.memcached1.4" + }, + "1a65eec91cd66eb16ba40e781620d9320ec1733f": { + "ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.redis6.x.cluster.on", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Customized default parameter group for redis6.x with cluster mode on", + "IsGlobal": false, + "id": "1a65eec91cd66eb16ba40e781620d9320ec1733f", + "name": "default.redis6.x.cluster.on" + }, + "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": { + "ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.redis2.8", + "CacheParameterGroupFamily": "redis2.8", + "Description": "Default parameter group for redis2.8", + "IsGlobal": false, + "id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e", + "name": "default.redis2.8" + }, + "51584be5be0c6c6af057229afd341d592a55bf0e": { + "ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.memcached1.6", + "CacheParameterGroupFamily": "memcached1.6", + "Description": "Default parameter group for memcached1.6", + "IsGlobal": false, + "id": "51584be5be0c6c6af057229afd341d592a55bf0e", + "name": "default.memcached1.6" + }, + "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": { + "ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.redis3.2", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Default parameter group for redis3.2", + "IsGlobal": false, + "id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3", + "name": "default.redis3.2" + }, + "6e3786a6f55135ca99b9432b0059a35deb2ae908": { + "ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.redis5.0", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Default parameter group for redis5.0", + "IsGlobal": false, + "id": "6e3786a6f55135ca99b9432b0059a35deb2ae908", + "name": "default.redis5.0" + }, + "89dee6407112ff413de0345de376d45c799f0028": { + "ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.redis4.0.cluster.on", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Customized default parameter group for redis4.0 with cluster mode on", + "IsGlobal": false, + "id": "89dee6407112ff413de0345de376d45c799f0028", + "name": "default.redis4.0.cluster.on" + }, + "92d124b9a74567482361fe34e367ac8bf5c02e0b": { + "ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.redis6.x", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Default parameter group for redis6.x", + "IsGlobal": false, + "id": "92d124b9a74567482361fe34e367ac8bf5c02e0b", + "name": "default.redis6.x" + }, + "a64a576f220009cfa7c322c46fc92d32a85a4978": { + "ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.redis5.0.cluster.on", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Customized default parameter group for redis5.0 with cluster mode on", + "IsGlobal": false, + "id": "a64a576f220009cfa7c322c46fc92d32a85a4978", + "name": "default.redis5.0.cluster.on" + }, + "c954e04f298cd030c6fde9c32c8365d1b9f76fb4": { + "ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.redis4.0", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Default parameter group for redis4.0", + "IsGlobal": false, + "id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4", + "name": "default.redis4.0" + }, + "e0934919fe4741105df762ae57b738fea22ebc40": { + "ARN": "arn:aws:elasticache:ap-south-1:430150006394:parametergroup:default.memcached1.5", + "CacheParameterGroupFamily": "memcached1.5", + "Description": "Default parameter group for memcached1.5", + "IsGlobal": false, + "id": "e0934919fe4741105df762ae57b738fea22ebc40", + "name": "default.memcached1.5" + } + }, + "parameter_groups_count": 12, + "region": "ap-south-1", + "security_groups": {}, + "security_groups_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-2651a14d": { + "arn": "arn:aws:vpc:ap-south-1:430150006394:virtual-private-cloud/vpc-2651a14d", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-2651a14d", + "name": "vpc-2651a14d", + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "ap-southeast-1": { + "clusters_count": 0, + "id": "ap-southeast-1", + "name": "ap-southeast-1", + "parameter_groups": { + "02e3d792a7e00a39f3c9fa0bb0445e86d7644525": { + "ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.redis3.2.cluster.on", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Customized default parameter group for redis3.2 with cluster mode on", + "IsGlobal": false, + "id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525", + "name": "default.redis3.2.cluster.on" + }, + "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": { + "ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.memcached1.4", + "CacheParameterGroupFamily": "memcached1.4", + "Description": "Default parameter group for memcached1.4", + "IsGlobal": false, + "id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124", + "name": "default.memcached1.4" + }, + "1a65eec91cd66eb16ba40e781620d9320ec1733f": { + "ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.redis6.x.cluster.on", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Customized default parameter group for redis6.x with cluster mode on", + "IsGlobal": false, + "id": "1a65eec91cd66eb16ba40e781620d9320ec1733f", + "name": "default.redis6.x.cluster.on" + }, + "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": { + "ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.redis2.8", + "CacheParameterGroupFamily": "redis2.8", + "Description": "Default parameter group for redis2.8", + "IsGlobal": false, + "id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e", + "name": "default.redis2.8" + }, + "51584be5be0c6c6af057229afd341d592a55bf0e": { + "ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.memcached1.6", + "CacheParameterGroupFamily": "memcached1.6", + "Description": "Default parameter group for memcached1.6", + "IsGlobal": false, + "id": "51584be5be0c6c6af057229afd341d592a55bf0e", + "name": "default.memcached1.6" + }, + "533bd3e057f46120794828b5c797b3fe8aab1336": { + "ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.redis2.6", + "CacheParameterGroupFamily": "redis2.6", + "Description": "Default parameter group for redis2.6", + "IsGlobal": false, + "id": "533bd3e057f46120794828b5c797b3fe8aab1336", + "name": "default.redis2.6" + }, + "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": { + "ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.redis3.2", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Default parameter group for redis3.2", + "IsGlobal": false, + "id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3", + "name": "default.redis3.2" + }, + "6e3786a6f55135ca99b9432b0059a35deb2ae908": { + "ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.redis5.0", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Default parameter group for redis5.0", + "IsGlobal": false, + "id": "6e3786a6f55135ca99b9432b0059a35deb2ae908", + "name": "default.redis5.0" + }, + "89dee6407112ff413de0345de376d45c799f0028": { + "ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.redis4.0.cluster.on", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Customized default parameter group for redis4.0 with cluster mode on", + "IsGlobal": false, + "id": "89dee6407112ff413de0345de376d45c799f0028", + "name": "default.redis4.0.cluster.on" + }, + "92d124b9a74567482361fe34e367ac8bf5c02e0b": { + "ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.redis6.x", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Default parameter group for redis6.x", + "IsGlobal": false, + "id": "92d124b9a74567482361fe34e367ac8bf5c02e0b", + "name": "default.redis6.x" + }, + "a64a576f220009cfa7c322c46fc92d32a85a4978": { + "ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.redis5.0.cluster.on", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Customized default parameter group for redis5.0 with cluster mode on", + "IsGlobal": false, + "id": "a64a576f220009cfa7c322c46fc92d32a85a4978", + "name": "default.redis5.0.cluster.on" + }, + "c954e04f298cd030c6fde9c32c8365d1b9f76fb4": { + "ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.redis4.0", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Default parameter group for redis4.0", + "IsGlobal": false, + "id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4", + "name": "default.redis4.0" + }, + "e0934919fe4741105df762ae57b738fea22ebc40": { + "ARN": "arn:aws:elasticache:ap-southeast-1:430150006394:parametergroup:default.memcached1.5", + "CacheParameterGroupFamily": "memcached1.5", + "Description": "Default parameter group for memcached1.5", + "IsGlobal": false, + "id": "e0934919fe4741105df762ae57b738fea22ebc40", + "name": "default.memcached1.5" + } + }, + "parameter_groups_count": 13, + "region": "ap-southeast-1", + "security_groups": {}, + "security_groups_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-04ed1062": { + "arn": "arn:aws:vpc:ap-southeast-1:430150006394:virtual-private-cloud/vpc-04ed1062", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-04ed1062", + "name": "vpc-04ed1062", + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "ap-southeast-2": { + "clusters_count": 0, + "id": "ap-southeast-2", + "name": "ap-southeast-2", + "parameter_groups": { + "02e3d792a7e00a39f3c9fa0bb0445e86d7644525": { + "ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.redis3.2.cluster.on", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Customized default parameter group for redis3.2 with cluster mode on", + "IsGlobal": false, + "id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525", + "name": "default.redis3.2.cluster.on" + }, + "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": { + "ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.memcached1.4", + "CacheParameterGroupFamily": "memcached1.4", + "Description": "Default parameter group for memcached1.4", + "IsGlobal": false, + "id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124", + "name": "default.memcached1.4" + }, + "1a65eec91cd66eb16ba40e781620d9320ec1733f": { + "ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.redis6.x.cluster.on", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Customized default parameter group for redis6.x with cluster mode on", + "IsGlobal": false, + "id": "1a65eec91cd66eb16ba40e781620d9320ec1733f", + "name": "default.redis6.x.cluster.on" + }, + "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": { + "ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.redis2.8", + "CacheParameterGroupFamily": "redis2.8", + "Description": "Default parameter group for redis2.8", + "IsGlobal": false, + "id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e", + "name": "default.redis2.8" + }, + "51584be5be0c6c6af057229afd341d592a55bf0e": { + "ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.memcached1.6", + "CacheParameterGroupFamily": "memcached1.6", + "Description": "Default parameter group for memcached1.6", + "IsGlobal": false, + "id": "51584be5be0c6c6af057229afd341d592a55bf0e", + "name": "default.memcached1.6" + }, + "533bd3e057f46120794828b5c797b3fe8aab1336": { + "ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.redis2.6", + "CacheParameterGroupFamily": "redis2.6", + "Description": "Default parameter group for redis2.6", + "IsGlobal": false, + "id": "533bd3e057f46120794828b5c797b3fe8aab1336", + "name": "default.redis2.6" + }, + "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": { + "ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.redis3.2", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Default parameter group for redis3.2", + "IsGlobal": false, + "id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3", + "name": "default.redis3.2" + }, + "6e3786a6f55135ca99b9432b0059a35deb2ae908": { + "ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.redis5.0", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Default parameter group for redis5.0", + "IsGlobal": false, + "id": "6e3786a6f55135ca99b9432b0059a35deb2ae908", + "name": "default.redis5.0" + }, + "89dee6407112ff413de0345de376d45c799f0028": { + "ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.redis4.0.cluster.on", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Customized default parameter group for redis4.0 with cluster mode on", + "IsGlobal": false, + "id": "89dee6407112ff413de0345de376d45c799f0028", + "name": "default.redis4.0.cluster.on" + }, + "92d124b9a74567482361fe34e367ac8bf5c02e0b": { + "ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.redis6.x", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Default parameter group for redis6.x", + "IsGlobal": false, + "id": "92d124b9a74567482361fe34e367ac8bf5c02e0b", + "name": "default.redis6.x" + }, + "a64a576f220009cfa7c322c46fc92d32a85a4978": { + "ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.redis5.0.cluster.on", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Customized default parameter group for redis5.0 with cluster mode on", + "IsGlobal": false, + "id": "a64a576f220009cfa7c322c46fc92d32a85a4978", + "name": "default.redis5.0.cluster.on" + }, + "c954e04f298cd030c6fde9c32c8365d1b9f76fb4": { + "ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.redis4.0", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Default parameter group for redis4.0", + "IsGlobal": false, + "id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4", + "name": "default.redis4.0" + }, + "e0934919fe4741105df762ae57b738fea22ebc40": { + "ARN": "arn:aws:elasticache:ap-southeast-2:430150006394:parametergroup:default.memcached1.5", + "CacheParameterGroupFamily": "memcached1.5", + "Description": "Default parameter group for memcached1.5", + "IsGlobal": false, + "id": "e0934919fe4741105df762ae57b738fea22ebc40", + "name": "default.memcached1.5" + } + }, + "parameter_groups_count": 13, + "region": "ap-southeast-2", + "security_groups": {}, + "security_groups_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-5d22c33b": { + "arn": "arn:aws:vpc:ap-southeast-2:430150006394:virtual-private-cloud/vpc-5d22c33b", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-5d22c33b", + "name": "vpc-5d22c33b", + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "ca-central-1": { + "clusters_count": 0, + "id": "ca-central-1", + "name": "ca-central-1", + "parameter_groups": { + "02e3d792a7e00a39f3c9fa0bb0445e86d7644525": { + "ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.redis3.2.cluster.on", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Customized default parameter group for redis3.2 with cluster mode on", + "IsGlobal": false, + "id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525", + "name": "default.redis3.2.cluster.on" + }, + "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": { + "ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.memcached1.4", + "CacheParameterGroupFamily": "memcached1.4", + "Description": "Default parameter group for memcached1.4", + "IsGlobal": false, + "id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124", + "name": "default.memcached1.4" + }, + "1a65eec91cd66eb16ba40e781620d9320ec1733f": { + "ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.redis6.x.cluster.on", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Customized default parameter group for redis6.x with cluster mode on", + "IsGlobal": false, + "id": "1a65eec91cd66eb16ba40e781620d9320ec1733f", + "name": "default.redis6.x.cluster.on" + }, + "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": { + "ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.redis2.8", + "CacheParameterGroupFamily": "redis2.8", + "Description": "Default parameter group for redis2.8", + "IsGlobal": false, + "id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e", + "name": "default.redis2.8" + }, + "51584be5be0c6c6af057229afd341d592a55bf0e": { + "ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.memcached1.6", + "CacheParameterGroupFamily": "memcached1.6", + "Description": "Default parameter group for memcached1.6", + "IsGlobal": false, + "id": "51584be5be0c6c6af057229afd341d592a55bf0e", + "name": "default.memcached1.6" + }, + "533bd3e057f46120794828b5c797b3fe8aab1336": { + "ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.redis2.6", + "CacheParameterGroupFamily": "redis2.6", + "Description": "Default parameter group for redis2.6", + "IsGlobal": false, + "id": "533bd3e057f46120794828b5c797b3fe8aab1336", + "name": "default.redis2.6" + }, + "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": { + "ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.redis3.2", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Default parameter group for redis3.2", + "IsGlobal": false, + "id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3", + "name": "default.redis3.2" + }, + "6e3786a6f55135ca99b9432b0059a35deb2ae908": { + "ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.redis5.0", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Default parameter group for redis5.0", + "IsGlobal": false, + "id": "6e3786a6f55135ca99b9432b0059a35deb2ae908", + "name": "default.redis5.0" + }, + "89dee6407112ff413de0345de376d45c799f0028": { + "ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.redis4.0.cluster.on", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Customized default parameter group for redis4.0 with cluster mode on", + "IsGlobal": false, + "id": "89dee6407112ff413de0345de376d45c799f0028", + "name": "default.redis4.0.cluster.on" + }, + "92d124b9a74567482361fe34e367ac8bf5c02e0b": { + "ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.redis6.x", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Default parameter group for redis6.x", + "IsGlobal": false, + "id": "92d124b9a74567482361fe34e367ac8bf5c02e0b", + "name": "default.redis6.x" + }, + "a64a576f220009cfa7c322c46fc92d32a85a4978": { + "ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.redis5.0.cluster.on", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Customized default parameter group for redis5.0 with cluster mode on", + "IsGlobal": false, + "id": "a64a576f220009cfa7c322c46fc92d32a85a4978", + "name": "default.redis5.0.cluster.on" + }, + "c954e04f298cd030c6fde9c32c8365d1b9f76fb4": { + "ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.redis4.0", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Default parameter group for redis4.0", + "IsGlobal": false, + "id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4", + "name": "default.redis4.0" + }, + "e0934919fe4741105df762ae57b738fea22ebc40": { + "ARN": "arn:aws:elasticache:ca-central-1:430150006394:parametergroup:default.memcached1.5", + "CacheParameterGroupFamily": "memcached1.5", + "Description": "Default parameter group for memcached1.5", + "IsGlobal": false, + "id": "e0934919fe4741105df762ae57b738fea22ebc40", + "name": "default.memcached1.5" + } + }, + "parameter_groups_count": 13, + "region": "ca-central-1", + "security_groups": {}, + "security_groups_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-b5113ddd": { + "arn": "arn:aws:vpc:ca-central-1:430150006394:virtual-private-cloud/vpc-b5113ddd", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-b5113ddd", + "name": "vpc-b5113ddd", + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "eu-central-1": { + "clusters_count": 0, + "id": "eu-central-1", + "name": "eu-central-1", + "parameter_groups": { + "02e3d792a7e00a39f3c9fa0bb0445e86d7644525": { + "ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.redis3.2.cluster.on", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Customized default parameter group for redis3.2 with cluster mode on", + "IsGlobal": false, + "id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525", + "name": "default.redis3.2.cluster.on" + }, + "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": { + "ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.memcached1.4", + "CacheParameterGroupFamily": "memcached1.4", + "Description": "Default parameter group for memcached1.4", + "IsGlobal": false, + "id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124", + "name": "default.memcached1.4" + }, + "1a65eec91cd66eb16ba40e781620d9320ec1733f": { + "ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.redis6.x.cluster.on", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Customized default parameter group for redis6.x with cluster mode on", + "IsGlobal": false, + "id": "1a65eec91cd66eb16ba40e781620d9320ec1733f", + "name": "default.redis6.x.cluster.on" + }, + "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": { + "ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.redis2.8", + "CacheParameterGroupFamily": "redis2.8", + "Description": "Default parameter group for redis2.8", + "IsGlobal": false, + "id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e", + "name": "default.redis2.8" + }, + "51584be5be0c6c6af057229afd341d592a55bf0e": { + "ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.memcached1.6", + "CacheParameterGroupFamily": "memcached1.6", + "Description": "Default parameter group for memcached1.6", + "IsGlobal": false, + "id": "51584be5be0c6c6af057229afd341d592a55bf0e", + "name": "default.memcached1.6" + }, + "533bd3e057f46120794828b5c797b3fe8aab1336": { + "ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.redis2.6", + "CacheParameterGroupFamily": "redis2.6", + "Description": "Default parameter group for redis2.6", + "IsGlobal": false, + "id": "533bd3e057f46120794828b5c797b3fe8aab1336", + "name": "default.redis2.6" + }, + "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": { + "ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.redis3.2", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Default parameter group for redis3.2", + "IsGlobal": false, + "id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3", + "name": "default.redis3.2" + }, + "6e3786a6f55135ca99b9432b0059a35deb2ae908": { + "ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.redis5.0", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Default parameter group for redis5.0", + "IsGlobal": false, + "id": "6e3786a6f55135ca99b9432b0059a35deb2ae908", + "name": "default.redis5.0" + }, + "89dee6407112ff413de0345de376d45c799f0028": { + "ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.redis4.0.cluster.on", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Customized default parameter group for redis4.0 with cluster mode on", + "IsGlobal": false, + "id": "89dee6407112ff413de0345de376d45c799f0028", + "name": "default.redis4.0.cluster.on" + }, + "92d124b9a74567482361fe34e367ac8bf5c02e0b": { + "ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.redis6.x", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Default parameter group for redis6.x", + "IsGlobal": false, + "id": "92d124b9a74567482361fe34e367ac8bf5c02e0b", + "name": "default.redis6.x" + }, + "a64a576f220009cfa7c322c46fc92d32a85a4978": { + "ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.redis5.0.cluster.on", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Customized default parameter group for redis5.0 with cluster mode on", + "IsGlobal": false, + "id": "a64a576f220009cfa7c322c46fc92d32a85a4978", + "name": "default.redis5.0.cluster.on" + }, + "c954e04f298cd030c6fde9c32c8365d1b9f76fb4": { + "ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.redis4.0", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Default parameter group for redis4.0", + "IsGlobal": false, + "id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4", + "name": "default.redis4.0" + }, + "e0934919fe4741105df762ae57b738fea22ebc40": { + "ARN": "arn:aws:elasticache:eu-central-1:430150006394:parametergroup:default.memcached1.5", + "CacheParameterGroupFamily": "memcached1.5", + "Description": "Default parameter group for memcached1.5", + "IsGlobal": false, + "id": "e0934919fe4741105df762ae57b738fea22ebc40", + "name": "default.memcached1.5" + } + }, + "parameter_groups_count": 13, + "region": "eu-central-1", + "security_groups": {}, + "security_groups_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-78b43312": { + "arn": "arn:aws:vpc:eu-central-1:430150006394:virtual-private-cloud/vpc-78b43312", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-78b43312", + "name": "vpc-78b43312", + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "eu-north-1": { + "clusters_count": 0, + "id": "eu-north-1", + "name": "eu-north-1", + "parameter_groups": { + "02e3d792a7e00a39f3c9fa0bb0445e86d7644525": { + "ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.redis3.2.cluster.on", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Customized default parameter group for redis3.2 with cluster mode on", + "IsGlobal": false, + "id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525", + "name": "default.redis3.2.cluster.on" + }, + "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": { + "ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.memcached1.4", + "CacheParameterGroupFamily": "memcached1.4", + "Description": "Default parameter group for memcached1.4", + "IsGlobal": false, + "id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124", + "name": "default.memcached1.4" + }, + "1a65eec91cd66eb16ba40e781620d9320ec1733f": { + "ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.redis6.x.cluster.on", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Customized default parameter group for redis6.x with cluster mode on", + "IsGlobal": false, + "id": "1a65eec91cd66eb16ba40e781620d9320ec1733f", + "name": "default.redis6.x.cluster.on" + }, + "51584be5be0c6c6af057229afd341d592a55bf0e": { + "ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.memcached1.6", + "CacheParameterGroupFamily": "memcached1.6", + "Description": "Default parameter group for memcached1.6", + "IsGlobal": false, + "id": "51584be5be0c6c6af057229afd341d592a55bf0e", + "name": "default.memcached1.6" + }, + "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": { + "ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.redis3.2", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Default parameter group for redis3.2", + "IsGlobal": false, + "id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3", + "name": "default.redis3.2" + }, + "6e3786a6f55135ca99b9432b0059a35deb2ae908": { + "ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.redis5.0", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Default parameter group for redis5.0", + "IsGlobal": false, + "id": "6e3786a6f55135ca99b9432b0059a35deb2ae908", + "name": "default.redis5.0" + }, + "89dee6407112ff413de0345de376d45c799f0028": { + "ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.redis4.0.cluster.on", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Customized default parameter group for redis4.0 with cluster mode on", + "IsGlobal": false, + "id": "89dee6407112ff413de0345de376d45c799f0028", + "name": "default.redis4.0.cluster.on" + }, + "92d124b9a74567482361fe34e367ac8bf5c02e0b": { + "ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.redis6.x", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Default parameter group for redis6.x", + "IsGlobal": false, + "id": "92d124b9a74567482361fe34e367ac8bf5c02e0b", + "name": "default.redis6.x" + }, + "a64a576f220009cfa7c322c46fc92d32a85a4978": { + "ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.redis5.0.cluster.on", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Customized default parameter group for redis5.0 with cluster mode on", + "IsGlobal": false, + "id": "a64a576f220009cfa7c322c46fc92d32a85a4978", + "name": "default.redis5.0.cluster.on" + }, + "c954e04f298cd030c6fde9c32c8365d1b9f76fb4": { + "ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.redis4.0", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Default parameter group for redis4.0", + "IsGlobal": false, + "id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4", + "name": "default.redis4.0" + }, + "e0934919fe4741105df762ae57b738fea22ebc40": { + "ARN": "arn:aws:elasticache:eu-north-1:430150006394:parametergroup:default.memcached1.5", + "CacheParameterGroupFamily": "memcached1.5", + "Description": "Default parameter group for memcached1.5", + "IsGlobal": false, + "id": "e0934919fe4741105df762ae57b738fea22ebc40", + "name": "default.memcached1.5" + } + }, + "parameter_groups_count": 11, + "region": "eu-north-1", + "security_groups": {}, + "security_groups_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-fa259d93": { + "arn": "arn:aws:vpc:eu-north-1:430150006394:virtual-private-cloud/vpc-fa259d93", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-fa259d93", + "name": "vpc-fa259d93", + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "eu-west-1": { + "clusters_count": 0, + "id": "eu-west-1", + "name": "eu-west-1", + "parameter_groups": { + "02e3d792a7e00a39f3c9fa0bb0445e86d7644525": { + "ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.redis3.2.cluster.on", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Customized default parameter group for redis3.2 with cluster mode on", + "IsGlobal": false, + "id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525", + "name": "default.redis3.2.cluster.on" + }, + "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": { + "ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.memcached1.4", + "CacheParameterGroupFamily": "memcached1.4", + "Description": "Default parameter group for memcached1.4", + "IsGlobal": false, + "id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124", + "name": "default.memcached1.4" + }, + "1a65eec91cd66eb16ba40e781620d9320ec1733f": { + "ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.redis6.x.cluster.on", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Customized default parameter group for redis6.x with cluster mode on", + "IsGlobal": false, + "id": "1a65eec91cd66eb16ba40e781620d9320ec1733f", + "name": "default.redis6.x.cluster.on" + }, + "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": { + "ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.redis2.8", + "CacheParameterGroupFamily": "redis2.8", + "Description": "Default parameter group for redis2.8", + "IsGlobal": false, + "id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e", + "name": "default.redis2.8" + }, + "51584be5be0c6c6af057229afd341d592a55bf0e": { + "ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.memcached1.6", + "CacheParameterGroupFamily": "memcached1.6", + "Description": "Default parameter group for memcached1.6", + "IsGlobal": false, + "id": "51584be5be0c6c6af057229afd341d592a55bf0e", + "name": "default.memcached1.6" + }, + "533bd3e057f46120794828b5c797b3fe8aab1336": { + "ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.redis2.6", + "CacheParameterGroupFamily": "redis2.6", + "Description": "Default parameter group for redis2.6", + "IsGlobal": false, + "id": "533bd3e057f46120794828b5c797b3fe8aab1336", + "name": "default.redis2.6" + }, + "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": { + "ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.redis3.2", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Default parameter group for redis3.2", + "IsGlobal": false, + "id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3", + "name": "default.redis3.2" + }, + "6e3786a6f55135ca99b9432b0059a35deb2ae908": { + "ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.redis5.0", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Default parameter group for redis5.0", + "IsGlobal": false, + "id": "6e3786a6f55135ca99b9432b0059a35deb2ae908", + "name": "default.redis5.0" + }, + "89dee6407112ff413de0345de376d45c799f0028": { + "ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.redis4.0.cluster.on", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Customized default parameter group for redis4.0 with cluster mode on", + "IsGlobal": false, + "id": "89dee6407112ff413de0345de376d45c799f0028", + "name": "default.redis4.0.cluster.on" + }, + "92d124b9a74567482361fe34e367ac8bf5c02e0b": { + "ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.redis6.x", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Default parameter group for redis6.x", + "IsGlobal": false, + "id": "92d124b9a74567482361fe34e367ac8bf5c02e0b", + "name": "default.redis6.x" + }, + "a64a576f220009cfa7c322c46fc92d32a85a4978": { + "ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.redis5.0.cluster.on", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Customized default parameter group for redis5.0 with cluster mode on", + "IsGlobal": false, + "id": "a64a576f220009cfa7c322c46fc92d32a85a4978", + "name": "default.redis5.0.cluster.on" + }, + "c954e04f298cd030c6fde9c32c8365d1b9f76fb4": { + "ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.redis4.0", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Default parameter group for redis4.0", + "IsGlobal": false, + "id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4", + "name": "default.redis4.0" + }, + "e0934919fe4741105df762ae57b738fea22ebc40": { + "ARN": "arn:aws:elasticache:eu-west-1:430150006394:parametergroup:default.memcached1.5", + "CacheParameterGroupFamily": "memcached1.5", + "Description": "Default parameter group for memcached1.5", + "IsGlobal": false, + "id": "e0934919fe4741105df762ae57b738fea22ebc40", + "name": "default.memcached1.5" + } + }, + "parameter_groups_count": 13, + "region": "eu-west-1", + "security_groups": {}, + "security_groups_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-f24c7994": { + "arn": "arn:aws:vpc:eu-west-1:430150006394:virtual-private-cloud/vpc-f24c7994", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-f24c7994", + "name": "vpc-f24c7994", + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "eu-west-2": { + "clusters_count": 0, + "id": "eu-west-2", + "name": "eu-west-2", + "parameter_groups": { + "02e3d792a7e00a39f3c9fa0bb0445e86d7644525": { + "ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.redis3.2.cluster.on", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Customized default parameter group for redis3.2 with cluster mode on", + "IsGlobal": false, + "id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525", + "name": "default.redis3.2.cluster.on" + }, + "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": { + "ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.memcached1.4", + "CacheParameterGroupFamily": "memcached1.4", + "Description": "Default parameter group for memcached1.4", + "IsGlobal": false, + "id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124", + "name": "default.memcached1.4" + }, + "1a65eec91cd66eb16ba40e781620d9320ec1733f": { + "ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.redis6.x.cluster.on", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Customized default parameter group for redis6.x with cluster mode on", + "IsGlobal": false, + "id": "1a65eec91cd66eb16ba40e781620d9320ec1733f", + "name": "default.redis6.x.cluster.on" + }, + "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": { + "ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.redis2.8", + "CacheParameterGroupFamily": "redis2.8", + "Description": "Default parameter group for redis2.8", + "IsGlobal": false, + "id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e", + "name": "default.redis2.8" + }, + "51584be5be0c6c6af057229afd341d592a55bf0e": { + "ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.memcached1.6", + "CacheParameterGroupFamily": "memcached1.6", + "Description": "Default parameter group for memcached1.6", + "IsGlobal": false, + "id": "51584be5be0c6c6af057229afd341d592a55bf0e", + "name": "default.memcached1.6" + }, + "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": { + "ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.redis3.2", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Default parameter group for redis3.2", + "IsGlobal": false, + "id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3", + "name": "default.redis3.2" + }, + "6e3786a6f55135ca99b9432b0059a35deb2ae908": { + "ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.redis5.0", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Default parameter group for redis5.0", + "IsGlobal": false, + "id": "6e3786a6f55135ca99b9432b0059a35deb2ae908", + "name": "default.redis5.0" + }, + "89dee6407112ff413de0345de376d45c799f0028": { + "ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.redis4.0.cluster.on", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Customized default parameter group for redis4.0 with cluster mode on", + "IsGlobal": false, + "id": "89dee6407112ff413de0345de376d45c799f0028", + "name": "default.redis4.0.cluster.on" + }, + "92d124b9a74567482361fe34e367ac8bf5c02e0b": { + "ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.redis6.x", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Default parameter group for redis6.x", + "IsGlobal": false, + "id": "92d124b9a74567482361fe34e367ac8bf5c02e0b", + "name": "default.redis6.x" + }, + "a64a576f220009cfa7c322c46fc92d32a85a4978": { + "ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.redis5.0.cluster.on", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Customized default parameter group for redis5.0 with cluster mode on", + "IsGlobal": false, + "id": "a64a576f220009cfa7c322c46fc92d32a85a4978", + "name": "default.redis5.0.cluster.on" + }, + "c954e04f298cd030c6fde9c32c8365d1b9f76fb4": { + "ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.redis4.0", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Default parameter group for redis4.0", + "IsGlobal": false, + "id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4", + "name": "default.redis4.0" + }, + "e0934919fe4741105df762ae57b738fea22ebc40": { + "ARN": "arn:aws:elasticache:eu-west-2:430150006394:parametergroup:default.memcached1.5", + "CacheParameterGroupFamily": "memcached1.5", + "Description": "Default parameter group for memcached1.5", + "IsGlobal": false, + "id": "e0934919fe4741105df762ae57b738fea22ebc40", + "name": "default.memcached1.5" + } + }, + "parameter_groups_count": 12, + "region": "eu-west-2", + "security_groups": {}, + "security_groups_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-3fa2fa57": { + "arn": "arn:aws:vpc:eu-west-2:430150006394:virtual-private-cloud/vpc-3fa2fa57", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-3fa2fa57", + "name": "vpc-3fa2fa57", + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "eu-west-3": { + "clusters_count": 0, + "id": "eu-west-3", + "name": "eu-west-3", + "parameter_groups": { + "02e3d792a7e00a39f3c9fa0bb0445e86d7644525": { + "ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.redis3.2.cluster.on", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Customized default parameter group for redis3.2 with cluster mode on", + "IsGlobal": false, + "id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525", + "name": "default.redis3.2.cluster.on" + }, + "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": { + "ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.memcached1.4", + "CacheParameterGroupFamily": "memcached1.4", + "Description": "Default parameter group for memcached1.4", + "IsGlobal": false, + "id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124", + "name": "default.memcached1.4" + }, + "1a65eec91cd66eb16ba40e781620d9320ec1733f": { + "ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.redis6.x.cluster.on", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Customized default parameter group for redis6.x with cluster mode on", + "IsGlobal": false, + "id": "1a65eec91cd66eb16ba40e781620d9320ec1733f", + "name": "default.redis6.x.cluster.on" + }, + "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": { + "ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.redis2.8", + "CacheParameterGroupFamily": "redis2.8", + "Description": "Default parameter group for redis2.8", + "IsGlobal": false, + "id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e", + "name": "default.redis2.8" + }, + "51584be5be0c6c6af057229afd341d592a55bf0e": { + "ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.memcached1.6", + "CacheParameterGroupFamily": "memcached1.6", + "Description": "Default parameter group for memcached1.6", + "IsGlobal": false, + "id": "51584be5be0c6c6af057229afd341d592a55bf0e", + "name": "default.memcached1.6" + }, + "533bd3e057f46120794828b5c797b3fe8aab1336": { + "ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.redis2.6", + "CacheParameterGroupFamily": "redis2.6", + "Description": "Default parameter group for redis2.6", + "IsGlobal": false, + "id": "533bd3e057f46120794828b5c797b3fe8aab1336", + "name": "default.redis2.6" + }, + "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": { + "ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.redis3.2", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Default parameter group for redis3.2", + "IsGlobal": false, + "id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3", + "name": "default.redis3.2" + }, + "6e3786a6f55135ca99b9432b0059a35deb2ae908": { + "ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.redis5.0", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Default parameter group for redis5.0", + "IsGlobal": false, + "id": "6e3786a6f55135ca99b9432b0059a35deb2ae908", + "name": "default.redis5.0" + }, + "89dee6407112ff413de0345de376d45c799f0028": { + "ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.redis4.0.cluster.on", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Customized default parameter group for redis4.0 with cluster mode on", + "IsGlobal": false, + "id": "89dee6407112ff413de0345de376d45c799f0028", + "name": "default.redis4.0.cluster.on" + }, + "92d124b9a74567482361fe34e367ac8bf5c02e0b": { + "ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.redis6.x", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Default parameter group for redis6.x", + "IsGlobal": false, + "id": "92d124b9a74567482361fe34e367ac8bf5c02e0b", + "name": "default.redis6.x" + }, + "a64a576f220009cfa7c322c46fc92d32a85a4978": { + "ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.redis5.0.cluster.on", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Customized default parameter group for redis5.0 with cluster mode on", + "IsGlobal": false, + "id": "a64a576f220009cfa7c322c46fc92d32a85a4978", + "name": "default.redis5.0.cluster.on" + }, + "c954e04f298cd030c6fde9c32c8365d1b9f76fb4": { + "ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.redis4.0", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Default parameter group for redis4.0", + "IsGlobal": false, + "id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4", + "name": "default.redis4.0" + }, + "e0934919fe4741105df762ae57b738fea22ebc40": { + "ARN": "arn:aws:elasticache:eu-west-3:430150006394:parametergroup:default.memcached1.5", + "CacheParameterGroupFamily": "memcached1.5", + "Description": "Default parameter group for memcached1.5", + "IsGlobal": false, + "id": "e0934919fe4741105df762ae57b738fea22ebc40", + "name": "default.memcached1.5" + } + }, + "parameter_groups_count": 13, + "region": "eu-west-3", + "security_groups": {}, + "security_groups_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-87d3fdee": { + "arn": "arn:aws:vpc:eu-west-3:430150006394:virtual-private-cloud/vpc-87d3fdee", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-87d3fdee", + "name": "vpc-87d3fdee", + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "sa-east-1": { + "clusters_count": 0, + "id": "sa-east-1", + "name": "sa-east-1", + "parameter_groups": { + "02e3d792a7e00a39f3c9fa0bb0445e86d7644525": { + "ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.redis3.2.cluster.on", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Customized default parameter group for redis3.2 with cluster mode on", + "IsGlobal": false, + "id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525", + "name": "default.redis3.2.cluster.on" + }, + "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": { + "ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.memcached1.4", + "CacheParameterGroupFamily": "memcached1.4", + "Description": "Default parameter group for memcached1.4", + "IsGlobal": false, + "id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124", + "name": "default.memcached1.4" + }, + "1a65eec91cd66eb16ba40e781620d9320ec1733f": { + "ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.redis6.x.cluster.on", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Customized default parameter group for redis6.x with cluster mode on", + "IsGlobal": false, + "id": "1a65eec91cd66eb16ba40e781620d9320ec1733f", + "name": "default.redis6.x.cluster.on" + }, + "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": { + "ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.redis2.8", + "CacheParameterGroupFamily": "redis2.8", + "Description": "Default parameter group for redis2.8", + "IsGlobal": false, + "id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e", + "name": "default.redis2.8" + }, + "51584be5be0c6c6af057229afd341d592a55bf0e": { + "ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.memcached1.6", + "CacheParameterGroupFamily": "memcached1.6", + "Description": "Default parameter group for memcached1.6", + "IsGlobal": false, + "id": "51584be5be0c6c6af057229afd341d592a55bf0e", + "name": "default.memcached1.6" + }, + "533bd3e057f46120794828b5c797b3fe8aab1336": { + "ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.redis2.6", + "CacheParameterGroupFamily": "redis2.6", + "Description": "Default parameter group for redis2.6", + "IsGlobal": false, + "id": "533bd3e057f46120794828b5c797b3fe8aab1336", + "name": "default.redis2.6" + }, + "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": { + "ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.redis3.2", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Default parameter group for redis3.2", + "IsGlobal": false, + "id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3", + "name": "default.redis3.2" + }, + "6e3786a6f55135ca99b9432b0059a35deb2ae908": { + "ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.redis5.0", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Default parameter group for redis5.0", + "IsGlobal": false, + "id": "6e3786a6f55135ca99b9432b0059a35deb2ae908", + "name": "default.redis5.0" + }, + "89dee6407112ff413de0345de376d45c799f0028": { + "ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.redis4.0.cluster.on", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Customized default parameter group for redis4.0 with cluster mode on", + "IsGlobal": false, + "id": "89dee6407112ff413de0345de376d45c799f0028", + "name": "default.redis4.0.cluster.on" + }, + "92d124b9a74567482361fe34e367ac8bf5c02e0b": { + "ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.redis6.x", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Default parameter group for redis6.x", + "IsGlobal": false, + "id": "92d124b9a74567482361fe34e367ac8bf5c02e0b", + "name": "default.redis6.x" + }, + "a64a576f220009cfa7c322c46fc92d32a85a4978": { + "ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.redis5.0.cluster.on", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Customized default parameter group for redis5.0 with cluster mode on", + "IsGlobal": false, + "id": "a64a576f220009cfa7c322c46fc92d32a85a4978", + "name": "default.redis5.0.cluster.on" + }, + "c954e04f298cd030c6fde9c32c8365d1b9f76fb4": { + "ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.redis4.0", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Default parameter group for redis4.0", + "IsGlobal": false, + "id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4", + "name": "default.redis4.0" + }, + "e0934919fe4741105df762ae57b738fea22ebc40": { + "ARN": "arn:aws:elasticache:sa-east-1:430150006394:parametergroup:default.memcached1.5", + "CacheParameterGroupFamily": "memcached1.5", + "Description": "Default parameter group for memcached1.5", + "IsGlobal": false, + "id": "e0934919fe4741105df762ae57b738fea22ebc40", + "name": "default.memcached1.5" + } + }, + "parameter_groups_count": 13, + "region": "sa-east-1", + "security_groups": {}, + "security_groups_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-b14fa4d7": { + "arn": "arn:aws:vpc:sa-east-1:430150006394:virtual-private-cloud/vpc-b14fa4d7", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-b14fa4d7", + "name": "vpc-b14fa4d7", + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "us-east-1": { + "clusters_count": 0, + "id": "us-east-1", + "name": "us-east-1", + "parameter_groups": { + "02e3d792a7e00a39f3c9fa0bb0445e86d7644525": { + "ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.redis3.2.cluster.on", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Customized default parameter group for redis3.2 with cluster mode on", + "IsGlobal": false, + "id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525", + "name": "default.redis3.2.cluster.on" + }, + "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": { + "ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.memcached1.4", + "CacheParameterGroupFamily": "memcached1.4", + "Description": "Default parameter group for memcached1.4", + "IsGlobal": false, + "id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124", + "name": "default.memcached1.4" + }, + "1a65eec91cd66eb16ba40e781620d9320ec1733f": { + "ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.redis6.x.cluster.on", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Customized default parameter group for redis6.x with cluster mode on", + "IsGlobal": false, + "id": "1a65eec91cd66eb16ba40e781620d9320ec1733f", + "name": "default.redis6.x.cluster.on" + }, + "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": { + "ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.redis2.8", + "CacheParameterGroupFamily": "redis2.8", + "Description": "Default parameter group for redis2.8", + "IsGlobal": false, + "id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e", + "name": "default.redis2.8" + }, + "51584be5be0c6c6af057229afd341d592a55bf0e": { + "ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.memcached1.6", + "CacheParameterGroupFamily": "memcached1.6", + "Description": "Default parameter group for memcached1.6", + "IsGlobal": false, + "id": "51584be5be0c6c6af057229afd341d592a55bf0e", + "name": "default.memcached1.6" + }, + "533bd3e057f46120794828b5c797b3fe8aab1336": { + "ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.redis2.6", + "CacheParameterGroupFamily": "redis2.6", + "Description": "Default parameter group for redis2.6", + "IsGlobal": false, + "id": "533bd3e057f46120794828b5c797b3fe8aab1336", + "name": "default.redis2.6" + }, + "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": { + "ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.redis3.2", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Default parameter group for redis3.2", + "IsGlobal": false, + "id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3", + "name": "default.redis3.2" + }, + "6e3786a6f55135ca99b9432b0059a35deb2ae908": { + "ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.redis5.0", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Default parameter group for redis5.0", + "IsGlobal": false, + "id": "6e3786a6f55135ca99b9432b0059a35deb2ae908", + "name": "default.redis5.0" + }, + "89dee6407112ff413de0345de376d45c799f0028": { + "ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.redis4.0.cluster.on", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Customized default parameter group for redis4.0 with cluster mode on", + "IsGlobal": false, + "id": "89dee6407112ff413de0345de376d45c799f0028", + "name": "default.redis4.0.cluster.on" + }, + "92d124b9a74567482361fe34e367ac8bf5c02e0b": { + "ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.redis6.x", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Default parameter group for redis6.x", + "IsGlobal": false, + "id": "92d124b9a74567482361fe34e367ac8bf5c02e0b", + "name": "default.redis6.x" + }, + "a64a576f220009cfa7c322c46fc92d32a85a4978": { + "ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.redis5.0.cluster.on", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Customized default parameter group for redis5.0 with cluster mode on", + "IsGlobal": false, + "id": "a64a576f220009cfa7c322c46fc92d32a85a4978", + "name": "default.redis5.0.cluster.on" + }, + "c954e04f298cd030c6fde9c32c8365d1b9f76fb4": { + "ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.redis4.0", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Default parameter group for redis4.0", + "IsGlobal": false, + "id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4", + "name": "default.redis4.0" + }, + "e0934919fe4741105df762ae57b738fea22ebc40": { + "ARN": "arn:aws:elasticache:us-east-1:430150006394:parametergroup:default.memcached1.5", + "CacheParameterGroupFamily": "memcached1.5", + "Description": "Default parameter group for memcached1.5", + "IsGlobal": false, + "id": "e0934919fe4741105df762ae57b738fea22ebc40", + "name": "default.memcached1.5" + } + }, + "parameter_groups_count": 13, + "region": "us-east-1", + "security_groups": {}, + "security_groups_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-ba1cbdc7": { + "arn": "arn:aws:vpc:us-east-1:430150006394:virtual-private-cloud/vpc-ba1cbdc7", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-ba1cbdc7", + "name": "vpc-ba1cbdc7", + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "us-east-2": { + "clusters_count": 0, + "id": "us-east-2", + "name": "us-east-2", + "parameter_groups": { + "02e3d792a7e00a39f3c9fa0bb0445e86d7644525": { + "ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.redis3.2.cluster.on", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Customized default parameter group for redis3.2 with cluster mode on", + "IsGlobal": false, + "id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525", + "name": "default.redis3.2.cluster.on" + }, + "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": { + "ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.memcached1.4", + "CacheParameterGroupFamily": "memcached1.4", + "Description": "Default parameter group for memcached1.4", + "IsGlobal": false, + "id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124", + "name": "default.memcached1.4" + }, + "1a65eec91cd66eb16ba40e781620d9320ec1733f": { + "ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.redis6.x.cluster.on", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Customized default parameter group for redis6.x with cluster mode on", + "IsGlobal": false, + "id": "1a65eec91cd66eb16ba40e781620d9320ec1733f", + "name": "default.redis6.x.cluster.on" + }, + "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": { + "ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.redis2.8", + "CacheParameterGroupFamily": "redis2.8", + "Description": "Default parameter group for redis2.8", + "IsGlobal": false, + "id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e", + "name": "default.redis2.8" + }, + "51584be5be0c6c6af057229afd341d592a55bf0e": { + "ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.memcached1.6", + "CacheParameterGroupFamily": "memcached1.6", + "Description": "Default parameter group for memcached1.6", + "IsGlobal": false, + "id": "51584be5be0c6c6af057229afd341d592a55bf0e", + "name": "default.memcached1.6" + }, + "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": { + "ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.redis3.2", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Default parameter group for redis3.2", + "IsGlobal": false, + "id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3", + "name": "default.redis3.2" + }, + "6e3786a6f55135ca99b9432b0059a35deb2ae908": { + "ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.redis5.0", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Default parameter group for redis5.0", + "IsGlobal": false, + "id": "6e3786a6f55135ca99b9432b0059a35deb2ae908", + "name": "default.redis5.0" + }, + "89dee6407112ff413de0345de376d45c799f0028": { + "ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.redis4.0.cluster.on", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Customized default parameter group for redis4.0 with cluster mode on", + "IsGlobal": false, + "id": "89dee6407112ff413de0345de376d45c799f0028", + "name": "default.redis4.0.cluster.on" + }, + "92d124b9a74567482361fe34e367ac8bf5c02e0b": { + "ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.redis6.x", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Default parameter group for redis6.x", + "IsGlobal": false, + "id": "92d124b9a74567482361fe34e367ac8bf5c02e0b", + "name": "default.redis6.x" + }, + "a64a576f220009cfa7c322c46fc92d32a85a4978": { + "ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.redis5.0.cluster.on", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Customized default parameter group for redis5.0 with cluster mode on", + "IsGlobal": false, + "id": "a64a576f220009cfa7c322c46fc92d32a85a4978", + "name": "default.redis5.0.cluster.on" + }, + "c954e04f298cd030c6fde9c32c8365d1b9f76fb4": { + "ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.redis4.0", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Default parameter group for redis4.0", + "IsGlobal": false, + "id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4", + "name": "default.redis4.0" + }, + "e0934919fe4741105df762ae57b738fea22ebc40": { + "ARN": "arn:aws:elasticache:us-east-2:430150006394:parametergroup:default.memcached1.5", + "CacheParameterGroupFamily": "memcached1.5", + "Description": "Default parameter group for memcached1.5", + "IsGlobal": false, + "id": "e0934919fe4741105df762ae57b738fea22ebc40", + "name": "default.memcached1.5" + } + }, + "parameter_groups_count": 12, + "region": "us-east-2", + "security_groups": {}, + "security_groups_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-e429ad8f": { + "arn": "arn:aws:vpc:us-east-2:430150006394:virtual-private-cloud/vpc-e429ad8f", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-e429ad8f", + "name": "vpc-e429ad8f", + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "us-west-1": { + "clusters_count": 0, + "id": "us-west-1", + "name": "us-west-1", + "parameter_groups": { + "02e3d792a7e00a39f3c9fa0bb0445e86d7644525": { + "ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.redis3.2.cluster.on", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Customized default parameter group for redis3.2 with cluster mode on", + "IsGlobal": false, + "id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525", + "name": "default.redis3.2.cluster.on" + }, + "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": { + "ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.memcached1.4", + "CacheParameterGroupFamily": "memcached1.4", + "Description": "Default parameter group for memcached1.4", + "IsGlobal": false, + "id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124", + "name": "default.memcached1.4" + }, + "1a65eec91cd66eb16ba40e781620d9320ec1733f": { + "ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.redis6.x.cluster.on", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Customized default parameter group for redis6.x with cluster mode on", + "IsGlobal": false, + "id": "1a65eec91cd66eb16ba40e781620d9320ec1733f", + "name": "default.redis6.x.cluster.on" + }, + "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": { + "ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.redis2.8", + "CacheParameterGroupFamily": "redis2.8", + "Description": "Default parameter group for redis2.8", + "IsGlobal": false, + "id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e", + "name": "default.redis2.8" + }, + "51584be5be0c6c6af057229afd341d592a55bf0e": { + "ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.memcached1.6", + "CacheParameterGroupFamily": "memcached1.6", + "Description": "Default parameter group for memcached1.6", + "IsGlobal": false, + "id": "51584be5be0c6c6af057229afd341d592a55bf0e", + "name": "default.memcached1.6" + }, + "533bd3e057f46120794828b5c797b3fe8aab1336": { + "ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.redis2.6", + "CacheParameterGroupFamily": "redis2.6", + "Description": "Default parameter group for redis2.6", + "IsGlobal": false, + "id": "533bd3e057f46120794828b5c797b3fe8aab1336", + "name": "default.redis2.6" + }, + "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": { + "ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.redis3.2", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Default parameter group for redis3.2", + "IsGlobal": false, + "id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3", + "name": "default.redis3.2" + }, + "6e3786a6f55135ca99b9432b0059a35deb2ae908": { + "ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.redis5.0", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Default parameter group for redis5.0", + "IsGlobal": false, + "id": "6e3786a6f55135ca99b9432b0059a35deb2ae908", + "name": "default.redis5.0" + }, + "89dee6407112ff413de0345de376d45c799f0028": { + "ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.redis4.0.cluster.on", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Customized default parameter group for redis4.0 with cluster mode on", + "IsGlobal": false, + "id": "89dee6407112ff413de0345de376d45c799f0028", + "name": "default.redis4.0.cluster.on" + }, + "92d124b9a74567482361fe34e367ac8bf5c02e0b": { + "ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.redis6.x", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Default parameter group for redis6.x", + "IsGlobal": false, + "id": "92d124b9a74567482361fe34e367ac8bf5c02e0b", + "name": "default.redis6.x" + }, + "a64a576f220009cfa7c322c46fc92d32a85a4978": { + "ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.redis5.0.cluster.on", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Customized default parameter group for redis5.0 with cluster mode on", + "IsGlobal": false, + "id": "a64a576f220009cfa7c322c46fc92d32a85a4978", + "name": "default.redis5.0.cluster.on" + }, + "c954e04f298cd030c6fde9c32c8365d1b9f76fb4": { + "ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.redis4.0", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Default parameter group for redis4.0", + "IsGlobal": false, + "id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4", + "name": "default.redis4.0" + }, + "e0934919fe4741105df762ae57b738fea22ebc40": { + "ARN": "arn:aws:elasticache:us-west-1:430150006394:parametergroup:default.memcached1.5", + "CacheParameterGroupFamily": "memcached1.5", + "Description": "Default parameter group for memcached1.5", + "IsGlobal": false, + "id": "e0934919fe4741105df762ae57b738fea22ebc40", + "name": "default.memcached1.5" + } + }, + "parameter_groups_count": 13, + "region": "us-west-1", + "security_groups": {}, + "security_groups_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-6e6fa508": { + "arn": "arn:aws:vpc:us-west-1:430150006394:virtual-private-cloud/vpc-6e6fa508", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-6e6fa508", + "name": "vpc-6e6fa508", + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "us-west-2": { + "clusters_count": 0, + "id": "us-west-2", + "name": "us-west-2", + "parameter_groups": { + "02e3d792a7e00a39f3c9fa0bb0445e86d7644525": { + "ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.redis3.2.cluster.on", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Customized default parameter group for redis3.2 with cluster mode on", + "IsGlobal": false, + "id": "02e3d792a7e00a39f3c9fa0bb0445e86d7644525", + "name": "default.redis3.2.cluster.on" + }, + "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124": { + "ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.memcached1.4", + "CacheParameterGroupFamily": "memcached1.4", + "Description": "Default parameter group for memcached1.4", + "IsGlobal": false, + "id": "156fb85ac56ddbaeb3fbfc0cfa4b423ef3d58124", + "name": "default.memcached1.4" + }, + "1a65eec91cd66eb16ba40e781620d9320ec1733f": { + "ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.redis6.x.cluster.on", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Customized default parameter group for redis6.x with cluster mode on", + "IsGlobal": false, + "id": "1a65eec91cd66eb16ba40e781620d9320ec1733f", + "name": "default.redis6.x.cluster.on" + }, + "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e": { + "ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.redis2.8", + "CacheParameterGroupFamily": "redis2.8", + "Description": "Default parameter group for redis2.8", + "IsGlobal": false, + "id": "3b3a45e6801b43ee92ebac794ec8d2fdef1b979e", + "name": "default.redis2.8" + }, + "51584be5be0c6c6af057229afd341d592a55bf0e": { + "ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.memcached1.6", + "CacheParameterGroupFamily": "memcached1.6", + "Description": "Default parameter group for memcached1.6", + "IsGlobal": false, + "id": "51584be5be0c6c6af057229afd341d592a55bf0e", + "name": "default.memcached1.6" + }, + "533bd3e057f46120794828b5c797b3fe8aab1336": { + "ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.redis2.6", + "CacheParameterGroupFamily": "redis2.6", + "Description": "Default parameter group for redis2.6", + "IsGlobal": false, + "id": "533bd3e057f46120794828b5c797b3fe8aab1336", + "name": "default.redis2.6" + }, + "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3": { + "ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.redis3.2", + "CacheParameterGroupFamily": "redis3.2", + "Description": "Default parameter group for redis3.2", + "IsGlobal": false, + "id": "579b3fd007c744dbecbcd8bfc8c002bfac7ff8d3", + "name": "default.redis3.2" + }, + "6e3786a6f55135ca99b9432b0059a35deb2ae908": { + "ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.redis5.0", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Default parameter group for redis5.0", + "IsGlobal": false, + "id": "6e3786a6f55135ca99b9432b0059a35deb2ae908", + "name": "default.redis5.0" + }, + "89dee6407112ff413de0345de376d45c799f0028": { + "ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.redis4.0.cluster.on", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Customized default parameter group for redis4.0 with cluster mode on", + "IsGlobal": false, + "id": "89dee6407112ff413de0345de376d45c799f0028", + "name": "default.redis4.0.cluster.on" + }, + "92d124b9a74567482361fe34e367ac8bf5c02e0b": { + "ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.redis6.x", + "CacheParameterGroupFamily": "redis6.x", + "Description": "Default parameter group for redis6.x", + "IsGlobal": false, + "id": "92d124b9a74567482361fe34e367ac8bf5c02e0b", + "name": "default.redis6.x" + }, + "a64a576f220009cfa7c322c46fc92d32a85a4978": { + "ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.redis5.0.cluster.on", + "CacheParameterGroupFamily": "redis5.0", + "Description": "Customized default parameter group for redis5.0 with cluster mode on", + "IsGlobal": false, + "id": "a64a576f220009cfa7c322c46fc92d32a85a4978", + "name": "default.redis5.0.cluster.on" + }, + "c954e04f298cd030c6fde9c32c8365d1b9f76fb4": { + "ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.redis4.0", + "CacheParameterGroupFamily": "redis4.0", + "Description": "Default parameter group for redis4.0", + "IsGlobal": false, + "id": "c954e04f298cd030c6fde9c32c8365d1b9f76fb4", + "name": "default.redis4.0" + }, + "e0934919fe4741105df762ae57b738fea22ebc40": { + "ARN": "arn:aws:elasticache:us-west-2:430150006394:parametergroup:default.memcached1.5", + "CacheParameterGroupFamily": "memcached1.5", + "Description": "Default parameter group for memcached1.5", + "IsGlobal": false, + "id": "e0934919fe4741105df762ae57b738fea22ebc40", + "name": "default.memcached1.5" + } + }, + "parameter_groups_count": 13, + "region": "us-west-2", + "security_groups": {}, + "security_groups_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-d45709ac": { + "arn": "arn:aws:vpc:us-west-2:430150006394:virtual-private-cloud/vpc-d45709ac", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-d45709ac", + "name": "vpc-d45709ac", + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + } + }, + "regions_count": 17, + "security_groups_count": 0 + }, + "elb": { + "elb_policies_count": 0, + "filters": {}, + "findings": { + "elb-listener-allowing-cleartext": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Load Balancer Listeners", + "description": "Load Balancer Allowing Clear Text (HTTP) Communication", + "display_path": "elb.regions.id.vpcs.id.elbs.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "elb.regions.id.vpcs.id.elbs.id.listeners.id", + "rationale": "Use of a secure protocol (HTTPS or SSL) is best practice for encrypted communication. A load balancer without a listener using an encrypted protocol can be vulnerable to eavesdropping and man-in-the-middle attacks.", + "references": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-listener-config.html" + ], + "remediation": null, + "service": "ELB" + }, + "elb-no-access-logs": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Load Balancers", + "description": "Lack of ELB Access Logs", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "elb.regions.id.vpcs.id.elbs.id", + "rationale": "Elastic Load Balancing provides access logs that capture detailed information about requests sent to your load balancer. Each log contains information such as the time the request was received, the client's IP address, latencies, request paths, and server responses. You can use these access logs to analyze traffic patterns and identify security issues.", + "references": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/access-log-collection.html" + ], + "remediation": null, + "service": "ELB" + }, + "elb-older-ssl-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Load Balancer Listeners Security Policy", + "description": "Older SSL/TLS Policy", + "display_path": "elb.regions.id.elb_policies.id.reference_security_policy", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "elb.regions.id.elb_policies.id.reference_security_policy", + "rationale": "Use of the latest TLS policies is best practice. The recommended predefined security policies are:
  • ELBSecurityPolicy-2016-08
  • ELBSecurityPolicy-FS-2018-06
  • ELBSecurityPolicy-TLS-1-1-2017-01
  • ELBSecurityPolicy-TLS-1-2-2017-01
  • ELBSecurityPolicy-TLS-1-2-Ext-2018-06
  • ELBSecurityPolicy-FS-1-1-2019-08
  • ELBSecurityPolicy-FS-1-2-2019-08
  • ELBSecurityPolicy-FS-1-2-Res-2019-08
", + "references": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-policy-table.html" + ], + "remediation": null, + "service": "ELB" + } + }, + "regions": { + "ap-northeast-1": { + "elb_policies": {}, + "elb_policies_count": 0, + "id": "ap-northeast-1", + "name": "ap-northeast-1", + "region": "ap-northeast-1", + "vpcs": { + "vpc-0cbc506a": { + "arn": "arn:aws:vpc:ap-northeast-1:430150006394:virtual-private-cloud/vpc-0cbc506a", + "cidr_block": "172.31.0.0/16", + "default": true, + "elbs": {}, + "elbs_count": 0, + "id": "vpc-0cbc506a", + "name": "vpc-0cbc506a", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ap-northeast-2": { + "elb_policies": {}, + "elb_policies_count": 0, + "id": "ap-northeast-2", + "name": "ap-northeast-2", + "region": "ap-northeast-2", + "vpcs": { + "vpc-73f44e18": { + "arn": "arn:aws:vpc:ap-northeast-2:430150006394:virtual-private-cloud/vpc-73f44e18", + "cidr_block": "172.31.0.0/16", + "default": true, + "elbs": {}, + "elbs_count": 0, + "id": "vpc-73f44e18", + "name": "vpc-73f44e18", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ap-northeast-3": { + "elb_policies": {}, + "elb_policies_count": 0, + "id": "ap-northeast-3", + "name": "ap-northeast-3", + "region": "ap-northeast-3", + "vpcs": { + "vpc-47b7dd2e": { + "arn": "arn:aws:vpc:ap-northeast-3:430150006394:virtual-private-cloud/vpc-47b7dd2e", + "cidr_block": "172.31.0.0/16", + "default": true, + "elbs": {}, + "elbs_count": 0, + "id": "vpc-47b7dd2e", + "name": "vpc-47b7dd2e", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ap-south-1": { + "elb_policies": {}, + "elb_policies_count": 0, + "id": "ap-south-1", + "name": "ap-south-1", + "region": "ap-south-1", + "vpcs": { + "vpc-2651a14d": { + "arn": "arn:aws:vpc:ap-south-1:430150006394:virtual-private-cloud/vpc-2651a14d", + "cidr_block": "172.31.0.0/16", + "default": true, + "elbs": {}, + "elbs_count": 0, + "id": "vpc-2651a14d", + "name": "vpc-2651a14d", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ap-southeast-1": { + "elb_policies": {}, + "elb_policies_count": 0, + "id": "ap-southeast-1", + "name": "ap-southeast-1", + "region": "ap-southeast-1", + "vpcs": { + "vpc-04ed1062": { + "arn": "arn:aws:vpc:ap-southeast-1:430150006394:virtual-private-cloud/vpc-04ed1062", + "cidr_block": "172.31.0.0/16", + "default": true, + "elbs": {}, + "elbs_count": 0, + "id": "vpc-04ed1062", + "name": "vpc-04ed1062", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ap-southeast-2": { + "elb_policies": {}, + "elb_policies_count": 0, + "id": "ap-southeast-2", + "name": "ap-southeast-2", + "region": "ap-southeast-2", + "vpcs": { + "vpc-5d22c33b": { + "arn": "arn:aws:vpc:ap-southeast-2:430150006394:virtual-private-cloud/vpc-5d22c33b", + "cidr_block": "172.31.0.0/16", + "default": true, + "elbs": {}, + "elbs_count": 0, + "id": "vpc-5d22c33b", + "name": "vpc-5d22c33b", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ca-central-1": { + "elb_policies": {}, + "elb_policies_count": 0, + "id": "ca-central-1", + "name": "ca-central-1", + "region": "ca-central-1", + "vpcs": { + "vpc-b5113ddd": { + "arn": "arn:aws:vpc:ca-central-1:430150006394:virtual-private-cloud/vpc-b5113ddd", + "cidr_block": "172.31.0.0/16", + "default": true, + "elbs": {}, + "elbs_count": 0, + "id": "vpc-b5113ddd", + "name": "vpc-b5113ddd", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "eu-central-1": { + "elb_policies": {}, + "elb_policies_count": 0, + "id": "eu-central-1", + "name": "eu-central-1", + "region": "eu-central-1", + "vpcs": { + "vpc-78b43312": { + "arn": "arn:aws:vpc:eu-central-1:430150006394:virtual-private-cloud/vpc-78b43312", + "cidr_block": "172.31.0.0/16", + "default": true, + "elbs": {}, + "elbs_count": 0, + "id": "vpc-78b43312", + "name": "vpc-78b43312", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "eu-north-1": { + "elb_policies": {}, + "elb_policies_count": 0, + "id": "eu-north-1", + "name": "eu-north-1", + "region": "eu-north-1", + "vpcs": { + "vpc-fa259d93": { + "arn": "arn:aws:vpc:eu-north-1:430150006394:virtual-private-cloud/vpc-fa259d93", + "cidr_block": "172.31.0.0/16", + "default": true, + "elbs": {}, + "elbs_count": 0, + "id": "vpc-fa259d93", + "name": "vpc-fa259d93", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "eu-west-1": { + "elb_policies": {}, + "elb_policies_count": 0, + "id": "eu-west-1", + "name": "eu-west-1", + "region": "eu-west-1", + "vpcs": { + "vpc-f24c7994": { + "arn": "arn:aws:vpc:eu-west-1:430150006394:virtual-private-cloud/vpc-f24c7994", + "cidr_block": "172.31.0.0/16", + "default": true, + "elbs": {}, + "elbs_count": 0, + "id": "vpc-f24c7994", + "name": "vpc-f24c7994", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "eu-west-2": { + "elb_policies": {}, + "elb_policies_count": 0, + "id": "eu-west-2", + "name": "eu-west-2", + "region": "eu-west-2", + "vpcs": { + "vpc-3fa2fa57": { + "arn": "arn:aws:vpc:eu-west-2:430150006394:virtual-private-cloud/vpc-3fa2fa57", + "cidr_block": "172.31.0.0/16", + "default": true, + "elbs": {}, + "elbs_count": 0, + "id": "vpc-3fa2fa57", + "name": "vpc-3fa2fa57", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "eu-west-3": { + "elb_policies": {}, + "elb_policies_count": 0, + "id": "eu-west-3", + "name": "eu-west-3", + "region": "eu-west-3", + "vpcs": { + "vpc-87d3fdee": { + "arn": "arn:aws:vpc:eu-west-3:430150006394:virtual-private-cloud/vpc-87d3fdee", + "cidr_block": "172.31.0.0/16", + "default": true, + "elbs": {}, + "elbs_count": 0, + "id": "vpc-87d3fdee", + "name": "vpc-87d3fdee", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "sa-east-1": { + "elb_policies": {}, + "elb_policies_count": 0, + "id": "sa-east-1", + "name": "sa-east-1", + "region": "sa-east-1", + "vpcs": { + "vpc-b14fa4d7": { + "arn": "arn:aws:vpc:sa-east-1:430150006394:virtual-private-cloud/vpc-b14fa4d7", + "cidr_block": "172.31.0.0/16", + "default": true, + "elbs": {}, + "elbs_count": 0, + "id": "vpc-b14fa4d7", + "name": "vpc-b14fa4d7", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "us-east-1": { + "elb_policies": {}, + "elb_policies_count": 0, + "id": "us-east-1", + "name": "us-east-1", + "region": "us-east-1", + "vpcs": { + "vpc-ba1cbdc7": { + "arn": "arn:aws:vpc:us-east-1:430150006394:virtual-private-cloud/vpc-ba1cbdc7", + "cidr_block": "172.31.0.0/16", + "default": true, + "elbs": {}, + "elbs_count": 0, + "id": "vpc-ba1cbdc7", + "name": "vpc-ba1cbdc7", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "us-east-2": { + "elb_policies": {}, + "elb_policies_count": 0, + "id": "us-east-2", + "name": "us-east-2", + "region": "us-east-2", + "vpcs": { + "vpc-e429ad8f": { + "arn": "arn:aws:vpc:us-east-2:430150006394:virtual-private-cloud/vpc-e429ad8f", + "cidr_block": "172.31.0.0/16", + "default": true, + "elbs": {}, + "elbs_count": 0, + "id": "vpc-e429ad8f", + "name": "vpc-e429ad8f", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "us-west-1": { + "elb_policies": {}, + "elb_policies_count": 0, + "id": "us-west-1", + "name": "us-west-1", + "region": "us-west-1", + "vpcs": { + "vpc-6e6fa508": { + "arn": "arn:aws:vpc:us-west-1:430150006394:virtual-private-cloud/vpc-6e6fa508", + "cidr_block": "172.31.0.0/16", + "default": true, + "elbs": {}, + "elbs_count": 0, + "id": "vpc-6e6fa508", + "name": "vpc-6e6fa508", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "us-west-2": { + "elb_policies": {}, + "elb_policies_count": 0, + "id": "us-west-2", + "name": "us-west-2", + "region": "us-west-2", + "vpcs": { + "vpc-d45709ac": { + "arn": "arn:aws:vpc:us-west-2:430150006394:virtual-private-cloud/vpc-d45709ac", + "cidr_block": "172.31.0.0/16", + "default": true, + "elbs": {}, + "elbs_count": 0, + "id": "vpc-d45709ac", + "name": "vpc-d45709ac", + "state": "available" + } + }, + "vpcs_count": 1 + } + }, + "regions_count": 17 + }, + "elbv2": { + "filters": {}, + "findings": { + "elbv2-http-request-smuggling": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Load Balancer Attributes", + "description": "Drop Invalid Header Fields Disabled", + "display_path": "elbv2.regions.id.vpcs.id.lbs.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "elbv2.regions.id.vpcs.id.lbs.id.attributes.id", + "rationale": "Dropping invalid header fields should be enabled in order to mitigate the risk of request smuggling attacks.", + "references": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/API_LoadBalancerAttribute.html", + "https://medium.com/@emilefugulin/http-desync-attacks-with-python-and-aws-1ba07d2c860f", + "https://99designs.com/blog/engineering/request-smuggling/", + "https://portswigger.net/web-security/request-smuggling" + ], + "remediation": null, + "service": "ELBv2" + }, + "elbv2-listener-allowing-cleartext": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Load Balancer Listeners", + "description": "Load Balancer Allowing Clear Text (HTTP) Communication", + "display_path": "elbv2.regions.id.vpcs.id.lbs.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "elbv2.regions.id.vpcs.id.lbs.id.listeners.id.Protocol", + "rationale": "Use of a secure protocol (HTTPS or SSL) is best practice for encrypted communication. A load balancer without a listener using an encrypted protocol can be vulnerable to eavesdropping and man-in-the-middle attacks.", + "references": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-https-load-balancers.html", + "https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html", + "https://docs.aws.amazon.com/elasticloadbalancing/latest/network/create-tls-listener.html" + ], + "remediation": null, + "service": "ELBv2" + }, + "elbv2-no-access-logs": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Load Balancer Attributes", + "description": "Lack of ELBv2 Access Logs", + "display_path": "elbv2.regions.id.vpcs.id.lbs.id", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "elbv2.regions.id.vpcs.id.lbs.id.attributes.id", + "rationale": "Elastic Load Balancing provides access logs that capture detailed information about requests sent to your load balancer. Each log contains information such as the time the request was received, the client's IP address, latencies, request paths, and server responses. You can use these access logs to analyze traffic patterns and identify security issues.

Note that for Network Load Balancers, access logs are created only if the load balancer has a TLS listener.", + "references": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html", + "https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-access-logs.html" + ], + "remediation": null, + "service": "ELBv2" + }, + "elbv2-no-deletion-protection": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Load Balancer Attributes", + "description": "Lack of Deletion Protection", + "display_path": "elbv2.regions.id.vpcs.id.lbs.id", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "elbv2.regions.id.vpcs.id.lbs.id.attributes.id", + "rationale": "Enabling deletion protection on load balancers mitigates risks of accidental deletion.", + "references": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#deletion-protection" + ], + "remediation": null, + "service": "ELBv2" + }, + "elbv2-older-ssl-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Load Balancer Listeners", + "description": "Older SSL/TLS Policy", + "display_path": "elbv2.regions.id.vpcs.id.lbs.id", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "elbv2.regions.id.vpcs.id.lbs.id.listeners.id.SslPolicy", + "rationale": "Use of the latest TLS policies is best practice. The recommended predefined security policies are:
  • ELBSecurityPolicy-2016-08
  • ELBSecurityPolicy-FS-2018-06
  • ELBSecurityPolicy-TLS-1-1-2017-01
  • ELBSecurityPolicy-TLS-1-2-2017-01
  • ELBSecurityPolicy-TLS-1-2-Ext-2018-06
  • ELBSecurityPolicy-FS-1-1-2019-08
  • ELBSecurityPolicy-FS-1-2-2019-08
  • ELBSecurityPolicy-FS-1-2-Res-2019-08
", + "references": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html#describe-ssl-policies" + ], + "remediation": null, + "service": "ELBv2" + } + }, + "regions": { + "ap-northeast-1": { + "id": "ap-northeast-1", + "name": "ap-northeast-1", + "region": "ap-northeast-1", + "vpcs": { + "vpc-0cbc506a": { + "arn": "arn:aws:vpc:ap-northeast-1:430150006394:virtual-private-cloud/vpc-0cbc506a", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-0cbc506a", + "lbs": {}, + "lbs_count": 0, + "name": "vpc-0cbc506a", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ap-northeast-2": { + "id": "ap-northeast-2", + "name": "ap-northeast-2", + "region": "ap-northeast-2", + "vpcs": { + "vpc-73f44e18": { + "arn": "arn:aws:vpc:ap-northeast-2:430150006394:virtual-private-cloud/vpc-73f44e18", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-73f44e18", + "lbs": {}, + "lbs_count": 0, + "name": "vpc-73f44e18", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ap-northeast-3": { + "id": "ap-northeast-3", + "name": "ap-northeast-3", + "region": "ap-northeast-3", + "vpcs": { + "vpc-47b7dd2e": { + "arn": "arn:aws:vpc:ap-northeast-3:430150006394:virtual-private-cloud/vpc-47b7dd2e", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-47b7dd2e", + "lbs": {}, + "lbs_count": 0, + "name": "vpc-47b7dd2e", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ap-south-1": { + "id": "ap-south-1", + "name": "ap-south-1", + "region": "ap-south-1", + "vpcs": { + "vpc-2651a14d": { + "arn": "arn:aws:vpc:ap-south-1:430150006394:virtual-private-cloud/vpc-2651a14d", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-2651a14d", + "lbs": {}, + "lbs_count": 0, + "name": "vpc-2651a14d", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ap-southeast-1": { + "id": "ap-southeast-1", + "name": "ap-southeast-1", + "region": "ap-southeast-1", + "vpcs": { + "vpc-04ed1062": { + "arn": "arn:aws:vpc:ap-southeast-1:430150006394:virtual-private-cloud/vpc-04ed1062", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-04ed1062", + "lbs": {}, + "lbs_count": 0, + "name": "vpc-04ed1062", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ap-southeast-2": { + "id": "ap-southeast-2", + "name": "ap-southeast-2", + "region": "ap-southeast-2", + "vpcs": { + "vpc-5d22c33b": { + "arn": "arn:aws:vpc:ap-southeast-2:430150006394:virtual-private-cloud/vpc-5d22c33b", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-5d22c33b", + "lbs": {}, + "lbs_count": 0, + "name": "vpc-5d22c33b", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ca-central-1": { + "id": "ca-central-1", + "name": "ca-central-1", + "region": "ca-central-1", + "vpcs": { + "vpc-b5113ddd": { + "arn": "arn:aws:vpc:ca-central-1:430150006394:virtual-private-cloud/vpc-b5113ddd", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-b5113ddd", + "lbs": {}, + "lbs_count": 0, + "name": "vpc-b5113ddd", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "eu-central-1": { + "id": "eu-central-1", + "name": "eu-central-1", + "region": "eu-central-1", + "vpcs": { + "vpc-78b43312": { + "arn": "arn:aws:vpc:eu-central-1:430150006394:virtual-private-cloud/vpc-78b43312", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-78b43312", + "lbs": {}, + "lbs_count": 0, + "name": "vpc-78b43312", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "eu-north-1": { + "id": "eu-north-1", + "name": "eu-north-1", + "region": "eu-north-1", + "vpcs": { + "vpc-fa259d93": { + "arn": "arn:aws:vpc:eu-north-1:430150006394:virtual-private-cloud/vpc-fa259d93", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-fa259d93", + "lbs": {}, + "lbs_count": 0, + "name": "vpc-fa259d93", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "eu-west-1": { + "id": "eu-west-1", + "name": "eu-west-1", + "region": "eu-west-1", + "vpcs": { + "vpc-f24c7994": { + "arn": "arn:aws:vpc:eu-west-1:430150006394:virtual-private-cloud/vpc-f24c7994", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-f24c7994", + "lbs": {}, + "lbs_count": 0, + "name": "vpc-f24c7994", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "eu-west-2": { + "id": "eu-west-2", + "name": "eu-west-2", + "region": "eu-west-2", + "vpcs": { + "vpc-3fa2fa57": { + "arn": "arn:aws:vpc:eu-west-2:430150006394:virtual-private-cloud/vpc-3fa2fa57", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-3fa2fa57", + "lbs": {}, + "lbs_count": 0, + "name": "vpc-3fa2fa57", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "eu-west-3": { + "id": "eu-west-3", + "name": "eu-west-3", + "region": "eu-west-3", + "vpcs": { + "vpc-87d3fdee": { + "arn": "arn:aws:vpc:eu-west-3:430150006394:virtual-private-cloud/vpc-87d3fdee", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-87d3fdee", + "lbs": {}, + "lbs_count": 0, + "name": "vpc-87d3fdee", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "sa-east-1": { + "id": "sa-east-1", + "name": "sa-east-1", + "region": "sa-east-1", + "vpcs": { + "vpc-b14fa4d7": { + "arn": "arn:aws:vpc:sa-east-1:430150006394:virtual-private-cloud/vpc-b14fa4d7", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-b14fa4d7", + "lbs": {}, + "lbs_count": 0, + "name": "vpc-b14fa4d7", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "us-east-1": { + "id": "us-east-1", + "name": "us-east-1", + "region": "us-east-1", + "vpcs": { + "vpc-ba1cbdc7": { + "arn": "arn:aws:vpc:us-east-1:430150006394:virtual-private-cloud/vpc-ba1cbdc7", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-ba1cbdc7", + "lbs": {}, + "lbs_count": 0, + "name": "vpc-ba1cbdc7", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "us-east-2": { + "id": "us-east-2", + "name": "us-east-2", + "region": "us-east-2", + "vpcs": { + "vpc-e429ad8f": { + "arn": "arn:aws:vpc:us-east-2:430150006394:virtual-private-cloud/vpc-e429ad8f", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-e429ad8f", + "lbs": {}, + "lbs_count": 0, + "name": "vpc-e429ad8f", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "us-west-1": { + "id": "us-west-1", + "name": "us-west-1", + "region": "us-west-1", + "vpcs": { + "vpc-6e6fa508": { + "arn": "arn:aws:vpc:us-west-1:430150006394:virtual-private-cloud/vpc-6e6fa508", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-6e6fa508", + "lbs": {}, + "lbs_count": 0, + "name": "vpc-6e6fa508", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "us-west-2": { + "id": "us-west-2", + "name": "us-west-2", + "region": "us-west-2", + "vpcs": { + "vpc-d45709ac": { + "arn": "arn:aws:vpc:us-west-2:430150006394:virtual-private-cloud/vpc-d45709ac", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-d45709ac", + "lbs": {}, + "lbs_count": 0, + "name": "vpc-d45709ac", + "state": "available" + } + }, + "vpcs_count": 1 + } + }, + "regions_count": 17 + }, + "emr": { + "clusters_count": 0, + "filters": {}, + "findings": {}, + "regions": { + "ap-northeast-1": { + "clusters_count": 0, + "id": "ap-northeast-1", + "name": "ap-northeast-1", + "region": "ap-northeast-1", + "vpcs": {}, + "vpcs_count": 1 + }, + "ap-northeast-2": { + "clusters_count": 0, + "id": "ap-northeast-2", + "name": "ap-northeast-2", + "region": "ap-northeast-2", + "vpcs": {}, + "vpcs_count": 1 + }, + "ap-northeast-3": { + "clusters_count": 0, + "id": "ap-northeast-3", + "name": "ap-northeast-3", + "region": "ap-northeast-3", + "vpcs": {}, + "vpcs_count": 1 + }, + "ap-south-1": { + "clusters_count": 0, + "id": "ap-south-1", + "name": "ap-south-1", + "region": "ap-south-1", + "vpcs": {}, + "vpcs_count": 1 + }, + "ap-southeast-1": { + "clusters_count": 0, + "id": "ap-southeast-1", + "name": "ap-southeast-1", + "region": "ap-southeast-1", + "vpcs": {}, + "vpcs_count": 1 + }, + "ap-southeast-2": { + "clusters_count": 0, + "id": "ap-southeast-2", + "name": "ap-southeast-2", + "region": "ap-southeast-2", + "vpcs": {}, + "vpcs_count": 1 + }, + "ca-central-1": { + "clusters_count": 0, + "id": "ca-central-1", + "name": "ca-central-1", + "region": "ca-central-1", + "vpcs": {}, + "vpcs_count": 1 + }, + "eu-central-1": { + "clusters_count": 0, + "id": "eu-central-1", + "name": "eu-central-1", + "region": "eu-central-1", + "vpcs": {}, + "vpcs_count": 1 + }, + "eu-north-1": { + "clusters_count": 0, + "id": "eu-north-1", + "name": "eu-north-1", + "region": "eu-north-1", + "vpcs": {}, + "vpcs_count": 1 + }, + "eu-west-1": { + "clusters_count": 0, + "id": "eu-west-1", + "name": "eu-west-1", + "region": "eu-west-1", + "vpcs": {}, + "vpcs_count": 1 + }, + "eu-west-2": { + "clusters_count": 0, + "id": "eu-west-2", + "name": "eu-west-2", + "region": "eu-west-2", + "vpcs": {}, + "vpcs_count": 1 + }, + "eu-west-3": { + "clusters_count": 0, + "id": "eu-west-3", + "name": "eu-west-3", + "region": "eu-west-3", + "vpcs": {}, + "vpcs_count": 1 + }, + "sa-east-1": { + "clusters_count": 0, + "id": "sa-east-1", + "name": "sa-east-1", + "region": "sa-east-1", + "vpcs": {}, + "vpcs_count": 1 + }, + "us-east-1": { + "clusters_count": 0, + "id": "us-east-1", + "name": "us-east-1", + "region": "us-east-1", + "vpcs": {}, + "vpcs_count": 1 + }, + "us-east-2": { + "clusters_count": 0, + "id": "us-east-2", + "name": "us-east-2", + "region": "us-east-2", + "vpcs": {}, + "vpcs_count": 1 + }, + "us-west-1": { + "clusters_count": 0, + "id": "us-west-1", + "name": "us-west-1", + "region": "us-west-1", + "vpcs": {}, + "vpcs_count": 1 + }, + "us-west-2": { + "clusters_count": 0, + "id": "us-west-2", + "name": "us-west-2", + "region": "us-west-2", + "vpcs": {}, + "vpcs_count": 1 + } + }, + "regions_count": 17 + }, + "iam": { + "credential_reports": { + "06f47b690457429238adabc75e53fc0c93bf6c77": { + "access_key_1_active": "true", + "access_key_1_last_rotated": "2013-12-19T09:13:40+00:00", + "access_key_1_last_used_date": null, + "access_key_1_last_used_region": "N/A", + "access_key_1_last_used_service": "N/A", + "access_key_2_active": "true", + "access_key_2_last_rotated": "2019-01-25T17:58:41+00:00", + "access_key_2_last_used_date": "2021-03-19T12:26:00+00:00", + "access_key_2_last_used_region": "ca-central-1", + "access_key_2_last_used_service": "cloudwatch", + "arn": "arn:aws:iam::430150006394:user/dams", + "cert_1_active": "false", + "cert_1_last_rotated": "N/A", + "cert_2_active": "false", + "cert_2_last_rotated": "N/A", + "id": "06f47b690457429238adabc75e53fc0c93bf6c77", + "last_used": "2021-03-19T12:26:00+00:00", + "mfa_active": "false", + "mfa_active_hardware": false, + "name": "dams", + "password_enabled": "false", + "password_last_changed": null, + "password_last_used": null, + "password_next_rotation": "N/A", + "user": "dams", + "user_creation_time": "2013-12-19T09:13:40+00:00" + }, + "68dcc047c3da5bbbc3f3e9d54000b7357f0e507e": { + "access_key_1_active": "true", + "access_key_1_last_rotated": "2021-03-19T12:29:26+00:00", + "access_key_1_last_used_date": "2021-03-19T12:33:00+00:00", + "access_key_1_last_used_region": "eu-north-1", + "access_key_1_last_used_service": "ec2", + "access_key_2_active": "false", + "access_key_2_last_rotated": null, + "access_key_2_last_used_date": null, + "access_key_2_last_used_region": "N/A", + "access_key_2_last_used_service": "N/A", + "arn": "arn:aws:iam::430150006394:root", + "cert_1_active": "false", + "cert_1_last_rotated": "N/A", + "cert_2_active": "false", + "cert_2_last_rotated": "N/A", + "id": "68dcc047c3da5bbbc3f3e9d54000b7357f0e507e", + "last_used": "2021-04-28T10:51:19+00:00", + "mfa_active": "false", + "mfa_active_hardware": false, + "name": "", + "password_enabled": "not_supported", + "password_last_changed": "not_supported", + "password_last_used": "2021-04-28T10:51:19+00:00", + "password_next_rotation": "not_supported", + "user": "", + "user_creation_time": "2013-12-19T08:57:25+00:00" + } + }, + "credential_reports_count": 2, + "filters": { + "iam-role-for-EC2": { + "checked_items": 9, + "compliance": null, + "dashboard_name": "Roles", + "description": "Role for EC2", + "display_path": "iam.roles.id", + "flagged_items": 1, + "items": [ + "iam.roles.AROAI265GPNVMDZAKJPPA.assume_role_policy.PolicyDocument.Statement.0" + ], + "level": "", + "path": "iam.roles.id.assume_role_policy.PolicyDocument.Statement.id", + "rationale": null, + "references": null, + "remediation": null, + "service": "IAM" + }, + "iam-role-for-Lambda": { + "checked_items": 9, + "compliance": null, + "dashboard_name": "Roles", + "description": "Role for Lambda", + "display_path": "iam.roles.id", + "flagged_items": 1, + "items": [ + "iam.roles.AROAJY5MNJYDKGD2UIATQ.assume_role_policy.PolicyDocument.Statement.0" + ], + "level": "", + "path": "iam.roles.id.assume_role_policy.PolicyDocument.Statement.id", + "rationale": null, + "references": null, + "remediation": null, + "service": "IAM" + }, + "iam-role-for-cross-account": { + "checked_items": 9, + "compliance": null, + "dashboard_name": "Roles", + "description": "Role for cross account", + "display_path": "iam.roles.id", + "flagged_items": 0, + "items": [], + "level": "", + "path": "iam.roles.id.assume_role_policy.PolicyDocument.Statement.id", + "rationale": null, + "references": null, + "remediation": null, + "service": "IAM" + }, + "iam-role-for-same-account": { + "checked_items": 9, + "compliance": null, + "dashboard_name": "Roles", + "description": "Role for same account", + "display_path": "iam.roles.id", + "flagged_items": 0, + "items": [], + "level": "", + "path": "iam.roles.id.assume_role_policy.PolicyDocument.Statement.id", + "rationale": null, + "references": null, + "remediation": null, + "service": "IAM" + } + }, + "findings": { + "iam-assume-role-lacks-external-id-and-mfa": { + "checked_items": 9, + "compliance": null, + "dashboard_name": "Roles", + "description": "Cross-Account AssumeRole Policy Lacks External ID and MFA", + "display_path": "iam.roles.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "iam.roles.id.assume_role_policy.PolicyDocument.Statement.id", + "rationale": "When authorizing cross-account role assumption, either an External ID or MFA should be required. If the role is intended for use by a service, an External ID can prevent \"confused deputy\" attacks. If the role is intended for use by an external user, then MFA will strengthen the authentication by requiring a second factor.", + "references": [ + "https://research.nccgroup.com/2019/12/18/demystifying-aws-assumerole-and-stsexternalid/", + "https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html" + ], + "remediation": null, + "service": "IAM" + }, + "iam-assume-role-policy-allows-all": { + "checked_items": 9, + "compliance": null, + "dashboard_name": "Roles", + "description": "AssumeRole Policy Allows All Principals", + "display_path": "iam.roles.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "iam.roles.id.assume_role_policy.PolicyDocument.Statement.id", + "rationale": "Setting the AssumeRole policy's principal attribute to \"AWS:*\" means that anyone is authorized to assume the role and access the AWS account.", + "references": [ + "https://research.nccgroup.com/2019/12/18/demystifying-aws-assumerole-and-stsexternalid/" + ], + "remediation": null, + "service": "IAM" + }, + "iam-ec2-role-without-instances": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Roles", + "description": "Unused Role for EC2 Service", + "display_path": "iam.roles.id", + "flagged_items": 0, + "id_suffix": "instances", + "items": [], + "level": "warning", + "path": "iam.roles.id.assume_role_policy.Statement.id.Principal", + "rationale": "An EC2 role is defined which is unused and may not be required. This being the case, its existence in the configuration increases the risk that it may be inappropriately assigned. The unused role should be reviewed and removed if no longer required.", + "references": [ + "https://aws.amazon.com/about-aws/whats-new/2019/11/identify-unused-iam-roles-easily-and-remove-them-confidently-by-using-the-last-used-timestamp/" + ], + "remediation": null, + "service": "IAM" + }, + "iam-group-with-inline-policies": { + "checked_items": 1, + "compliance": null, + "dashboard_name": "Groups", + "description": "Group with Inline Policies", + "flagged_items": 1, + "id_suffix": "inline_policies", + "items": [ + "iam.groups.AGPAIW3P3726RZDVZBZL2.inline_policies" + ], + "level": "warning", + "path": "iam.groups.id", + "rationale": "An inline policy is a policy that's embedded in an IAM identity (a user, group, or role). These policies are harder to audit and manage, and should be deprecated in favor of managed policies.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#best-practice-managed-vs-inline", + "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html" + ], + "remediation": null, + "service": "IAM" + }, + "iam-group-with-no-users": { + "checked_items": 1, + "compliance": null, + "dashboard_name": "groups", + "description": "Group with No Users", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "iam.groups.id", + "rationale": "Groups with no users should be reviewed and deleted if not necessary.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#use-groups-for-permissions" + ], + "remediation": null, + "service": "IAM" + }, + "iam-inline-group-policy-allows-NotActions": { + "checked_items": 1, + "compliance": null, + "dashboard_name": "Statements", + "description": "Inline group Policy Allows \"NotActions\"", + "display_path": "iam.groups.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "iam.groups.id.inline_policies.id.PolicyDocument.Statement.id", + "rationale": "The combination of \"effect = allow\" and \"NotAction\" results in the policy allowing every action except those listed in the statement. The target policy does not follow the principle of least privilege because thousands of actions exist in AWS and because this policy automatically authorizes users to perform new actions created, regardless of their nature.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html", + "https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notaction.html", + "https://aws.amazon.com/blogs/security/back-to-school-understanding-the-iam-policy-grammar/" + ], + "remediation": null, + "service": "IAM" + }, + "iam-inline-group-policy-allows-iam-PassRole": { + "checked_items": 1, + "compliance": null, + "dashboard_name": "Policies", + "description": "Inline group Policy Allows \"iam:PassRole\" For All Resources", + "display_path": "iam.groups.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "iam.groups.id.inline_policies.id.PolicyDocument.Statement.id", + "rationale": "Using \"*\" for the resource field might grant permissions to more resources than necessary, potentially introducing privilege escalation scenarios.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html" + ], + "remediation": null, + "service": "IAM" + }, + "iam-inline-group-policy-allows-sts-AssumeRole": { + "checked_items": 1, + "compliance": null, + "dashboard_name": "Policies", + "description": "Inline group Policy Allows \"sts:AssumeRole\" For All Resources", + "display_path": "iam.groups.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "iam.groups.id.inline_policies.id.PolicyDocument.Statement.id", + "rationale": "Using \"*\" for the resource field might grant permissions to more resources than necessary, potentially introducing privilege escalation scenarios.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html" + ], + "remediation": null, + "service": "IAM" + }, + "iam-inline-role-policy-allows-NotActions": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Statements", + "description": "Inline role Policy Allows \"NotActions\"", + "display_path": "iam.roles.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "iam.roles.id.inline_policies.id.PolicyDocument.Statement.id", + "rationale": "The combination of \"effect = allow\" and \"NotAction\" results in the policy allowing every action except those listed in the statement. The target policy does not follow the principle of least privilege because thousands of actions exist in AWS and because this policy automatically authorizes users to perform new actions created, regardless of their nature.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html", + "https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notaction.html", + "https://aws.amazon.com/blogs/security/back-to-school-understanding-the-iam-policy-grammar/" + ], + "remediation": null, + "service": "IAM" + }, + "iam-inline-role-policy-allows-iam-PassRole": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Policies", + "description": "Inline role Policy Allows \"iam:PassRole\" For All Resources", + "display_path": "iam.roles.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "iam.roles.id.inline_policies.id.PolicyDocument.Statement.id", + "rationale": "Using \"*\" for the resource field might grant permissions to more resources than necessary, potentially introducing privilege escalation scenarios.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html" + ], + "remediation": null, + "service": "IAM" + }, + "iam-inline-role-policy-allows-sts-AssumeRole": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Policies", + "description": "Inline role Policy Allows \"sts:AssumeRole\" For All Resources", + "display_path": "iam.roles.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "iam.roles.id.inline_policies.id.PolicyDocument.Statement.id", + "rationale": "Using \"*\" for the resource field might grant permissions to more resources than necessary, potentially introducing privilege escalation scenarios.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html" + ], + "remediation": null, + "service": "IAM" + }, + "iam-inline-user-policy-allows-NotActions": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Statements", + "description": "Inline user Policy Allows \"NotActions\"", + "display_path": "iam.users.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "iam.users.id.inline_policies.id.PolicyDocument.Statement.id", + "rationale": "The combination of \"effect = allow\" and \"NotAction\" results in the policy allowing every action except those listed in the statement. The target policy does not follow the principle of least privilege because thousands of actions exist in AWS and because this policy automatically authorizes users to perform new actions created, regardless of their nature.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html", + "https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notaction.html", + "https://aws.amazon.com/blogs/security/back-to-school-understanding-the-iam-policy-grammar/" + ], + "remediation": null, + "service": "IAM" + }, + "iam-inline-user-policy-allows-iam-PassRole": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Policies", + "description": "Inline user Policy Allows \"iam:PassRole\" For All Resources", + "display_path": "iam.users.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "iam.users.id.inline_policies.id.PolicyDocument.Statement.id", + "rationale": "Using \"*\" for the resource field might grant permissions to more resources than necessary, potentially introducing privilege escalation scenarios.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html" + ], + "remediation": null, + "service": "IAM" + }, + "iam-inline-user-policy-allows-sts-AssumeRole": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Policies", + "description": "Inline user Policy Allows \"sts:AssumeRole\" For All Resources", + "display_path": "iam.users.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "iam.users.id.inline_policies.id.PolicyDocument.Statement.id", + "rationale": "Using \"*\" for the resource field might grant permissions to more resources than necessary, potentially introducing privilege escalation scenarios.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html" + ], + "remediation": null, + "service": "IAM" + }, + "iam-managed-policy-allows-NotActions": { + "checked_items": 14, + "compliance": null, + "dashboard_name": "Statements", + "description": "Managed Policy Allows \"NotActions\"", + "display_path": "iam.policies.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "iam.policies.id.PolicyDocument.Statement.id", + "rationale": "The combination of \"effect = allow\" and \"NotAction\" results in the policy allowing every action except those listed in the statement. The target policy does not follow the principle of least privilege because thousands of actions exist in AWS and because this policy automatically authorizes users to perform new actions created, regardless of their nature.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notaction.html", + "https://aws.amazon.com/blogs/security/back-to-school-understanding-the-iam-policy-grammar/" + ], + "remediation": null, + "service": "IAM" + }, + "iam-managed-policy-allows-full-privileges": { + "checked_items": 14, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.24", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.22", + "version": "1.2.0" + } + ], + "dashboard_name": "Statements", + "description": "Managed Policy Allows All Actions", + "display_path": "iam.policies.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "iam.policies.id.PolicyDocument.Statement.id", + "rationale": "Providing full privileges instead of restricting to the minimum set of permissions that the principal requires exposes the resources to potentially unwanted actions.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html", + "https://aws.amazon.com/blogs/security/back-to-school-understanding-the-iam-policy-grammar/" + ], + "remediation": "Ensure no managed policies are configured with Effect: Allow, Action: * and Resource: *", + "service": "IAM" + }, + "iam-managed-policy-allows-iam-PassRole": { + "checked_items": 14, + "compliance": null, + "dashboard_name": "Statements", + "description": "Managed Policy Allows \"iam:PassRole\" For All Resources", + "display_path": "iam.policies.id", + "flagged_items": 1, + "items": [ + "iam.policies.ANPAIDI2BQT2LKXZG36TW.PolicyDocument.Statement.0" + ], + "level": "danger", + "path": "iam.policies.id.PolicyDocument.Statement.id", + "rationale": "Using \"*\" for the resource field might grant permissions to more resources than necessary, potentially introducing privilege escalation scenarios.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html" + ], + "remediation": null, + "service": "IAM" + }, + "iam-managed-policy-allows-sts-AssumeRole": { + "checked_items": 14, + "compliance": null, + "dashboard_name": "Statements", + "description": "Managed Policy Allows \"sts:AssumeRole\" For All Resources", + "display_path": "iam.policies.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "iam.policies.id.PolicyDocument.Statement.id", + "rationale": "Using \"*\" for the resource field might grant permissions to more resources than necessary, potentially introducing privilege escalation scenarios.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html" + ], + "remediation": null, + "service": "IAM" + }, + "iam-managed-policy-no-attachments": { + "checked_items": 9, + "compliance": null, + "dashboard_name": "Policies", + "description": "Managed Policy Not Attached to Any Entity", + "display_path": "iam.policies.id", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "iam.policies.id", + "rationale": "Customer Managed policies should be reviewed and deleted if not necessary.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#customer-managed-policies" + ], + "remediation": null, + "service": "IAM" + }, + "iam-password-policy-expiration-threshold": { + "checked_items": 1, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.11", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.11", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.11", + "version": "1.2.0" + } + ], + "dashboard_name": "Password policy", + "description": "Passwords Expire after 90 Days", + "display_path": "iam.password_policy.MaxPasswordAge", + "flagged_items": 1, + "id_suffix": "MaxPasswordAge", + "items": [ + "iam.password_policy.MaxPasswordAge" + ], + "level": "danger", + "path": "iam.password_policy", + "rationale": "Password expiration is disabled, or expiration time is set to a too high value. As a result, compromised credentials could be used by potential attackers for a larger period of time. Periodic password change enforced with an appropriate password expiration policy could help to mitigate this issue.", + "references": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-cis-controls-1.11" + ], + "remediation": "Enable password expiration and set the expiration period to 90 days or less", + "service": "IAM" + }, + "iam-password-policy-minimum-length": { + "checked_items": 1, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.9", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.9", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.9", + "version": "1.2.0" + } + ], + "dashboard_name": "Password policy", + "description": "Minimum Password Length Too Short", + "flagged_items": 1, + "items": [ + "iam.password_policy.MinimumPasswordLength" + ], + "level": "danger", + "path": "iam.password_policy.MinimumPasswordLength", + "rationale": "The password policy did not enforce a minimum of 14 characters. As a result, password complexity requirements were not in line with security best practice.", + "references": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-cis-controls-1.9" + ], + "remediation": "Ensure the password policy is configured to require a minimum length", + "service": "IAM" + }, + "iam-password-policy-no-expiration": { + "checked_items": 1, + "compliance": null, + "dashboard_name": "Password policy", + "description": "Password Expiration Disabled", + "flagged_items": 1, + "items": [ + "iam.password_policy.ExpirePasswords" + ], + "level": "danger", + "path": "iam.password_policy.ExpirePasswords", + "rationale": "Password expiration is disabled. As a result, compromised credentials could be used by potential attackers for a indefinite amount of time. Periodic password change enforced with an appropriate password expiration policy could help to mitigate this issue.", + "references": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-cis-controls-1.11" + ], + "remediation": null, + "service": "IAM" + }, + "iam-password-policy-reuse-enabled": { + "checked_items": 1, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.10", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.10", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.10", + "version": "1.2.0" + } + ], + "dashboard_name": "Password policy", + "description": "Password Policy Allows the Reuse of Passwords", + "flagged_items": 1, + "items": [ + "iam.password_policy.PasswordReusePrevention" + ], + "level": "danger", + "path": "iam.password_policy.PasswordReusePrevention", + "rationale": "The password policy allowed password reuse. As a result, password complexity requirements were not in line with security best practice.", + "references": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-cis-controls-1.10" + ], + "remediation": "Ensure the password policy is configured to prevent password reuse", + "service": "IAM" + }, + "iam-role-with-inline-policies": { + "checked_items": 9, + "compliance": null, + "dashboard_name": "Roles", + "description": "Role with Inline Policies", + "flagged_items": 0, + "id_suffix": "inline_policies", + "items": [], + "level": "warning", + "path": "iam.roles.id", + "rationale": "An inline policy is a policy that's embedded in an IAM identity (a user, group, or role). These policies are harder to audit and manage, and should be deprecated in favor of managed policies.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#best-practice-managed-vs-inline", + "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html" + ], + "remediation": null, + "service": "IAM" + }, + "iam-root-account-no-hardware-mfa": { + "checked_items": 2, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.13", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.14", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.14", + "version": "1.2.0" + } + ], + "dashboard_name": "Accounts", + "description": "Root Account without Hardware MFA", + "flagged_items": 1, + "id_suffix": "mfa_active_hardware", + "items": [ + "iam.credential_reports.68dcc047c3da5bbbc3f3e9d54000b7357f0e507e.mfa_active_hardware" + ], + "level": "danger", + "path": "iam.credential_reports.id", + "rationale": "The root account is the most privileged user in an account. MFA adds an extra layer of protection on top of a user name and password. With MFA enabled, when a user signs in to an AWS website, they're prompted for their user name and password and for an authentication code from their AWS MFA device.", + "references": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-cis-controls-1.13" + ], + "remediation": "Enable MFA for the root account", + "service": "IAM" + }, + "iam-root-account-no-mfa": { + "checked_items": 2, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.13", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.13", + "version": "1.2.0" + } + ], + "dashboard_name": "Accounts", + "description": "Root Account without MFA", + "flagged_items": 1, + "id_suffix": "mfa_active", + "items": [ + "iam.credential_reports.68dcc047c3da5bbbc3f3e9d54000b7357f0e507e.mfa_active" + ], + "level": "danger", + "path": "iam.credential_reports.id", + "rationale": "The root account is the most privileged user in an account. MFA adds an extra layer of protection on top of a user name and password. With MFA enabled, when a user signs in to an AWS website, they're prompted for their user name and password and for an authentication code from their AWS MFA device.", + "references": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-cis-controls-1.13" + ], + "remediation": "Enable MFA for the root account", + "service": "IAM" + }, + "iam-root-account-used-recently": { + "checked_items": 2, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.1", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.1", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.1", + "version": "1.2.0" + } + ], + "dashboard_name": "Root account", + "description": "Root Account Used Recently", + "flagged_items": 0, + "id_suffix": "password_last_used", + "items": [], + "level": "danger", + "path": "iam.credential_reports.id", + "rationale": "The root account is the most privileged user in an account. As a best practice, the root account should only be used when required for root-only tasks.", + "references": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-standards-cis-controls-1.1", + "https://docs.aws.amazon.com/general/latest/gr/aws_tasks-that-require-root.html" + ], + "remediation": "Follow the remediation instructions of the Ensure IAM policies are attached only to groups or roles recommendation", + "service": "IAM" + }, + "iam-root-account-with-active-certs": { + "checked_items": 2, + "compliance": null, + "dashboard_name": "Root account", + "description": "Root Account Has Active X.509 Certs", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "iam.credential_reports.id", + "rationale": "Root account X.509 certificates should be deleted as they may be used to make SOAP-protocol requests in the context of the root account.", + "references": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-standards-cis-controls-1.1" + ], + "remediation": null, + "service": "IAM" + }, + "iam-root-account-with-active-keys": { + "checked_items": 2, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.12", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.12", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.12", + "version": "1.2.0" + } + ], + "dashboard_name": "Root account", + "description": "Root Account Has Active Keys", + "flagged_items": 1, + "items": [ + "iam.credential_reports.68dcc047c3da5bbbc3f3e9d54000b7357f0e507e" + ], + "level": "danger", + "path": "iam.credential_reports.id", + "rationale": "AWS root account access keys should be deleted as they provide unrestricted access to the AWS Account.", + "references": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html#securityhub-standards-cis-controls-1.1" + ], + "remediation": "Delete or disable active root account access keys", + "service": "IAM" + }, + "iam-unused-credentials-not-disabled": { + "checked_items": 2, + "class_suffix": "unused_credentials", + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.3", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.3", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.3", + "version": "1.2.0" + } + ], + "dashboard_name": "Users", + "description": "Credentials Unused for 90 Days or Greater Are Not Disabled", + "flagged_items": 2, + "items": [ + "iam.credential_reports.68dcc047c3da5bbbc3f3e9d54000b7357f0e507e.unused_credentials", + "iam.credential_reports.06f47b690457429238adabc75e53fc0c93bf6c77.unused_credentials" + ], + "level": "danger", + "path": "iam.credential_reports.id", + "rationale": "Disabling or removing unnecessary credentials will reduce the window of opportunity for compromised accounts to be used.", + "references": null, + "remediation": "Ensure that all credentials (including passwords and access keys) have been used and changed in the last 90 days", + "service": "IAM" + }, + "iam-user-no-Active-key-rotation": { + "checked_items": 2, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.4", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.4", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.4", + "version": "1.2.0" + } + ], + "dashboard_name": "Access keys", + "description": "Lack of Key Rotation for (Active) Days", + "display_path": "iam.users.id", + "flagged_items": 2, + "items": [ + "iam.users.AIDAJUK77MEJCW5J3DWZU.AccessKeys.0", + "iam.users.AIDAJUK77MEJCW5J3DWZU.AccessKeys.1" + ], + "level": "danger", + "path": "iam.users.id.AccessKeys.id", + "rationale": "In case of access key compromise, the lack of credential rotation increases the period during which an attacker has access to the AWS account.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#rotate-credentials" + ], + "remediation": "Rotate access keys that have not been changed recently", + "service": "IAM" + }, + "iam-user-no-Inactive-key-rotation": { + "checked_items": 2, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.4", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.4", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.4", + "version": "1.2.0" + } + ], + "dashboard_name": "Access keys", + "description": "Lack of Key Rotation for (Inactive) Days", + "display_path": "iam.users.id", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "iam.users.id.AccessKeys.id", + "rationale": "In case of access key compromise, the lack of credential rotation increases the period during which an attacker has access to the AWS account.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#rotate-credentials" + ], + "remediation": "Rotate access keys that have not been changed recently", + "service": "IAM" + }, + "iam-user-with-inline-policies": { + "checked_items": 1, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.15", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.16", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.16", + "version": "1.2.0" + } + ], + "dashboard_name": "Users", + "description": "User with inline Policies", + "flagged_items": 0, + "id_suffix": "inline_policies", + "items": [], + "level": "warning", + "path": "iam.users.id", + "rationale": "The user was found to be attached to inline policies. This can increase the complexity in user and policy management, and increase the risk of the user being assigned or retaining excessive permissions.", + "references": null, + "remediation": "Ensure IAM policies are only attached to groups or roles", + "service": "IAM" + }, + "iam-user-with-multiple-access-keys": { + "checked_items": 1, + "compliance": null, + "dashboard_name": "Users", + "description": "User with Multiple API Keys", + "flagged_items": 1, + "id_suffix": "multiple_api_keys", + "items": [ + "iam.users.AIDAJUK77MEJCW5J3DWZU.multiple_api_keys" + ], + "level": "warning", + "path": "iam.users.id", + "rationale": "The user was configured to have more than one active API keys associated with the account. Redundant or unused API keys should be removed.", + "references": [ + "https://docs.aws.amazon.com/general/latest/gr/aws-access-keys-best-practices.html" + ], + "remediation": null, + "service": "IAM" + }, + "iam-user-with-password-and-key": { + "checked_items": 1, + "compliance": null, + "dashboard_name": "Users", + "description": "User with Password and Keys Enabled", + "flagged_items": 0, + "id_suffix": "password_and_keys", + "items": [], + "level": "warning", + "path": "iam.users.id", + "rationale": "The user was found to have configured with both password and API keys for authentication. This is considered against security best practice.", + "references": [ + "https://docs.aws.amazon.com/general/latest/gr/aws-access-keys-best-practices.html", + "https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_admin-change-user.html" + ], + "remediation": null, + "service": "IAM" + }, + "iam-user-without-mfa": { + "checked_items": 1, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.2", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.2", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "1.2", + "version": "1.2.0" + } + ], + "dashboard_name": "Users", + "description": "User without MFA", + "flagged_items": 0, + "id_suffix": "mfa_enabled", + "items": [], + "level": "danger", + "path": "iam.users.id", + "rationale": "All IAM users should have MFA. MFA adds an extra layer of protection on top of a user name and password. With MFA enabled, when a user signs in to an AWS website, they're prompted for their user name and password and for an authentication code from their AWS MFA device.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#enable-mfa-for-privileged-users" + ], + "remediation": "Enable MFA for all users in the AWS account", + "service": "IAM" + } + }, + "groups": { + "AGPAIW3P3726RZDVZBZL2": { + "CreateDate": "2013-12-19 09:13:40+00:00", + "Path": "/", + "arn": "arn:aws:iam::430150006394:group/devs", + "id": "AGPAIW3P3726RZDVZBZL2", + "inline_policies": { + "58cd3df92811df89e93933e00cd5a76813cf6258": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "*" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "name": "AdministratorAccess-201312191013" + } + }, + "inline_policies_count": 1, + "name": "devs", + "users": [ + "AIDAJUK77MEJCW5J3DWZU" + ] + } + }, + "groups_count": 1, + "password_policy": { + "AllowUsersToChangePassword": true, + "ExpirePasswords": false, + "MinimumPasswordLength": 6, + "PasswordReusePrevention": false, + "RequireLowercaseCharacters": false, + "RequireNumbers": false, + "RequireSymbols": false, + "RequireUppercaseCharacters": false + }, + "password_policy_count": 0, + "permissions": { + "Action": { + "*": { + "groups": { + "Allow": { + "AGPAIW3P3726RZDVZBZL2": { + "Resource": { + "*": { + "inline_policies": { + "58cd3df92811df89e93933e00cd5a76813cf6258": { + "condition": null + } + } + } + } + } + } + } + }, + "a4b:getDevice": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "a4b:getProfile": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "a4b:getRoom": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "a4b:getRoomSkillParameter": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "a4b:getSkillGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "a4b:searchDevices": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "a4b:searchProfiles": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "a4b:searchRooms": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "a4b:searchSkillGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "access-analyzer:getFinding": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "access-analyzer:listAnalyzers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "access-analyzer:listArchiveRules": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "access-analyzer:listFindings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "acm-pca:describeCertificateAuthority": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "acm-pca:describeCertificateAuthorityAuditReport": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "acm-pca:getCertificate": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "acm-pca:getCertificateAuthorityCertificate": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "acm-pca:getCertificateAuthorityCsr": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "acm-pca:listCertificateAuthorities": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "acm-pca:listTags": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "acm:describeCertificate": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "acm:getCertificate": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "acm:listCertificates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "acm:listTagsForCertificate": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "airflow:getEnvironment": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "airflow:listEnvironments": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "airflow:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "amplify:getApp": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "amplify:getBranch": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "amplify:getDomainAssociation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "amplify:getJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "amplify:getWebhook": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "amplify:listApps": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "amplify:listWebhooks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "apigateway:GET": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "arn:aws:apigateway:*::/account": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/apis": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/apis/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/apis/*/authorizers": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/apis/*/authorizers/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/apis/*/deployments": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/apis/*/deployments/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/apis/*/integrations": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/apis/*/integrations/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/apis/*/integrations/*/integrationresponses": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/apis/*/integrations/*/integrationresponses/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/apis/*/models": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/apis/*/models/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/apis/*/routes": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/apis/*/routes/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/apis/*/routes/*/routeresponses": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/apis/*/routes/*/routeresponses/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/apis/*/stages": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/apis/*/stages/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/clientcertificates": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/clientcertificates/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/domainnames": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/domainnames/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/domainnames/*/apimappings": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/domainnames/*/apimappings/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/domainnames/*/basepathmappings": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/domainnames/*/basepathmappings/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/restapis": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/restapis/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/restapis/*/authorizers": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/restapis/*/authorizers/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/restapis/*/deployments": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/restapis/*/deployments/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/restapis/*/models": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/restapis/*/models/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/restapis/*/models/*/default_template": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/restapis/*/resources": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/restapis/*/resources/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/restapis/*/resources/*/methods/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/integration": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/integration/responses/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/responses/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/restapis/*/stages": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/restapis/*/stages/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "arn:aws:apigateway:*::/restapis/*/stages/*/sdks/*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appflow:describeConnectorEntity": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appflow:describeConnectorProfiles": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appflow:describeFlow": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appflow:listFlows": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "application-autoscaling:DeleteScalingPolicy": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "application-autoscaling:DeregisterScalableTarget": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "application-autoscaling:Describe*": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "application-autoscaling:PutScalingPolicy": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "application-autoscaling:RegisterScalableTarget": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "application-autoscaling:describeScalableTargets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "application-autoscaling:describeScalingActivities": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "application-autoscaling:describeScalingPolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "application-autoscaling:describeScheduledActions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "applicationinsights:describeComponentConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "applicationinsights:describeComponentConfigurationRecommendation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "applicationinsights:listApplications": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "applicationinsights:listComponents": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "applicationinsights:listConfigurationHistory": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "applicationinsights:listLogPatternSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "applicationinsights:listLogPatterns": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appmesh:describeGatewayRoute": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appmesh:describeMesh": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appmesh:describeRoute": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appmesh:describeVirtualGateway": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appmesh:describeVirtualNode": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appmesh:describeVirtualRouter": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appmesh:describeVirtualService": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appmesh:listGatewayRoutes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appmesh:listMeshes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appmesh:listRoutes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appmesh:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appmesh:listVirtualGateways": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appmesh:listVirtualNodes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appmesh:listVirtualRouters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appmesh:listVirtualServices": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "apprunner:describeAutoScalingConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "apprunner:describeCustomDomains": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "apprunner:describeOperation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "apprunner:describeService": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "apprunner:listAutoScalingConfigurations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "apprunner:listConnections": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "apprunner:listOperations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "apprunner:listServices": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "apprunner:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appstream:describeDirectoryConfigs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appstream:describeFleets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appstream:describeImageBuilders": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appstream:describeImages": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appstream:describeSessions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appstream:describeStacks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appstream:listAssociatedFleets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appstream:listAssociatedStacks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appstream:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appsync:getFunction": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appsync:getGraphqlApi": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appsync:getIntrospectionSchema": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appsync:getResolver": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appsync:getSchemaCreationStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appsync:getType": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appsync:listDataSources": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appsync:listFunctions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appsync:listGraphqlApis": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appsync:listResolvers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "appsync:listTypes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "athena:batchGetNamedQuery": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "athena:batchGetQueryExecution": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "athena:getNamedQuery": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "athena:getQueryExecution": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "athena:getWorkGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "athena:listNamedQueries": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "athena:listQueryExecutions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "athena:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "athena:listWorkGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "auditmanager:getAccountStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "auditmanager:getDelegations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "auditmanager:listAssessmentFrameworks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "auditmanager:listAssessmentReports": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "auditmanager:listAssessments": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "auditmanager:listControls": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "auditmanager:listKeywordsForDataSource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "auditmanager:listNotifications": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling-plans:describeScalingPlanResources": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling-plans:describeScalingPlans": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling-plans:getScalingPlanResourceForecastData": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:DescribeAccountLimits": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:DescribeAutoScalingGroups": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:DescribeLaunchConfigurations": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:describeAccountLimits": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:describeAdjustmentTypes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:describeAutoScalingGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:describeAutoScalingInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:describeAutoScalingNotificationTypes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:describeInstanceRefreshes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:describeLaunchConfigurations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:describeLifecycleHookTypes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:describeLifecycleHooks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:describeLoadBalancerTargetGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:describeLoadBalancers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:describeMetricCollectionTypes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:describeNotificationConfigurations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:describePolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:describeScalingActivities": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:describeScalingProcessTypes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:describeScheduledActions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:describeTags": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "autoscaling:describeTerminationPolicyTypes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:describeBackupJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:describeBackupVault": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:describeProtectedResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:describeRecoveryPoint": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:describeRestoreJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:getBackupPlan": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:getBackupPlanFromJSON": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:getBackupPlanFromTemplate": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:getBackupSelection": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:getBackupVaultAccessPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:getBackupVaultNotifications": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:getRecoveryPointRestoreMetadata": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:getSupportedResourceTypes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:listBackupJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:listBackupPlanTemplates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:listBackupPlanVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:listBackupPlans": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:listBackupSelections": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:listBackupVaults": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:listProtectedResources": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:listRecoveryPointsByBackupVault": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:listRecoveryPointsByResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:listRestoreJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "backup:listTags": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "batch:describeComputeEnvironments": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "batch:describeJobDefinitions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "batch:describeJobQueues": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "batch:describeJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "batch:listJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "braket:getDevice": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "braket:getQuantumTask": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "braket:searchDevices": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "braket:searchQuantumTasks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "budgets:viewBudget": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ce:GetReservationPurchaseRecommendation": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "ce:GetSavingsPlansPurchaseRecommendation": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "ce:getCostAndUsage": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ce:getCostAndUsageWithResources": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ce:getCostForecast": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ce:getDimensionValues": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ce:getReservationCoverage": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ce:getReservationPurchaseRecommendation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ce:getReservationUtilization": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ce:getRightsizingRecommendation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ce:getSavingsPlansCoverage": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ce:getSavingsPlansPurchaseRecommendation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ce:getSavingsPlansUtilization": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ce:getSavingsPlansUtilizationDetails": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ce:getTags": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloud9:describeEnvironmentMemberships": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloud9:describeEnvironments": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloud9:listEnvironments": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "clouddirectory:getDirectory": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "clouddirectory:listDirectories": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:DescribeAccountLimits": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:DescribeStacks": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:ListStacks": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:describeAccountLimits": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:describeChangeSet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:describeStackEvents": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:describeStackInstance": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:describeStackResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:describeStackResources": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:describeStackSet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:describeStackSetOperation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:describeStacks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:estimateTemplateCost": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:getStackPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:getTemplate": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:getTemplateSummary": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:listChangeSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:listExports": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:listImports": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:listStackInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:listStackResources": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:listStackSetOperationResults": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:listStackSetOperations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:listStackSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudformation:listStacks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudfront:ListDistributions": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudfront:getCloudFrontOriginAccessIdentity": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudfront:getCloudFrontOriginAccessIdentityConfig": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudfront:getDistribution": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudfront:getDistributionConfig": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudfront:getInvalidation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudfront:getStreamingDistribution": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudfront:getStreamingDistributionConfig": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudfront:listCloudFrontOriginAccessIdentities": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudfront:listDistributions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudfront:listDistributionsByWebACLId": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudfront:listInvalidations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudfront:listStreamingDistributions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudhsm:describeBackups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudhsm:describeClusters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudsearch:describeAnalysisSchemes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudsearch:describeAvailabilityOptions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudsearch:describeDomains": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudsearch:describeExpressions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudsearch:describeIndexFields": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudsearch:describeScalingParameters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudsearch:describeServiceAccessPolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudsearch:describeSuggesters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudsearch:listDomainNames": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudtrail:DescribeTrails": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + }, + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudtrail:GetEventSelectors": { + "roles": { + "Allow": { + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudtrail:GetTrailStatus": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + }, + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudtrail:describeTrails": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudtrail:getEventSelectors": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudtrail:getInsightSelectors": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudtrail:getTrail": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudtrail:getTrailStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudtrail:listPublicKeys": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudtrail:listTags": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudtrail:listTrails": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudtrail:lookupEvents": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudwatch:*": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudwatch:DeleteAlarms": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudwatch:DescribeAlarms": { + "roles": { + "Allow": { + "AROAIH747R37LKSEOZ2MA": { + "Resource": { + "*": { + "policies": { + "ANPAJSVXG6QHPE6VHDZ4Q": { + "condition": null + } + } + } + } + }, + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + }, + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudwatch:DescribeAlarmsForMetric": { + "roles": { + "Allow": { + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudwatch:GetMetricStatistics": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudwatch:PutMetricAlarm": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudwatch:describeAlarmHistory": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudwatch:describeAlarms": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudwatch:describeAlarmsForMetric": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudwatch:describeAnomalyDetectors": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudwatch:describeInsightRules": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudwatch:getDashboard": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudwatch:getInsightRuleReport": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudwatch:getMetricData": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudwatch:getMetricStatistics": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudwatch:listDashboards": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cloudwatch:listMetrics": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codeartifact:describeDomain": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codeartifact:describePackageVersion": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codeartifact:describeRepository": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codeartifact:getDomainPermissionsPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codeartifact:getRepositoryEndPoint": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codeartifact:getRepositoryPermissionsPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codeartifact:listDomains": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codeartifact:listPackageVersionAssets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codeartifact:listPackageVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codeartifact:listPackages": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codeartifact:listRepositories": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codeartifact:listRepositoriesInDomain": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codebuild:batchGetBuildBatches": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codebuild:batchGetBuilds": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codebuild:batchGetProjects": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codebuild:listBuildBatches": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codebuild:listBuildBatchesForProject": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codebuild:listBuilds": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codebuild:listBuildsForProject": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codebuild:listCuratedEnvironmentImages": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codebuild:listProjects": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codebuild:listSourceCredentials": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codecommit:batchGetRepositories": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codecommit:getBranch": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codecommit:getRepository": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codecommit:getRepositoryTriggers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codecommit:listBranches": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codecommit:listRepositories": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:batchGetApplicationRevisions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:batchGetApplications": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:batchGetDeploymentGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:batchGetDeploymentInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:batchGetDeploymentTargets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:batchGetDeployments": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:batchGetOnPremisesInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:getApplication": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:getApplicationRevision": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:getDeployment": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:getDeploymentConfig": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:getDeploymentGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:getDeploymentInstance": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:getDeploymentTarget": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:getOnPremisesInstance": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:listApplicationRevisions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:listApplications": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:listDeploymentConfigs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:listDeploymentGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:listDeploymentInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:listDeploymentTargets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:listDeployments": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:listGitHubAccountTokenNames": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codedeploy:listOnPremisesInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codepipeline:getJobDetails": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codepipeline:getPipeline": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codepipeline:getPipelineExecution": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codepipeline:getPipelineState": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codepipeline:listActionExecutions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codepipeline:listActionTypes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codepipeline:listPipelineExecutions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codepipeline:listPipelines": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codepipeline:listWebhooks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codestar:describeProject": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codestar:listProjects": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codestar:listResources": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codestar:listTeamMembers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "codestar:listUserProfiles": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-identity:describeIdentityPool": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-identity:getIdentityPoolRoles": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-identity:listIdentities": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-identity:listIdentityPools": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-idp:adminGetUser": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-idp:describeIdentityProvider": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-idp:describeResourceServer": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-idp:describeRiskConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-idp:describeUserImportJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-idp:describeUserPool": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-idp:describeUserPoolClient": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-idp:describeUserPoolDomain": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-idp:getGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-idp:getUICustomization": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-idp:getUser": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-idp:getUserPoolMfaConfig": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-idp:listGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-idp:listIdentityProviders": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-idp:listResourceServers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-idp:listUserImportJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-idp:listUserPoolClients": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-idp:listUserPools": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-sync:describeDataset": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-sync:describeIdentityPoolUsage": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-sync:describeIdentityUsage": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-sync:getCognitoEvents": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-sync:getIdentityPoolConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-sync:listDatasets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "cognito-sync:listIdentityPoolUsage": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "compute-optimizer:getAutoScalingGroupRecommendations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "compute-optimizer:getEBSVolumeRecommendations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "compute-optimizer:getEC2InstanceRecommendations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "compute-optimizer:getEC2RecommendationProjectedMetrics": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "compute-optimizer:getEnrollmentStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "compute-optimizer:getRecommendationSummaries": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "config:BatchGetResourceConfig": { + "roles": { + "Allow": { + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + } + } + } + }, + "config:DeleteConfigRule": { + "roles": { + "Allow": { + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "arn:aws:config:*:*:config-rule/aws-service-rule/*securityhub*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + } + } + } + }, + "config:DescribeConfigRuleEvaluationStatus": { + "roles": { + "Allow": { + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "arn:aws:config:*:*:config-rule/aws-service-rule/*securityhub*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + } + } + } + }, + "config:DescribeConfigRules": { + "roles": { + "Allow": { + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + } + } + } + }, + "config:DescribeConfigurationRecorderStatus": { + "roles": { + "Allow": { + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + } + } + } + }, + "config:DescribeConfigurationRecorders": { + "roles": { + "Allow": { + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + } + } + } + }, + "config:GetComplianceDetailsByConfigRule": { + "roles": { + "Allow": { + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "arn:aws:config:*:*:config-rule/aws-service-rule/*securityhub*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + } + } + } + }, + "config:PutConfigRule": { + "roles": { + "Allow": { + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "arn:aws:config:*:*:config-rule/aws-service-rule/*securityhub*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + } + } + } + }, + "config:PutEvaluations": { + "roles": { + "Allow": { + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + } + } + } + }, + "config:SelectResourceConfig": { + "roles": { + "Allow": { + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + } + } + } + }, + "config:describeConfigRuleEvaluationStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "config:describeConfigRules": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "config:describeConfigurationRecorderStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "config:describeConfigurationRecorders": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "config:describeDeliveryChannelStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "config:describeDeliveryChannels": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "config:getResourceConfigHistory": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "config:listDiscoveredResources": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "connect:describeUser": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "connect:getCurrentMetricData": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "connect:getMetricData": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "connect:listRoutingProfiles": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "connect:listSecurityProfiles": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "connect:listUsers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "controltower:describeAccountFactoryConfig": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "controltower:describeCoreService": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "controltower:describeGuardrail": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "controltower:describeGuardrailForTarget": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "controltower:describeManagedAccount": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "controltower:describeSingleSignOn": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "controltower:getAvailableUpdates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "controltower:getHomeRegion": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "controltower:getLandingZoneStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "controltower:listDirectoryGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "controltower:listGuardrailViolations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "controltower:listGuardrailsForTarget": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "controltower:listManagedAccounts": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "controltower:listManagedAccountsForGuardrail": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "controltower:listManagedAccountsForParent": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "controltower:listManagedOrganizationalUnits": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "controltower:listManagedOrganizationalUnitsForGuardrail": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "databrew:describeDataset": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "databrew:describeJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "databrew:describeProject": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "databrew:describeRecipe": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "databrew:listDatasets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "databrew:listJobRuns": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "databrew:listJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "databrew:listProjects": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "databrew:listRecipeVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "databrew:listRecipes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "databrew:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "datapipeline:describeObjects": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "datapipeline:describePipelines": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "datapipeline:getPipelineDefinition": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "datapipeline:listPipelines": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "datapipeline:queryObjects": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "datasync:describeAgent": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "datasync:describeLocationEfs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "datasync:describeLocationFsxWindows": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "datasync:describeLocationNfs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "datasync:describeLocationObjectStorage": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "datasync:describeLocationS3": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "datasync:describeLocationSmb": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "datasync:describeTask": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "datasync:describeTaskExecution": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "datasync:listAgents": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "datasync:listLocations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "datasync:listTaskExecutions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "datasync:listTasks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dax:describeClusters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dax:describeDefaultParameters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dax:describeEvents": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dax:describeParameterGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dax:describeParameters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dax:describeSubnetGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "detective:getMembers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "detective:listGraphs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "detective:listInvitations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "detective:listMembers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:getAccountSettings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:getDevice": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:getDevicePool": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:getDevicePoolCompatibility": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:getJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:getProject": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:getRemoteAccessSession": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:getRun": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:getSuite": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:getTest": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:getTestGridProject": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:getTestGridSession": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:getUpload": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:listArtifacts": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:listDevicePools": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:listDevices": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:listJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:listProjects": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:listRemoteAccessSessions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:listRuns": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:listSamples": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:listSuites": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:listTestGridProjects": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:listTestGridSessionActions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:listTestGridSessionArtifacts": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:listTestGridSessions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:listTests": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:listUniqueProblems": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "devicefarm:listUploads": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "directconnect:describeConnections": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "directconnect:describeConnectionsOnInterconnect": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "directconnect:describeInterconnects": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "directconnect:describeLocations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "directconnect:describeVirtualGateways": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "directconnect:describeVirtualInterfaces": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dlm:getLifecyclePolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dlm:getLifecyclePolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dms:describeAccountAttributes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dms:describeConnections": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dms:describeEndpointTypes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dms:describeEndpoints": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dms:describeOrderableReplicationInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dms:describeRefreshSchemasStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dms:describeReplicationInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dms:describeReplicationSubnetGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ds:describeConditionalForwarders": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ds:describeDirectories": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ds:describeEventTopics": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ds:describeSnapshots": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ds:describeTrusts": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ds:getDirectoryLimits": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ds:getSnapshotLimits": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ds:listIpRoutes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ds:listSchemaExtensions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ds:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dynamodb:*": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "dynamodb:DescribeLimits": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "dynamodb:DescribeTable": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "dynamodb:ListTables": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "dynamodb:describeBackup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dynamodb:describeContinuousBackups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dynamodb:describeGlobalTable": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dynamodb:describeLimits": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dynamodb:describeStream": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dynamodb:describeTable": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dynamodb:describeTimeToLive": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dynamodb:listBackups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dynamodb:listGlobalTables": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dynamodb:listStreams": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dynamodb:listTables": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "dynamodb:listTagsOfResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:AuthorizeSecurityGroupEgress": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:AuthorizeSecurityGroupIngress": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:CancelSpotInstanceRequests": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + }, + "AROAJ2LRZXYT2USPF2ZTY": { + "Resource": { + "*": { + "policies": { + "ANPAI4YEZURRMKACW56EA": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:CreateFleet": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:CreateLaunchTemplate": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:CreateNetworkInterface": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:CreateSecurityGroup": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:CreateTags": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DeleteLaunchTemplate": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + }, + "AROAJ2LRZXYT2USPF2ZTY": { + "Resource": { + "*": { + "policies": { + "ANPAI4YEZURRMKACW56EA": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DeleteNetworkInterface": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + }, + "AROAJ2LRZXYT2USPF2ZTY": { + "Resource": { + "*": { + "policies": { + "ANPAI4YEZURRMKACW56EA": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DeletePlacementGroup": { + "roles": { + "Allow": { + "AROAJ2LRZXYT2USPF2ZTY": { + "Resource": { + "*": { + "policies": { + "ANPAI4YEZURRMKACW56EA": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DeleteSecurityGroup": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DeleteTags": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DeleteVolume": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + }, + "AROAJ2LRZXYT2USPF2ZTY": { + "Resource": { + "*": { + "policies": { + "ANPAI4YEZURRMKACW56EA": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:Describe*": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeAccountAttributes": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeAddresses": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + }, + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeAvailabilityZones": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeByoipCidrs": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeDhcpOptions": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeImages": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + }, + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeInstanceAttribute": { + "roles": { + "Allow": { + "AROAJ2LRZXYT2USPF2ZTY": { + "Resource": { + "*": { + "policies": { + "ANPAI4YEZURRMKACW56EA": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeInstanceStatus": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeInstances": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + }, + "AROAJ2LRZXYT2USPF2ZTY": { + "Resource": { + "*": { + "policies": { + "ANPAI4YEZURRMKACW56EA": { + "condition": null + } + } + } + } + }, + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeInternetGateways": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeKeyPairs": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeLaunchTemplateVersions": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeLaunchTemplates": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + }, + "AROAJ2LRZXYT2USPF2ZTY": { + "Resource": { + "*": { + "policies": { + "ANPAI4YEZURRMKACW56EA": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeNetworkAcls": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeNetworkInterfaces": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribePlacementGroups": { + "roles": { + "Allow": { + "AROAJ2LRZXYT2USPF2ZTY": { + "Resource": { + "*": { + "policies": { + "ANPAI4YEZURRMKACW56EA": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribePrefixLists": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeReservedInstances": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeReservedInstancesOfferings": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeRouteTables": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeSecurityGroups": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + }, + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeSnapshots": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeSpotInstanceRequests": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + }, + "AROAJ2LRZXYT2USPF2ZTY": { + "Resource": { + "*": { + "policies": { + "ANPAI4YEZURRMKACW56EA": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeSpotPriceHistory": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeSubnets": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeTags": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeVolumeStatus": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + }, + "AROAJ2LRZXYT2USPF2ZTY": { + "Resource": { + "*": { + "policies": { + "ANPAI4YEZURRMKACW56EA": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeVolumes": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + }, + "AROAJ2LRZXYT2USPF2ZTY": { + "Resource": { + "*": { + "policies": { + "ANPAI4YEZURRMKACW56EA": { + "condition": null + } + } + } + } + }, + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeVpcAttribute": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeVpcEndpointServices": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeVpcEndpoints": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + }, + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeVpcs": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + }, + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + }, + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeVpnConnections": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DescribeVpnGateways": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DetachNetworkInterface": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:DetachVolume": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + }, + "AROAJ2LRZXYT2USPF2ZTY": { + "Resource": { + "*": { + "policies": { + "ANPAI4YEZURRMKACW56EA": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:ModifyImageAttribute": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:ModifyInstanceAttribute": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + }, + "AROAJ2LRZXYT2USPF2ZTY": { + "Resource": { + "*": { + "policies": { + "ANPAI4YEZURRMKACW56EA": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:RequestSpotInstances": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:RevokeSecurityGroupEgress": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:RunInstances": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:TerminateInstances": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + }, + "AROAJ2LRZXYT2USPF2ZTY": { + "Resource": { + "*": { + "policies": { + "ANPAI4YEZURRMKACW56EA": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:acceptReservedInstancesExchangeQuote": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:cancelReservedInstancesListing": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:createReservedInstancesListing": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeAccountAttributes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeAddresses": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeAvailabilityZones": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeBundleTasks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeByoipCidrs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeCapacityReservations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeClassicLinkInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeClientVpnAuthorizationRules": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeClientVpnConnections": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeClientVpnEndpoints": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeClientVpnRoutes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeClientVpnTargetNetworks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeCoipPools": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeConversionTasks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeCustomerGateways": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeDhcpOptions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeElasticGpus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeExportImageTasks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeExportTasks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeFastSnapshotRestores": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeFleetHistory": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeFleetInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeFleets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeFlowLogs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeHostReservationOfferings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeHostReservations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeHosts": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeIdFormat": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeIdentityIdFormat": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeImageAttribute": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeImages": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeImportImageTasks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeImportSnapshotTasks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeInstanceAttribute": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeInstanceStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeInternetGateways": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeKeyPairs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeLaunchTemplateVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeLaunchTemplates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeLocalGatewayRouteTableVirtualInterfaceGroupAssociations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeLocalGatewayRouteTableVpcAssociations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeLocalGatewayRouteTables": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeLocalGatewayVirtualInterfaceGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeLocalGatewayVirtualInterfaces": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeLocalGateways": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeMovingAddresses": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeNatGateways": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeNetworkAcls": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeNetworkInterfaceAttribute": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeNetworkInterfaces": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describePlacementGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describePrefixLists": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describePublicIpv4Pools": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeRegions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeReservedInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeReservedInstancesListings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeReservedInstancesModifications": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeReservedInstancesOfferings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeRouteTables": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeScheduledInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeSecurityGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeSnapshotAttribute": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeSnapshots": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeSpotDatafeedSubscription": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeSpotFleetInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeSpotFleetRequestHistory": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeSpotFleetRequests": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeSpotInstanceRequests": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeSpotPriceHistory": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeSubnets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeTags": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeTrafficMirrorFilters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeTrafficMirrorSessions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeTrafficMirrorTargets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeTransitGatewayAttachments": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeTransitGatewayRouteTables": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeTransitGatewayVpcAttachments": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeTransitGateways": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeVolumeAttribute": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeVolumeStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeVolumes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeVolumesModifications": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeVpcAttribute": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeVpcClassicLink": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeVpcClassicLinkDnsSupport": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeVpcEndpointConnectionNotifications": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeVpcEndpointConnections": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeVpcEndpointServiceConfigurations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeVpcEndpointServicePermissions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeVpcEndpointServices": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeVpcEndpoints": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeVpcPeeringConnections": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeVpcs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeVpnConnections": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:describeVpnGateways": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:getCoipPoolUsage": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:getConsoleScreenshot": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:getReservedInstancesExchangeQuote": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:getTransitGatewayAttachmentPropagations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:getTransitGatewayRouteTableAssociations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:getTransitGatewayRouteTablePropagations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:modifyReservedInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:purchaseReservedInstancesOffering": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ec2:searchLocalGatewayRoutes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecr-public:describeImageTags": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecr-public:describeImages": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecr-public:describeRegistries": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecr-public:describeRepositories": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecr-public:getRegistryCatalogData": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecr-public:getRepositoryCatalogData": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecr-public:getRepositoryPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecr-public:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecr:batchCheckLayerAvailability": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecr:describeImageScanFindings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecr:describeImages": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecr:describeRegistry": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecr:describeRepositories": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecr:getLifecyclePolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecr:getRegistryPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecr:getRepositoryPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecr:listImages": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecr:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecs:describeCapacityProviders": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecs:describeClusters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecs:describeContainerInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecs:describeServices": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecs:describeTaskDefinition": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecs:describeTaskSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecs:describeTasks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecs:listAccountSettings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecs:listAttributes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecs:listClusters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecs:listContainerInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecs:listServices": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecs:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecs:listTaskDefinitionFamilies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecs:listTaskDefinitions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ecs:listTasks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "eks:describeCluster": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "eks:describeFargateProfile": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "eks:describeNodegroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "eks:describeUpdate": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "eks:listClusters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "eks:listFargateProfiles": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "eks:listNodegroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "eks:listUpdates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticache:describeCacheClusters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticache:describeCacheEngineVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticache:describeCacheParameterGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticache:describeCacheParameters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticache:describeCacheSecurityGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticache:describeCacheSubnetGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticache:describeEngineDefaultParameters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticache:describeEvents": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticache:describeReplicationGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticache:describeReservedCacheNodes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticache:describeReservedCacheNodesOfferings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticache:describeSnapshots": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticache:listAllowedNodeTypeModifications": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticache:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticbeanstalk:checkDNSAvailability": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticbeanstalk:describeApplicationVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticbeanstalk:describeApplications": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticbeanstalk:describeConfigurationOptions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticbeanstalk:describeConfigurationSettings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticbeanstalk:describeEnvironmentHealth": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticbeanstalk:describeEnvironmentManagedActionHistory": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticbeanstalk:describeEnvironmentManagedActions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticbeanstalk:describeEnvironmentResources": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticbeanstalk:describeEnvironments": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticbeanstalk:describeEvents": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticbeanstalk:describeInstancesHealth": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticbeanstalk:describePlatformVersion": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticbeanstalk:listAvailableSolutionStacks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticbeanstalk:listPlatformVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticbeanstalk:validateConfigurationSettings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticfilesystem:describeAccessPoints": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticfilesystem:describeFileSystemPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticfilesystem:describeFileSystems": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticfilesystem:describeLifecycleConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticfilesystem:describeMountTargetSecurityGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticfilesystem:describeMountTargets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticfilesystem:describeTags": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticfilesystem:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticloadbalancing:DescribeAccountLimits": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticloadbalancing:DescribeInstanceHealth": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticloadbalancing:DescribeLoadBalancerAttributes": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticloadbalancing:DescribeLoadBalancerPolicies": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticloadbalancing:DescribeLoadBalancerPolicyTypes": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticloadbalancing:DescribeLoadBalancers": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticloadbalancing:DescribeTargetGroups": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticloadbalancing:describeInstanceHealth": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticloadbalancing:describeListenerCertificates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticloadbalancing:describeListeners": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticloadbalancing:describeLoadBalancerAttributes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticloadbalancing:describeLoadBalancerPolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticloadbalancing:describeLoadBalancerPolicyTypes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticloadbalancing:describeLoadBalancers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticloadbalancing:describeRules": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticloadbalancing:describeSSLPolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticloadbalancing:describeTags": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticloadbalancing:describeTargetGroupAttributes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticloadbalancing:describeTargetGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticloadbalancing:describeTargetHealth": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticmapreduce:Describe*": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticmapreduce:ListBootstrapActions": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticmapreduce:ListClusters": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticmapreduce:ListInstanceGroups": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + }, + "AROAIH747R37LKSEOZ2MA": { + "Resource": { + "*": { + "policies": { + "ANPAJSVXG6QHPE6VHDZ4Q": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticmapreduce:ListInstances": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticmapreduce:ListSteps": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticmapreduce:ModifyInstanceGroups": { + "roles": { + "Allow": { + "AROAIH747R37LKSEOZ2MA": { + "Resource": { + "*": { + "policies": { + "ANPAJSVXG6QHPE6VHDZ4Q": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticmapreduce:describeCluster": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticmapreduce:describeSecurityConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticmapreduce:describeStep": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticmapreduce:listBootstrapActions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticmapreduce:listClusters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticmapreduce:listInstanceGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticmapreduce:listInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticmapreduce:listSecurityConfigurations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elasticmapreduce:listSteps": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elastictranscoder:listJobsByPipeline": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elastictranscoder:listJobsByStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elastictranscoder:listPipelines": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elastictranscoder:listPresets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elastictranscoder:readPipeline": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "elastictranscoder:readPreset": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "es:describeElasticsearchDomain": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "es:describeElasticsearchDomainConfig": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "es:describeElasticsearchDomains": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "es:listDomainNames": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "es:listTags": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "events:describeApiDestination": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "events:describeEventBus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "events:describeEventSource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "events:describePartnerEventSource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "events:describeRule": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "events:listApiDestinations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "events:listConnections": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "events:listEventBuses": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "events:listEventSources": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "events:listPartnerEventSourceAccounts": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "events:listPartnerEventSources": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "events:listRuleNamesByTarget": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "events:listRules": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "events:listTargetsByRule": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "events:testEventPattern": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "firehose:describeDeliveryStream": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "firehose:listDeliveryStreams": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "fms:getAdminAccount": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "fms:getComplianceDetail": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "fms:getNotificationChannel": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "fms:getPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "fms:getProtectionStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "fms:listComplianceStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "fms:listMemberAccounts": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "fms:listPolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "forecast:describeDataset": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "forecast:describeDatasetGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "forecast:describeDatasetImportJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "forecast:describeForecast": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "forecast:describeForecastExportJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "forecast:describePredictor": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "forecast:getAccuracyMetrics": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "forecast:listDatasetGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "forecast:listDatasetImportJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "forecast:listDatasets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "forecast:listForecastExportJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "forecast:listForecasts": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "forecast:listPredictors": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "fsx:describeBackups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "fsx:describeDataRepositoryTasks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "fsx:describeFileSystems": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "fsx:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glacier:describeJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glacier:describeVault": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glacier:getDataRetrievalPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glacier:getVaultAccessPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glacier:getVaultLock": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glacier:getVaultNotifications": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glacier:listJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glacier:listTagsForVault": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glacier:listVaults": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "globalaccelerator:describeAccelerator": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "globalaccelerator:describeAcceleratorAttributes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "globalaccelerator:describeEndpointGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "globalaccelerator:describeListener": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "globalaccelerator:listAccelerators": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "globalaccelerator:listEndpointGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "globalaccelerator:listListeners": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:BatchCreatePartition": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:BatchDeletePartition": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:BatchGetPartition": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:CreateDatabase": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:CreatePartition": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:CreateTable": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:CreateUserDefinedFunction": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:DeleteDatabase": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:DeletePartition": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:DeleteTable": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:DeleteUserDefinedFunction": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:GetDatabase": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:GetDatabases": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:GetPartition": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:GetPartitions": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:GetTable": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:GetTableVersions": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:GetTables": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:GetUserDefinedFunction": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:GetUserDefinedFunctions": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:UpdateDatabase": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:UpdatePartition": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:UpdateTable": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:UpdateUserDefinedFunction": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:batchGetPartition": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:checkSchemaVersionValidity": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getCatalogImportStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getClassifier": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getClassifiers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getCrawler": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getCrawlerMetrics": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getCrawlers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getDatabase": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getDatabases": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getDataflowGraph": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getDevEndpoint": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getDevEndpoints": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getJobRun": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getJobRuns": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getMapping": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getPartition": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getPartitions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getRegistry": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getSchema": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getSchemaByDefinition": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getSchemaVersion": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getSchemaVersionsDiff": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getTable": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getTableVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getTables": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getTrigger": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getTriggers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getUserDefinedFunction": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:getUserDefinedFunctions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:listRegistries": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:listSchemaVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:listSchemas": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "glue:querySchemaVersionMetadata": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:getConnectivityInfo": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:getCoreDefinition": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:getCoreDefinitionVersion": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:getDeploymentStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:getDeviceDefinition": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:getDeviceDefinitionVersion": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:getFunctionDefinition": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:getFunctionDefinitionVersion": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:getGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:getGroupCertificateAuthority": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:getGroupVersion": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:getLoggerDefinition": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:getLoggerDefinitionVersion": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:getResourceDefinitionVersion": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:getServiceRoleForAccount": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:getSubscriptionDefinition": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:getSubscriptionDefinitionVersion": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:listCoreDefinitionVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:listCoreDefinitions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:listDeployments": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:listDeviceDefinitionVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:listDeviceDefinitions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:listFunctionDefinitionVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:listFunctionDefinitions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:listGroupVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:listGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:listLoggerDefinitionVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:listLoggerDefinitions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:listResourceDefinitionVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:listResourceDefinitions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:listSubscriptionDefinitionVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "greengrass:listSubscriptionDefinitions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "guardduty:getDetector": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "guardduty:getFindings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "guardduty:getFindingsStatistics": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "guardduty:getIPSet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "guardduty:getInvitationsCount": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "guardduty:getMasterAccount": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "guardduty:getMembers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "guardduty:getThreatIntelSet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "guardduty:listDetectors": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "guardduty:listFindings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "guardduty:listIPSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "guardduty:listInvitations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "guardduty:listMembers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "guardduty:listThreatIntelSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "health:describeAffectedAccountsForOrganization": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "health:describeAffectedEntities": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "health:describeAffectedEntitiesForOrganization": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "health:describeEntityAggregates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "health:describeEventAggregates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "health:describeEventDetails": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "health:describeEventDetailsForOrganization": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "health:describeEventTypes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "health:describeEvents": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "health:describeEventsForOrganization": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "health:describeHealthServiceStatusForOrganization": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:CreateServiceLinkedRole": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "arn:aws:iam::*:role/aws-service-role/spot.amazonaws.com/AWSServiceRoleForEC2Spot*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": { + "StringLike": { + "iam:AWSServiceName": "spot.amazonaws.com" + } + } + } + } + } + } + } + } + } + }, + "iam:DeleteRole": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "arn:aws:iam::*:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:GenerateCredentialReport": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + }, + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:GetAccountPasswordPolicy": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:GetAccountSummary": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:GetCredentialReport": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + }, + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:GetRole": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + }, + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:GetRolePolicy": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:GetServerCertificate": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:ListInstanceProfiles": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:ListRolePolicies": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:ListRoles": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:ListServerCertificates": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:PassRole": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:getAccessKeyLastUsed": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:getAccountAuthorizationDetails": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:getAccountPasswordPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:getAccountSummary": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:getContextKeysForCustomPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:getContextKeysForPrincipalPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:getCredentialReport": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:getGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:getGroupPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:getInstanceProfile": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:getLoginProfile": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:getOpenIDConnectProvider": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:getPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:getPolicyVersion": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:getRole": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:getRolePolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:getSAMLProvider": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:getSSHPublicKey": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:getServerCertificate": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:getUser": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:getUserPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listAccessKeys": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listAccountAliases": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listAttachedGroupPolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listAttachedRolePolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listAttachedUserPolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listEntitiesForPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listGroupPolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listGroupsForUser": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listInstanceProfiles": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listInstanceProfilesForRole": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listMFADevices": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listOpenIDConnectProviders": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listPolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listPolicyVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listRolePolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listRoles": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listSAMLProviders": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listSSHPublicKeys": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listServerCertificates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listSigningCertificates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listUserPolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listUsers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:listVirtualMFADevices": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:simulateCustomPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iam:simulatePrincipalPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "imagebuilder:getComponent": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "imagebuilder:getComponentPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "imagebuilder:getContainerRecipe": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "imagebuilder:getDistributionConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "imagebuilder:getImage": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "imagebuilder:getImagePipeline": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "imagebuilder:getImagePolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "imagebuilder:getImageRecipe": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "imagebuilder:getImageRecipePolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "imagebuilder:getInfrastructureConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "imagebuilder:listComponentBuildVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "imagebuilder:listComponents": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "imagebuilder:listContainerRecipes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "imagebuilder:listDistributionConfigurations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "imagebuilder:listImageBuildVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "imagebuilder:listImagePipelineImages": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "imagebuilder:listImagePipelines": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "imagebuilder:listImageRecipes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "imagebuilder:listImages": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "imagebuilder:listInfrastructureConfigurations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "imagebuilder:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "importexport:getStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "importexport:listJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "inspector:describeAssessmentRuns": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "inspector:describeAssessmentTargets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "inspector:describeAssessmentTemplates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "inspector:describeCrossAccountAccessRole": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "inspector:describeResourceGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "inspector:describeRulesPackages": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "inspector:getTelemetryMetadata": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "inspector:listAssessmentRunAgents": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "inspector:listAssessmentRuns": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "inspector:listAssessmentTargets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "inspector:listAssessmentTemplates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "inspector:listEventSubscriptions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "inspector:listRulesPackages": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "inspector:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:describeAuthorizer": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:describeCACertificate": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:describeCertificate": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:describeDefaultAuthorizer": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:describeEndpoint": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:describeIndex": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:describeJobExecution": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:describeThing": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:describeThingGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:describeTunnel": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:getEffectivePolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:getIndexingConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:getLoggingOptions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:getPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:getPolicyVersion": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:getTopicRule": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:getV2LoggingOptions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listAttachedPolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listAuthorizers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listCACertificates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listCertificates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listCertificatesByCA": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listJobExecutionsForJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listJobExecutionsForThing": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listOutgoingCertificates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listPolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listPolicyPrincipals": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listPolicyVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listPrincipalPolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listPrincipalThings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listRoleAliases": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listTargetsForPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listThingGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listThingGroupsForThing": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listThingPrincipals": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listThingRegistrationTasks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listThingTypes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listThings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listTopicRules": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listTunnels": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iot:listV2LoggingLevels": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotevents:describeDetector": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotevents:describeDetectorModel": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotevents:describeInput": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotevents:describeLoggingOptions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotevents:listDetectorModelVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotevents:listDetectorModels": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotevents:listDetectors": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotevents:listInputs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotsitewise:describeAccessPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotsitewise:describeAsset": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotsitewise:describeAssetModel": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotsitewise:describeAssetProperty": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotsitewise:describeDashboard": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotsitewise:describeGateway": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotsitewise:describeGatewayCapabilityConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotsitewise:describeLoggingOptions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotsitewise:describePortal": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotsitewise:describeProject": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotsitewise:listAccessPolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotsitewise:listAssetModels": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotsitewise:listAssets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotsitewise:listAssociatedAssets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotsitewise:listDashboards": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotsitewise:listGateways": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotsitewise:listPortals": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotsitewise:listProjectAssets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotsitewise:listProjects": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotwireless:getDestination": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotwireless:getDeviceProfile": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotwireless:getPartnerAccount": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotwireless:getServiceEndpoint": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotwireless:getServiceProfile": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotwireless:getWirelessDevice": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotwireless:getWirelessDeviceStatistics": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotwireless:getWirelessGateway": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotwireless:getWirelessGatewayCertificate": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotwireless:getWirelessGatewayFirmwareInformation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotwireless:getWirelessGatewayStatistics": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotwireless:getWirelessGatewayTask": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotwireless:getWirelessGatewayTaskDefinition": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotwireless:listDestinations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotwireless:listDeviceProfiles": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotwireless:listPartnerAccounts": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotwireless:listServiceProfiles": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotwireless:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotwireless:listWirelessDevices": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotwireless:listWirelessGatewayTaskDefinitions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "iotwireless:listWirelessGateways": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kafka:describeCluster": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kafka:getBootstrapBrokers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kafka:listClusters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kafka:listNodes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kendra:describeDataSource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kendra:describeFaq": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kendra:describeIndex": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kendra:listDataSources": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kendra:listFaqs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kendra:listIndices": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kinesis:CreateStream": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "kinesis:DeleteStream": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "kinesis:DescribeLimits": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "kinesis:DescribeStream": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "kinesis:GetRecords": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "kinesis:GetShardIterator": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "kinesis:MergeShards": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "kinesis:PutRecord": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "kinesis:SplitShard": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "kinesis:describeStream": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kinesis:listStreams": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kinesis:listTagsForStream": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kinesisanalytics:describeApplication": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kinesisanalytics:describeApplicationSnapshot": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kinesisanalytics:listApplicationSnapshots": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kinesisanalytics:listApplications": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kms:DescribeKey": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "kms:GetKeyPolicy": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "kms:ListGrants": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "kms:ListKeyPolicies": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "kms:ListKeys": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "kms:describeKey": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kms:getKeyPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kms:getKeyRotationStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kms:listAliases": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kms:listGrants": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kms:listKeyPolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kms:listKeys": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kms:listResourceTags": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "kms:listRetirableGrants": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:GetLayerVersionPolicy": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:GetPolicy": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:ListAliases": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:ListFunctions": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:ListLayerVersions": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:ListLayers": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:ListVersionsByFunction": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:getAccountSettings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:getAlias": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:getCodeSigningConfig": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:getEventSourceMapping": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:getFunction": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:getFunctionCodeSigningConfig": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:getFunctionConcurrency": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:getFunctionConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:getFunctionEventInvokeConfig": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:getLayerVersion": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:getLayerVersionPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:getPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:getProvisionedConcurrencyConfig": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:listAliases": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:listCodeSigningConfigs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:listEventSourceMappings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:listFunctionEventInvokeConfigs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:listFunctions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:listFunctionsByCodeSigningConfig": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:listLayerVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:listLayers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:listProvisionedConcurrencyConfigs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lambda:listVersionsByFunction": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "launchwizard:describeProvisionedApp": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "launchwizard:describeProvisioningEvents": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "launchwizard:listProvisionedApps": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lex:getBot": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lex:getBotAlias": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lex:getBotAliases": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lex:getBotChannelAssociation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lex:getBotChannelAssociations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lex:getBotVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lex:getBots": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lex:getBuiltinIntent": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lex:getBuiltinIntents": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lex:getBuiltinSlotTypes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lex:getIntent": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lex:getIntentVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lex:getIntents": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lex:getSlotType": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lex:getSlotTypeVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lex:getSlotTypes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "license-manager:getLicenseConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "license-manager:getServiceSettings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "license-manager:listAssociationsForLicenseConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "license-manager:listFailuresForLicenseConfigurationOperations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "license-manager:listLicenseConfigurations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "license-manager:listLicenseSpecificationsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "license-manager:listResourceInventory": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "license-manager:listUsageForLicenseConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getActiveNames": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getAlarms": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getAutoSnapshots": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getBlueprints": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getBundles": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getCertificates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getContainerImages": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getContainerServiceDeployments": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getContainerServices": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getDisk": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getDiskSnapshot": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getDiskSnapshots": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getDisks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getDistributions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getDomain": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getDomains": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getExportSnapshotRecords": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getInstance": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getInstanceMetricData": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getInstancePortStates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getInstanceSnapshot": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getInstanceSnapshots": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getInstanceState": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getKeyPair": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getKeyPairs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getLoadBalancer": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getLoadBalancerTlsCertificates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getLoadBalancers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getOperation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getOperations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getOperationsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getRegions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getRelationalDatabase": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getRelationalDatabaseSnapshot": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getRelationalDatabaseSnapshots": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getRelationalDatabases": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getStaticIp": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lightsail:getStaticIps": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "logs:CreateLogGroup": { + "roles": { + "Allow": { + "AROAJY5MNJYDKGD2UIATQ": { + "Resource": { + "arn:aws:logs:eu-west-1:430150006394:*": { + "policies": { + "ANPAIDFYJXP7KKG7FLVWO": { + "condition": null + } + } + } + } + } + } + } + }, + "logs:CreateLogStream": { + "roles": { + "Allow": { + "AROAJY5MNJYDKGD2UIATQ": { + "Resource": { + "arn:aws:logs:eu-west-1:430150006394:log-group:/aws/lambda/load-wikipedia:*": { + "policies": { + "ANPAIDFYJXP7KKG7FLVWO": { + "condition": null + } + } + } + } + } + } + } + }, + "logs:DescribeMetricFilters": { + "roles": { + "Allow": { + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + } + } + } + }, + "logs:PutLogEvents": { + "roles": { + "Allow": { + "AROAJY5MNJYDKGD2UIATQ": { + "Resource": { + "arn:aws:logs:eu-west-1:430150006394:log-group:/aws/lambda/load-wikipedia:*": { + "policies": { + "ANPAIDFYJXP7KKG7FLVWO": { + "condition": null + } + } + } + } + } + } + } + }, + "logs:describeDestinations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "logs:describeExportTasks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "logs:describeLogGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "logs:describeLogStreams": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "logs:describeMetricFilters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "logs:describeQueries": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "logs:describeSubscriptionFilters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "logs:testMetricFilter": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lookoutmetrics:describeAlert": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lookoutmetrics:describeAnomalyDetectionExecutions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lookoutmetrics:describeAnomalyDetector": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lookoutmetrics:describeMetricSet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lookoutmetrics:getAnomalyGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lookoutmetrics:getDataQualityMetrics": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lookoutmetrics:getFeedback": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lookoutmetrics:getSampleData": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lookoutmetrics:listAlerts": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lookoutmetrics:listAnomalyDetectors": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lookoutmetrics:listAnomalyGroupSummaries": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lookoutmetrics:listAnomalyGroupTimeSeries": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lookoutmetrics:listMetricSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "lookoutmetrics:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "machinelearning:describeBatchPredictions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "machinelearning:describeDataSources": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "machinelearning:describeEvaluations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "machinelearning:describeMLModels": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "machinelearning:getBatchPrediction": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "machinelearning:getDataSource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "machinelearning:getEvaluation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "machinelearning:getMLModel": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "managedblockchain:getMember": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "managedblockchain:getNetwork": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "managedblockchain:getNode": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "managedblockchain:listMembers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "managedblockchain:listNetworks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "managedblockchain:listNodes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediaconnect:describeFlow": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediaconnect:listEntitlements": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediaconnect:listFlows": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediaconvert:describeEndpoints": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediaconvert:getJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediaconvert:getJobTemplate": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediaconvert:getPreset": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediaconvert:getQueue": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediaconvert:listJobTemplates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediaconvert:listJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "medialive:describeChannel": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "medialive:describeInput": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "medialive:describeInputDevice": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "medialive:describeInputSecurityGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "medialive:describeMultiplex": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "medialive:describeOffering": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "medialive:describeReservation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "medialive:describeSchedule": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "medialive:listChannels": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "medialive:listInputDevices": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "medialive:listInputSecurityGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "medialive:listInputs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "medialive:listMultiplexes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "medialive:listOfferings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "medialive:listReservations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediapackage:describeChannel": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediapackage:describeOriginEndpoint": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediapackage:listChannels": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediapackage:listOriginEndpoints": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediastore:describeContainer": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediastore:describeObject": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediastore:getContainerPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediastore:getCorsPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediastore:listContainers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediastore:listItems": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediatailor:getPlaybackConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mediatailor:listPlaybackConfigurations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mgn:describeJobLogItems": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mgn:describeJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mgn:describeReplicationConfigurationTemplates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mgn:describeSourceServers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mgn:getLaunchConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mgn:getReplicationConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getAdmChannel": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getApnsChannel": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getApnsSandboxChannel": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getApnsVoipChannel": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getApnsVoipSandboxChannel": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getApp": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getApplicationSettings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getApps": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getBaiduChannel": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getCampaign": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getCampaignActivities": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getCampaignVersion": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getCampaignVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getCampaigns": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getEmailChannel": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getEndpoint": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getEventStream": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getExportJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getExportJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getGcmChannel": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getImportJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getImportJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getSegment": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getSegmentImportJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getSegmentVersion": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getSegmentVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getSegments": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mobiletargeting:getSmsChannel": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mq:describeBroker": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mq:describeConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mq:describeConfigurationRevision": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mq:describeUser": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mq:listBrokers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mq:listConfigurationRevisions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mq:listConfigurations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "mq:listUsers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "network-firewall:describeFirewall": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "network-firewall:describeFirewallPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "network-firewall:describeLoggingConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "network-firewall:describeRuleGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "network-firewall:listFirewallPolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "network-firewall:listFirewalls": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "network-firewall:listRuleGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "networkmanager:describeGlobalNetworks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "networkmanager:getCustomerGatewayAssociations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "networkmanager:getDevices": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "networkmanager:getLinkAssociations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "networkmanager:getLinks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "networkmanager:getSites": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "networkmanager:getTransitGatewayRegistrations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks-cm:describeAccountAttributes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks-cm:describeBackups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks-cm:describeEvents": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks-cm:describeNodeAssociationStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks-cm:describeServers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:describeAgentVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:describeApps": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:describeCommands": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:describeDeployments": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:describeEcsClusters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:describeElasticIps": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:describeElasticLoadBalancers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:describeInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:describeLayers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:describeLoadBasedAutoScaling": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:describeMyUserProfile": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:describePermissions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:describeRaidArrays": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:describeRdsDbInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:describeServiceErrors": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:describeStackProvisioningParameters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:describeStackSummary": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:describeStacks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:describeTimeBasedAutoScaling": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:describeUserProfiles": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:describeVolumes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "opsworks:getHostnameSuggestion": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "organizations:DescribeAccount": { + "roles": { + "Allow": { + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + }, + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "organizations:DescribeOrganization": { + "roles": { + "Allow": { + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + }, + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "organizations:DescribeOrganizationalUnit": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "organizations:ListAWSServiceAccessForOrganization": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "organizations:ListAccounts": { + "roles": { + "Allow": { + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + }, + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "organizations:ListAccountsForParent": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "organizations:ListChildren": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "organizations:ListDelegatedAdministrators": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "organizations:ListOrganizationalUnitsForParent": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "organizations:ListParents": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "organizations:ListRoots": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "organizations:listAccounts": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "organizations:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "outposts:getOutpost": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "outposts:getOutpostInstanceTypes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "outposts:listOutposts": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "outposts:listSites": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "personalize:describeAlgorithm": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "personalize:describeCampaign": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "personalize:describeDataset": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "personalize:describeDatasetGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "personalize:describeDatasetImportJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "personalize:describeEventTracker": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "personalize:describeFeatureTransformation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "personalize:describeRecipe": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "personalize:describeSchema": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "personalize:describeSolution": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "personalize:describeSolutionVersion": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "personalize:listCampaigns": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "personalize:listDatasetGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "personalize:listDatasetImportJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "personalize:listDatasets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "personalize:listEventTrackers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "personalize:listRecipes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "personalize:listSchemas": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "personalize:listSolutionVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "personalize:listSolutions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "polly:describeVoices": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "polly:getLexicon": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "polly:listLexicons": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "pricing:describeServices": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "pricing:getAttributeValues": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "pricing:getProducts": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "quicksight:describeDashboard": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "quicksight:describeDashboardPermissions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "quicksight:describeGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "quicksight:describeIAMPolicyAssignment": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "quicksight:describeTemplate": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "quicksight:describeTemplateAlias": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "quicksight:describeTemplatePermissions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "quicksight:describeUser": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "quicksight:listDashboards": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "quicksight:listGroupMemberships": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "quicksight:listGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "quicksight:listIAMPolicyAssignments": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "quicksight:listIAMPolicyAssignmentsForUser": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "quicksight:listTemplateAliases": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "quicksight:listTemplateVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "quicksight:listTemplates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "quicksight:listUserGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "quicksight:listUsers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ram:getPermission": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ram:getResourceShareAssociations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ram:getResourceShareInvitations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ram:getResourceShares": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ram:listPendingInvitationResources": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ram:listPrincipals": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ram:listResourceSharePermissions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ram:listResources": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:Describe*": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:DescribeAccountAttributes": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:DescribeDBClusters": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:DescribeDBEngineVersions": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:DescribeDBInstances": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:DescribeDBParameterGroups": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:DescribeDBParameters": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:DescribeDBSecurityGroups": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:DescribeDBSnapshots": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:DescribeDBSubnetGroups": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:DescribeEngineDefaultParameters": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:DescribeEvents": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:DescribeOptionGroupOptions": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:DescribeOptionGroups": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:DescribeOrderableDBInstanceOptions": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:DescribeReservedDBInstances": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:DescribeReservedDBInstancesOfferings": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:ListTagsForResource": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeAccountAttributes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeCertificates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeDBClusterParameterGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeDBClusterParameters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeDBClusterSnapshots": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeDBClusters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeDBEngineVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeDBInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeDBParameterGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeDBParameters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeDBSecurityGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeDBSnapshotAttributes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeDBSnapshots": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeDBSubnetGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeEngineDefaultClusterParameters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeEngineDefaultParameters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeEventCategories": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeEventSubscriptions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeEvents": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeExportTasks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeOptionGroupOptions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeOptionGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeOrderableDBInstanceOptions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describePendingMaintenanceActions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeReservedDBInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:describeReservedDBInstancesOfferings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rds:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift-data:describeStatement": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift-data:listStatements": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:DescribeClusters": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:DescribeReservedNodeOfferings": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:DescribeReservedNodes": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeClusterParameterGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeClusterParameters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeClusterSecurityGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeClusterSnapshots": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeClusterSubnetGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeClusterVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeClusters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeDefaultClusterParameters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeEventCategories": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeEventSubscriptions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeEvents": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeHsmClientCertificates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeHsmConfigurations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeLoggingStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeOrderableClusterOptions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeReservedNodeOfferings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeReservedNodes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeResize": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeSnapshotCopyGrants": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeStorage": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeTableRestoreStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "redshift:describeTags": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rekognition:listCollections": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "rekognition:listFaces": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "resource-groups:getGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "resource-groups:getGroupQuery": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "resource-groups:getTags": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "resource-groups:listGroupResources": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "resource-groups:listGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "resource-groups:searchResources": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "robomaker:batchDescribeSimulationJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "robomaker:describeDeploymentJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "robomaker:describeFleet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "robomaker:describeRobot": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "robomaker:describeRobotApplication": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "robomaker:describeSimulationApplication": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "robomaker:describeSimulationJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "robomaker:listDeploymentJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "robomaker:listFleets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "robomaker:listRobotApplications": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "robomaker:listRobots": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "robomaker:listSimulationApplications": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "robomaker:listSimulationJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53-recovery-readiness:getCell": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53-recovery-readiness:getCellReadinessSummary": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53-recovery-readiness:getReadinessCheck": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53-recovery-readiness:getReadinessCheckResourceStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53-recovery-readiness:getReadinessCheckStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53-recovery-readiness:getRecoveryGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53-recovery-readiness:getRecoveryGroupReadinessSummary": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53-recovery-readiness:listCells": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53-recovery-readiness:listReadinessChecks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53-recovery-readiness:listRecoveryGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53-recovery-readiness:listResourceSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:GetAccountLimit": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:GetHealthCheck": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:GetHostedZone": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:ListHealthChecks": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:ListHostedZones": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:ListHostedZonesByName": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:ListResourceRecordSets": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:getChange": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:getCheckerIpRanges": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:getGeoLocation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:getHealthCheck": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:getHealthCheckCount": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:getHealthCheckLastFailureReason": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:getHealthCheckStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:getHostedZone": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:getHostedZoneCount": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:getReusableDelegationSet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:getTrafficPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:getTrafficPolicyInstance": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:getTrafficPolicyInstanceCount": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:listGeoLocations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:listHealthChecks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:listHostedZones": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:listHostedZonesByName": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:listResourceRecordSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:listReusableDelegationSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:listTagsForResources": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:listTrafficPolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:listTrafficPolicyInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:listTrafficPolicyInstancesByHostedZone": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:listTrafficPolicyInstancesByPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53:listTrafficPolicyVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53domains:checkDomainAvailability": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53domains:getContactReachabilityStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53domains:getDomainDetail": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53domains:getOperationDetail": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53domains:listDomains": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53domains:listOperations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53domains:listTagsForDomain": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53domains:viewBilling": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53resolver:getFirewallConfig": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53resolver:getFirewallDomainList": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53resolver:getFirewallRuleGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53resolver:getFirewallRuleGroupAssociation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53resolver:getResolverDnssecConfig": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53resolver:getResolverRulePolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53resolver:listFirewallConfigs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53resolver:listFirewallDomainLists": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53resolver:listFirewallDomains": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53resolver:listFirewallRuleGroupAssociations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53resolver:listFirewallRuleGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53resolver:listFirewallRules": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53resolver:listResolverDnssecConfigs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53resolver:listResolverEndpointIpAddresses": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53resolver:listResolverEndpoints": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53resolver:listResolverRuleAssociations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53resolver:listResolverRules": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "route53resolver:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:*": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:CreateBucket": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:DescribeMultiRegionAccessPointOperation": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:Get*": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:GetAccessPoint": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:GetAccessPointPolicy": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:GetAccessPointPolicyStatus": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:GetAccountPublicAccessBlock": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + }, + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:GetBucketAcl": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + }, + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:GetBucketLocation": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + }, + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:GetBucketLogging": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:GetBucketPolicy": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + }, + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:GetBucketPolicyStatus": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + }, + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:GetBucketPublicAccessBlock": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + }, + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:GetBucketVersioning": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:GetMultiRegionAccessPoint": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:GetMultiRegionAccessPointPolicy": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:GetMultiRegionAccessPointPolicyStatus": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:List*": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:ListAccessPoints": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:ListAllMyBuckets": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + }, + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:ListBucket": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:ListMultiRegionAccessPoints": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:getAccelerateConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:getAccessPointConfigurationForObjectLambda": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:getAccessPointForObjectLambda": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:getAccessPointPolicyStatusForObjectLambda": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:getAnalyticsConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:getBucketAcl": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:getBucketCORS": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:getBucketLocation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:getBucketLogging": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:getBucketNotification": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:getBucketPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:getBucketRequestPayment": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:getBucketTagging": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:getBucketVersioning": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:getBucketWebsite": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:getEncryptionConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:getInventoryConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:getLifecycleConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:getMetricsConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:getReplicationConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:listAccessPointsForObjectLambda": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:listAllMyBuckets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:listBucket": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "s3:listBucketMultipartUploads": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeAction": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeAlgorithm": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeApp": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeArtifact": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeAutoMLJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeCompilationJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeContext": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeDataQualityJobDefinition": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeDevice": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeDeviceFleet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeDomain": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeEdgePackagingJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeEndpoint": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeEndpointConfig": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeExperiment": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeFeatureGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeHumanTaskUi": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeHyperParameterTuningJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeImage": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeImageVersion": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeLabelingJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeModel": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeModelBiasJobDefinition": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeModelExplainabilityJobDefinition": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeModelPackage": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeModelPackageGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeModelQualityJobDefinition": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeMonitoringSchedule": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeNotebookInstance": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeNotebookInstanceLifecycleConfig": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describePipeline": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describePipelineDefinitionForExecution": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describePipelineExecution": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeProcessingJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeProject": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeSubscribedWorkteam": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeTrainingJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeTransformJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeTrial": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeTrialComponent": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeUserProfile": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:describeWorkteam": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listActions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listAlgorithms": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listApps": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listArtifacts": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listAssociations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listAutoMLJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listCandidatesForAutoMLJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listCodeRepositories": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listCompilationJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listContexts": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listDataQualityJobDefinitions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listDeviceFleets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listDevices": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listDomains": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listEdgePackagingJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listEndpointConfigs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listEndpoints": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listExperiments": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listFeatureGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listFlowDefinitions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listHumanTaskUis": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listHyperParameterTuningJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listImageVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listImages": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listLabelingJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listLabelingJobsForWorkteam": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listModelBiasJobDefinitions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listModelExplainabilityJobDefinitions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listModelPackageGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listModelPackages": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listModelQualityJobDefinitions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listModels": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listMonitoringExecutions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listMonitoringSchedules": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listNotebookInstanceLifecycleConfigs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listNotebookInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listPipelineExecutionSteps": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listPipelineExecutions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listPipelineParametersForExecution": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listPipelines": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listProcessingJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listProjects": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listSubscribedWorkteams": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listTags": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listTrainingJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listTrainingJobsForHyperParameterTuningJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listTransformJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listTrialComponents": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listTrials": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listUserProfiles": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sagemaker:listWorkteams": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sdb:*": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "sdb:BatchPutAttributes": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "sdb:Select": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "sdb:domainMetadata": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sdb:listDomains": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "secretsmanager:DescribeSecret": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "secretsmanager:GetResourcePolicy": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "secretsmanager:ListSecrets": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "secretsmanager:describeSecret": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "secretsmanager:getResourcePolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "secretsmanager:listSecretVersionIds": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "secretsmanager:listSecrets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "securityhub:getEnabledStandards": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "securityhub:getFindings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "securityhub:getInsightResults": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "securityhub:getInsights": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "securityhub:getMasterAccount": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "securityhub:getMembers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "securityhub:listEnabledProductsForImport": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "securityhub:listInvitations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "securityhub:listMembers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicecatalog:describeConstraint": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicecatalog:describePortfolio": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicecatalog:describeProduct": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicecatalog:describeProductAsAdmin": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicecatalog:describeProductView": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicecatalog:describeProvisioningArtifact": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicecatalog:describeProvisioningParameters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicecatalog:describeRecord": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicecatalog:listAcceptedPortfolioShares": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicecatalog:listConstraintsForPortfolio": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicecatalog:listLaunchPaths": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicecatalog:listPortfolioAccess": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicecatalog:listPortfolios": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicecatalog:listPortfoliosForProduct": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicecatalog:listPrincipalsForPortfolio": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicecatalog:listProvisioningArtifacts": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicecatalog:listRecordHistory": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicecatalog:scanProvisionedProducts": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicecatalog:searchProducts": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicequotas:getAWSDefaultServiceQuota": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicequotas:getAssociationForServiceQuotaTemplate": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicequotas:getRequestedServiceQuotaChange": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicequotas:getServiceQuota": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicequotas:getServiceQuotaIncreaseRequestFromTemplate": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicequotas:listAWSDefaultServiceQuotas": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicequotas:listRequestedServiceQuotaChangeHistory": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicequotas:listRequestedServiceQuotaChangeHistoryByQuota": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicequotas:listServiceQuotaIncreaseRequestsInTemplate": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicequotas:listServiceQuotas": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "servicequotas:listServices": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:GetSendQuota": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:describeActiveReceiptRuleSet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:describeReceiptRule": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:describeReceiptRuleSet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:getAccount": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:getBlacklistReports": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:getConfigurationSet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:getConfigurationSetEventDestinations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:getDedicatedIp": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:getDedicatedIps": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:getDeliverabilityDashboardOptions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:getDeliverabilityTestReport": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:getDomainDeliverabilityCampaign": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:getDomainStatisticsReport": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:getEmailIdentity": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:getIdentityDkimAttributes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:getIdentityMailFromDomainAttributes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:getIdentityNotificationAttributes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:getIdentityPolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:getIdentityVerificationAttributes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:getSendQuota": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:getSendStatistics": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:listConfigurationSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:listDedicatedIpPools": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:listDeliverabilityTestReports": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:listDomainDeliverabilityCampaigns": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:listEmailIdentities": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:listIdentities": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:listIdentityPolicies": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:listReceiptFilters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:listReceiptRuleSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ses:listVerifiedEmailAddresses": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "shield:describeAttack": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "shield:describeProtection": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "shield:describeSubscription": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "shield:listAttacks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "shield:listProtections": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sms-voice:getConfigurationSetEventDestinations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sms:getConnectors": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sms:getReplicationJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sms:getReplicationRuns": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sms:getServers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "snowball:describeAddress": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "snowball:describeAddresses": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "snowball:describeJob": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "snowball:getSnowballUsage": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "snowball:listJobs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sns:*": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "sns:GetTopicAttributes": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "sns:ListSubscriptionsByTopic": { + "roles": { + "Allow": { + "AROAWIJXQGZ5HSCDUOZE5": { + "Resource": { + "*": { + "policies": { + "ANPAJQPCESDDYDLLSOGYO": { + "condition": null + } + } + } + } + } + } + } + }, + "sns:ListTopics": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "sns:checkIfPhoneNumberIsOptedOut": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sns:getEndpointAttributes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sns:getPlatformApplicationAttributes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sns:getSMSAttributes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sns:getSubscriptionAttributes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sns:getTopicAttributes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sns:listEndpointsByPlatformApplication": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sns:listPhoneNumbersOptedOut": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sns:listPlatformApplications": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sns:listSubscriptions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sns:listSubscriptionsByTopic": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sns:listTopics": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sqs:*": { + "roles": { + "Allow": { + "AROAI265GPNVMDZAKJPPA": { + "Resource": { + "*": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + } + } + } + } + } + }, + "sqs:CreateQueue": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "sqs:Delete*": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "sqs:GetQueue*": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "sqs:GetQueueAttributes": { + "roles": { + "Allow": { + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "sqs:ListQueues": { + "roles": { + "Allow": { + "AROAJCHEQKY4NYQFQWP5K": { + "Resource": { + "*": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + } + } + }, + "AROAWIJXQGZ5OSPI4PBJL": { + "Resource": { + "*": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + } + } + } + } + }, + "sqs:PurgeQueue": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "sqs:ReceiveMessage": { + "roles": { + "Allow": { + "AROAIXBSWIKGEEDLMO53I": { + "Resource": { + "*": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + } + } + } + } + } + }, + "sqs:getQueueAttributes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sqs:getQueueUrl": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sqs:listDeadLetterSourceQueues": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "sqs:listQueues": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm-contacts:describeEngagement": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm-contacts:describePage": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm-contacts:getContact": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm-contacts:getContactChannel": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm-contacts:listContactChannels": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm-contacts:listContacts": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm-contacts:listEngagements": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm-contacts:listPageReceipts": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm-contacts:listPagesByContact": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm-contacts:listPagesByEngagement": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm-incidents:getIncidentRecord": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm-incidents:getReplicationSet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm-incidents:getResponsePlan": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm-incidents:listIncidentRecords": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm-incidents:listReplicationSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm-incidents:listResponsePlans": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm-incidents:listTimelineEvents": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeActivations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeAssociation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeAssociationExecutionTargets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeAssociationExecutions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeAutomationExecutions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeAutomationStepExecutions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeAvailablePatches": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeDocument": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeDocumentPermission": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeEffectiveInstanceAssociations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeEffectivePatchesForPatchBaseline": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeInstanceAssociationsStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeInstanceInformation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeInstancePatchStates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeInstancePatchStatesForPatchGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeInstancePatches": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeInventoryDeletions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeMaintenanceWindowExecutionTaskInvocations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeMaintenanceWindowExecutionTasks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeMaintenanceWindowExecutions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeMaintenanceWindowSchedule": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeMaintenanceWindowTargets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeMaintenanceWindowTasks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeMaintenanceWindows": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeMaintenanceWindowsForTarget": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeOpsItems": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeParameters": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describePatchBaselines": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describePatchGroupState": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describePatchGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describePatchProperties": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:describeSessions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:getAutomationExecution": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:getCommandInvocation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:getConnectionStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:getDefaultPatchBaseline": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:getDeployablePatchSnapshotForInstance": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:getInventorySchema": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:getMaintenanceWindow": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:getMaintenanceWindowExecution": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:getMaintenanceWindowExecutionTask": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:getMaintenanceWindowExecutionTaskInvocation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:getMaintenanceWindowTask": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:getOpsItem": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:getPatchBaseline": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:getPatchBaselineForPatchGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:getServiceSetting": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:labelParameterVersion": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:listAssociationVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:listAssociations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:listCommandInvocations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:listCommands": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:listComplianceItems": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:listComplianceSummaries": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:listDocumentVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:listDocuments": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:listOpsItemEvents": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:listResourceComplianceSummaries": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:listResourceDataSync": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "ssm:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "states:describeActivity": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "states:describeExecution": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "states:describeStateMachine": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "states:describeStateMachineForExecution": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "states:getExecutionHistory": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "states:listActivities": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "states:listExecutions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "states:listStateMachines": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:describeBandwidthRateLimit": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:describeCache": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:describeCachediSCSIVolumes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:describeFileSystemAssociations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:describeGatewayInformation": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:describeMaintenanceStartTime": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:describeNFSFileShares": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:describeSMBFileShares": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:describeSMBSettings": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:describeSnapshotSchedule": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:describeStorediSCSIVolumes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:describeTapeArchives": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:describeTapeRecoveryPoints": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:describeTapes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:describeUploadBuffer": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:describeVTLDevices": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:describeWorkingStorage": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:listFileShares": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:listFileSystemAssociations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:listGateways": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:listLocalDisks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:listTapes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:listVolumeInitiators": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:listVolumeRecoveryPoints": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "storagegateway:listVolumes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "swf:countClosedWorkflowExecutions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "swf:countOpenWorkflowExecutions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "swf:countPendingActivityTasks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "swf:countPendingDecisionTasks": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "swf:describeActivityType": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "swf:describeDomain": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "swf:describeWorkflowExecution": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "swf:describeWorkflowType": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "swf:getWorkflowExecutionHistory": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "swf:listActivityTypes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "swf:listClosedWorkflowExecutions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "swf:listDomains": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "swf:listOpenWorkflowExecutions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "swf:listWorkflowTypes": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "synthetics:describeCanaries": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "synthetics:describeCanariesLastRun": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "synthetics:describeRuntimeVersions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "synthetics:getCanary": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "synthetics:getCanaryRuns": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "transfer:describeServer": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "transfer:describeUser": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "transfer:listServers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "transfer:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "transfer:listUsers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf-regional:getByteMatchSet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf-regional:getChangeTokenStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf-regional:getIPSet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf-regional:getRule": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf-regional:getSqlInjectionMatchSet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf-regional:getWebACL": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf-regional:getWebACLForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf-regional:listByteMatchSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf-regional:listIPSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf-regional:listResourcesForWebACL": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf-regional:listRules": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf-regional:listSqlInjectionMatchSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf-regional:listWebACLs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf:getByteMatchSet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf:getChangeTokenStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf:getIPSet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf:getRule": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf:getSampledRequests": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf:getSizeConstraintSet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf:getSqlInjectionMatchSet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf:getWebACL": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf:getXssMatchSet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf:listByteMatchSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf:listIPSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf:listRules": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf:listSizeConstraintSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf:listSqlInjectionMatchSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf:listWebACLs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "waf:listXssMatchSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "wafv2:checkCapacity": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "wafv2:describeManagedRuleGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "wafv2:getIPSet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "wafv2:getLoggingConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "wafv2:getPermissionPolicy": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "wafv2:getRateBasedStatementManagedKeys": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "wafv2:getRegexPatternSet": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "wafv2:getRuleGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "wafv2:getSampledRequests": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "wafv2:getWebACL": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "wafv2:getWebACLForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "wafv2:listAvailableManagedRuleGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "wafv2:listIPSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "wafv2:listLoggingConfigurations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "wafv2:listRegexPatternSets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "wafv2:listResourcesForWebACL": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "wafv2:listRuleGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "wafv2:listTagsForResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "wafv2:listWebACLs": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workdocs:checkAlias": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workdocs:describeAvailableDirectories": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workdocs:describeInstances": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "worklink:describeAuditStreamConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "worklink:describeCompanyNetworkConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "worklink:describeDevice": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "worklink:describeDevicePolicyConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "worklink:describeDomain": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "worklink:describeFleetMetadata": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "worklink:describeIdentityProviderConfiguration": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "worklink:describeWebsiteCertificateAuthority": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "worklink:listDevices": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "worklink:listDomains": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "worklink:listFleets": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "worklink:listWebsiteAuthorizationProviders": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "worklink:listWebsiteCertificateAuthorities": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workmail:describeGroup": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workmail:describeOrganization": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workmail:describeResource": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workmail:describeUser": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workmail:listAliases": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workmail:listGroupMembers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workmail:listGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workmail:listMailboxPermissions": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workmail:listOrganizations": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workmail:listResourceDelegates": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workmail:listResources": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workmail:listUsers": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workspaces:describeAccount": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workspaces:describeAccountModifications": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workspaces:describeIpGroups": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workspaces:describeTags": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workspaces:describeWorkspaceBundles": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workspaces:describeWorkspaceDirectories": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workspaces:describeWorkspaceImages": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workspaces:describeWorkspaces": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + }, + "workspaces:describeWorkspacesConnectionStatus": { + "roles": { + "Allow": { + "AROAJCXETX2ROIWUKOPGG": { + "Resource": { + "*": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + } + } + } + } + } + } + } + }, + "policies": { + "ANPAI4YEZURRMKACW56EA": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ec2:DescribeInstances", + "ec2:DescribeLaunchTemplates", + "ec2:DescribeSpotInstanceRequests", + "ec2:DeleteLaunchTemplate", + "ec2:ModifyInstanceAttribute", + "ec2:TerminateInstances", + "ec2:CancelSpotInstanceRequests", + "ec2:DeleteNetworkInterface", + "ec2:DescribeInstanceAttribute", + "ec2:DescribeVolumeStatus", + "ec2:DescribeVolumes", + "ec2:DetachVolume", + "ec2:DeleteVolume", + "ec2:DescribePlacementGroups", + "ec2:DeletePlacementGroup" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "arn": "arn:aws:iam::aws:policy/aws-service-role/AmazonEMRCleanupPolicy", + "attached_to": { + "roles": [ + { + "id": "AROAJ2LRZXYT2USPF2ZTY", + "name": "AWSServiceRoleForEMRCleanup" + } + ] + }, + "id": "ANPAI4YEZURRMKACW56EA", + "name": "AmazonEMRCleanupPolicy" + }, + "ANPAIDFYJXP7KKG7FLVWO": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogGroup" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:eu-west-1:430150006394:*" + ] + }, + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:eu-west-1:430150006394:log-group:/aws/lambda/load-wikipedia:*" + ] + } + ], + "Version": "2012-10-17" + }, + "arn": "arn:aws:iam::430150006394:policy/service-role/AWSLambdaBasicExecutionRole-676647ec-377e-496c-8355-37f23bf12c85", + "attached_to": { + "roles": [ + { + "id": "AROAJY5MNJYDKGD2UIATQ", + "name": "load-wikipedia" + } + ] + }, + "id": "ANPAIDFYJXP7KKG7FLVWO", + "name": "AWSLambdaBasicExecutionRole-676647ec-377e-496c-8355-37f23bf12c85" + }, + "ANPAIDI2BQT2LKXZG36TW": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ec2:AuthorizeSecurityGroupEgress", + "ec2:AuthorizeSecurityGroupIngress", + "ec2:CancelSpotInstanceRequests", + "ec2:CreateFleet", + "ec2:CreateLaunchTemplate", + "ec2:CreateNetworkInterface", + "ec2:CreateSecurityGroup", + "ec2:CreateTags", + "ec2:DeleteLaunchTemplate", + "ec2:DeleteNetworkInterface", + "ec2:DeleteSecurityGroup", + "ec2:DeleteTags", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeAccountAttributes", + "ec2:DescribeDhcpOptions", + "ec2:DescribeImages", + "ec2:DescribeInstanceStatus", + "ec2:DescribeInstances", + "ec2:DescribeKeyPairs", + "ec2:DescribeLaunchTemplates", + "ec2:DescribeNetworkAcls", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribePrefixLists", + "ec2:DescribeRouteTables", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSpotInstanceRequests", + "ec2:DescribeSpotPriceHistory", + "ec2:DescribeSubnets", + "ec2:DescribeTags", + "ec2:DescribeVpcAttribute", + "ec2:DescribeVpcEndpoints", + "ec2:DescribeVpcEndpointServices", + "ec2:DescribeVpcs", + "ec2:DetachNetworkInterface", + "ec2:ModifyImageAttribute", + "ec2:ModifyInstanceAttribute", + "ec2:RequestSpotInstances", + "ec2:RevokeSecurityGroupEgress", + "ec2:RunInstances", + "ec2:TerminateInstances", + "ec2:DeleteVolume", + "ec2:DescribeVolumeStatus", + "ec2:DescribeVolumes", + "ec2:DetachVolume", + "iam:GetRole", + "iam:GetRolePolicy", + "iam:ListInstanceProfiles", + "iam:ListRolePolicies", + "iam:PassRole", + "s3:CreateBucket", + "s3:Get*", + "s3:List*", + "sdb:BatchPutAttributes", + "sdb:Select", + "sqs:CreateQueue", + "sqs:Delete*", + "sqs:GetQueue*", + "sqs:PurgeQueue", + "sqs:ReceiveMessage", + "cloudwatch:PutMetricAlarm", + "cloudwatch:DescribeAlarms", + "cloudwatch:DeleteAlarms", + "application-autoscaling:RegisterScalableTarget", + "application-autoscaling:DeregisterScalableTarget", + "application-autoscaling:PutScalingPolicy", + "application-autoscaling:DeleteScalingPolicy", + "application-autoscaling:Describe*" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "iam:CreateServiceLinkedRole" + ], + "Condition": { + "StringLike": { + "iam:AWSServiceName": "spot.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/aws-service-role/spot.amazonaws.com/AWSServiceRoleForEC2Spot*" + ] + } + ], + "Version": "2012-10-17" + }, + "arn": "arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceRole", + "attached_to": { + "roles": [ + { + "id": "AROAIXBSWIKGEEDLMO53I", + "name": "EMR_DefaultRole" + } + ] + }, + "id": "ANPAIDI2BQT2LKXZG36TW", + "name": "AmazonElasticMapReduceRole" + }, + "ANPAIGALS5RCDLZLB3PGS": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "cloudwatch:*", + "dynamodb:*", + "ec2:Describe*", + "elasticmapreduce:Describe*", + "elasticmapreduce:ListBootstrapActions", + "elasticmapreduce:ListClusters", + "elasticmapreduce:ListInstanceGroups", + "elasticmapreduce:ListInstances", + "elasticmapreduce:ListSteps", + "kinesis:CreateStream", + "kinesis:DeleteStream", + "kinesis:DescribeStream", + "kinesis:GetRecords", + "kinesis:GetShardIterator", + "kinesis:MergeShards", + "kinesis:PutRecord", + "kinesis:SplitShard", + "rds:Describe*", + "s3:*", + "sdb:*", + "sns:*", + "sqs:*", + "glue:CreateDatabase", + "glue:UpdateDatabase", + "glue:DeleteDatabase", + "glue:GetDatabase", + "glue:GetDatabases", + "glue:CreateTable", + "glue:UpdateTable", + "glue:DeleteTable", + "glue:GetTable", + "glue:GetTables", + "glue:GetTableVersions", + "glue:CreatePartition", + "glue:BatchCreatePartition", + "glue:UpdatePartition", + "glue:DeletePartition", + "glue:BatchDeletePartition", + "glue:GetPartition", + "glue:GetPartitions", + "glue:BatchGetPartition", + "glue:CreateUserDefinedFunction", + "glue:UpdateUserDefinedFunction", + "glue:DeleteUserDefinedFunction", + "glue:GetUserDefinedFunction", + "glue:GetUserDefinedFunctions" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "arn": "arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceforEC2Role", + "attached_to": { + "roles": [ + { + "id": "AROAI265GPNVMDZAKJPPA", + "name": "EMR_EC2_DefaultRole" + } + ] + }, + "id": "ANPAIGALS5RCDLZLB3PGS", + "name": "AmazonElasticMapReduceforEC2Role" + }, + "ANPAJ7W6266ELXF5MISDS": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "apigateway:GET" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:apigateway:*::/account", + "arn:aws:apigateway:*::/apis", + "arn:aws:apigateway:*::/apis/*", + "arn:aws:apigateway:*::/apis/*/authorizers", + "arn:aws:apigateway:*::/apis/*/authorizers/*", + "arn:aws:apigateway:*::/apis/*/deployments", + "arn:aws:apigateway:*::/apis/*/deployments/*", + "arn:aws:apigateway:*::/apis/*/integrations", + "arn:aws:apigateway:*::/apis/*/integrations/*", + "arn:aws:apigateway:*::/apis/*/integrations/*/integrationresponses", + "arn:aws:apigateway:*::/apis/*/integrations/*/integrationresponses/*", + "arn:aws:apigateway:*::/apis/*/models", + "arn:aws:apigateway:*::/apis/*/models/*", + "arn:aws:apigateway:*::/apis/*/routes", + "arn:aws:apigateway:*::/apis/*/routes/*", + "arn:aws:apigateway:*::/apis/*/routes/*/routeresponses", + "arn:aws:apigateway:*::/apis/*/routes/*/routeresponses/*", + "arn:aws:apigateway:*::/apis/*/stages", + "arn:aws:apigateway:*::/apis/*/stages/*", + "arn:aws:apigateway:*::/clientcertificates", + "arn:aws:apigateway:*::/clientcertificates/*", + "arn:aws:apigateway:*::/domainnames", + "arn:aws:apigateway:*::/domainnames/*", + "arn:aws:apigateway:*::/domainnames/*/apimappings", + "arn:aws:apigateway:*::/domainnames/*/apimappings/*", + "arn:aws:apigateway:*::/domainnames/*/basepathmappings", + "arn:aws:apigateway:*::/domainnames/*/basepathmappings/*", + "arn:aws:apigateway:*::/restapis", + "arn:aws:apigateway:*::/restapis/*", + "arn:aws:apigateway:*::/restapis/*/authorizers", + "arn:aws:apigateway:*::/restapis/*/authorizers/*", + "arn:aws:apigateway:*::/restapis/*/deployments", + "arn:aws:apigateway:*::/restapis/*/deployments/*", + "arn:aws:apigateway:*::/restapis/*/models", + "arn:aws:apigateway:*::/restapis/*/models/*", + "arn:aws:apigateway:*::/restapis/*/models/*/default_template", + "arn:aws:apigateway:*::/restapis/*/resources", + "arn:aws:apigateway:*::/restapis/*/resources/*", + "arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/integration/responses/*", + "arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/responses/*", + "arn:aws:apigateway:*::/restapis/*/stages/*/sdks/*", + "arn:aws:apigateway:*::/restapis/*/resources/*/methods/*", + "arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/integration", + "arn:aws:apigateway:*::/restapis/*/stages", + "arn:aws:apigateway:*::/restapis/*/stages/*" + ] + }, + { + "Action": [ + "iam:DeleteRole" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport" + ] + }, + { + "Action": [ + "a4b:getDevice", + "a4b:getProfile", + "a4b:getRoom", + "a4b:getRoomSkillParameter", + "a4b:getSkillGroup", + "a4b:searchDevices", + "a4b:searchProfiles", + "a4b:searchRooms", + "a4b:searchSkillGroups", + "access-analyzer:getFinding", + "access-analyzer:listAnalyzers", + "access-analyzer:listArchiveRules", + "access-analyzer:listFindings", + "acm-pca:describeCertificateAuthority", + "acm-pca:describeCertificateAuthorityAuditReport", + "acm-pca:getCertificate", + "acm-pca:getCertificateAuthorityCertificate", + "acm-pca:getCertificateAuthorityCsr", + "acm-pca:listCertificateAuthorities", + "acm-pca:listTags", + "acm:describeCertificate", + "acm:getCertificate", + "acm:listCertificates", + "acm:listTagsForCertificate", + "airflow:getEnvironment", + "airflow:listEnvironments", + "airflow:listTagsForResource", + "amplify:getApp", + "amplify:getBranch", + "amplify:getDomainAssociation", + "amplify:getJob", + "amplify:getWebhook", + "amplify:listApps", + "amplify:listWebhooks", + "appflow:describeConnectorEntity", + "appflow:describeConnectorProfiles", + "appflow:describeFlow", + "appflow:listFlows", + "application-autoscaling:describeScalableTargets", + "application-autoscaling:describeScalingActivities", + "application-autoscaling:describeScalingPolicies", + "application-autoscaling:describeScheduledActions", + "applicationinsights:describeComponentConfiguration", + "applicationinsights:describeComponentConfigurationRecommendation", + "applicationinsights:listApplications", + "applicationinsights:listComponents", + "applicationinsights:listConfigurationHistory", + "applicationinsights:listLogPatterns", + "applicationinsights:listLogPatternSets", + "appmesh:describeGatewayRoute", + "appmesh:describeMesh", + "appmesh:describeRoute", + "appmesh:describeVirtualGateway", + "appmesh:describeVirtualNode", + "appmesh:describeVirtualRouter", + "appmesh:describeVirtualService", + "appmesh:listGatewayRoutes", + "appmesh:listMeshes", + "appmesh:listRoutes", + "appmesh:listTagsForResource", + "appmesh:listVirtualGateways", + "appmesh:listVirtualNodes", + "appmesh:listVirtualRouters", + "appmesh:listVirtualServices", + "apprunner:describeAutoScalingConfiguration", + "apprunner:describeCustomDomains", + "apprunner:describeOperation", + "apprunner:describeService", + "apprunner:listAutoScalingConfigurations", + "apprunner:listConnections", + "apprunner:listOperations", + "apprunner:listServices", + "apprunner:listTagsForResource", + "appstream:describeDirectoryConfigs", + "appstream:describeFleets", + "appstream:describeImageBuilders", + "appstream:describeImages", + "appstream:describeSessions", + "appstream:describeStacks", + "appstream:listAssociatedFleets", + "appstream:listAssociatedStacks", + "appstream:listTagsForResource", + "appsync:getFunction", + "appsync:getGraphqlApi", + "appsync:getIntrospectionSchema", + "appsync:getResolver", + "appsync:getSchemaCreationStatus", + "appsync:getType", + "appsync:listDataSources", + "appsync:listFunctions", + "appsync:listGraphqlApis", + "appsync:listResolvers", + "appsync:listTypes", + "athena:batchGetNamedQuery", + "athena:batchGetQueryExecution", + "athena:getNamedQuery", + "athena:getQueryExecution", + "athena:getWorkGroup", + "athena:listNamedQueries", + "athena:listQueryExecutions", + "athena:listTagsForResource", + "athena:listWorkGroups", + "auditmanager:getAccountStatus", + "auditmanager:getDelegations", + "auditmanager:listAssessmentFrameworks", + "auditmanager:listAssessmentReports", + "auditmanager:listAssessments", + "auditmanager:listControls", + "auditmanager:listKeywordsForDataSource", + "auditmanager:listNotifications", + "autoscaling-plans:describeScalingPlanResources", + "autoscaling-plans:describeScalingPlans", + "autoscaling-plans:getScalingPlanResourceForecastData", + "autoscaling:describeAccountLimits", + "autoscaling:describeAdjustmentTypes", + "autoscaling:describeAutoScalingGroups", + "autoscaling:describeAutoScalingInstances", + "autoscaling:describeAutoScalingNotificationTypes", + "autoscaling:describeInstanceRefreshes", + "autoscaling:describeLaunchConfigurations", + "autoscaling:describeLifecycleHooks", + "autoscaling:describeLifecycleHookTypes", + "autoscaling:describeLoadBalancers", + "autoscaling:describeLoadBalancerTargetGroups", + "autoscaling:describeMetricCollectionTypes", + "autoscaling:describeNotificationConfigurations", + "autoscaling:describePolicies", + "autoscaling:describeScalingActivities", + "autoscaling:describeScalingProcessTypes", + "autoscaling:describeScheduledActions", + "autoscaling:describeTags", + "autoscaling:describeTerminationPolicyTypes", + "backup:describeBackupJob", + "backup:describeBackupVault", + "backup:describeProtectedResource", + "backup:describeRecoveryPoint", + "backup:describeRestoreJob", + "backup:getBackupPlan", + "backup:getBackupPlanFromJSON", + "backup:getBackupPlanFromTemplate", + "backup:getBackupSelection", + "backup:getBackupVaultAccessPolicy", + "backup:getBackupVaultNotifications", + "backup:getRecoveryPointRestoreMetadata", + "backup:getSupportedResourceTypes", + "backup:listBackupJobs", + "backup:listBackupPlans", + "backup:listBackupPlanTemplates", + "backup:listBackupPlanVersions", + "backup:listBackupSelections", + "backup:listBackupVaults", + "backup:listProtectedResources", + "backup:listRecoveryPointsByBackupVault", + "backup:listRecoveryPointsByResource", + "backup:listRestoreJobs", + "backup:listTags", + "batch:describeComputeEnvironments", + "batch:describeJobDefinitions", + "batch:describeJobQueues", + "batch:describeJobs", + "batch:listJobs", + "braket:getDevice", + "braket:getQuantumTask", + "braket:searchDevices", + "braket:searchQuantumTasks", + "budgets:viewBudget", + "ce:getCostAndUsage", + "ce:getCostAndUsageWithResources", + "ce:getCostForecast", + "ce:getDimensionValues", + "ce:getReservationCoverage", + "ce:getReservationPurchaseRecommendation", + "ce:getReservationUtilization", + "ce:getRightsizingRecommendation", + "ce:getSavingsPlansCoverage", + "ce:getSavingsPlansPurchaseRecommendation", + "ce:getSavingsPlansUtilization", + "ce:getSavingsPlansUtilizationDetails", + "ce:getTags", + "cloud9:describeEnvironmentMemberships", + "cloud9:describeEnvironments", + "cloud9:listEnvironments", + "clouddirectory:getDirectory", + "clouddirectory:listDirectories", + "cloudformation:describeAccountLimits", + "cloudformation:describeChangeSet", + "cloudformation:describeStackEvents", + "cloudformation:describeStackInstance", + "cloudformation:describeStackResource", + "cloudformation:describeStackResources", + "cloudformation:describeStacks", + "cloudformation:describeStackSet", + "cloudformation:describeStackSetOperation", + "cloudformation:estimateTemplateCost", + "cloudformation:getStackPolicy", + "cloudformation:getTemplate", + "cloudformation:getTemplateSummary", + "cloudformation:listChangeSets", + "cloudformation:listExports", + "cloudformation:listImports", + "cloudformation:listStackInstances", + "cloudformation:listStackResources", + "cloudformation:listStacks", + "cloudformation:listStackSetOperationResults", + "cloudformation:listStackSetOperations", + "cloudformation:listStackSets", + "cloudfront:getCloudFrontOriginAccessIdentity", + "cloudfront:getCloudFrontOriginAccessIdentityConfig", + "cloudfront:getDistribution", + "cloudfront:getDistributionConfig", + "cloudfront:getInvalidation", + "cloudfront:getStreamingDistribution", + "cloudfront:getStreamingDistributionConfig", + "cloudfront:listCloudFrontOriginAccessIdentities", + "cloudfront:listDistributions", + "cloudfront:listDistributionsByWebACLId", + "cloudfront:listInvalidations", + "cloudfront:listStreamingDistributions", + "cloudhsm:describeBackups", + "cloudhsm:describeClusters", + "cloudsearch:describeAnalysisSchemes", + "cloudsearch:describeAvailabilityOptions", + "cloudsearch:describeDomains", + "cloudsearch:describeExpressions", + "cloudsearch:describeIndexFields", + "cloudsearch:describeScalingParameters", + "cloudsearch:describeServiceAccessPolicies", + "cloudsearch:describeSuggesters", + "cloudsearch:listDomainNames", + "cloudtrail:describeTrails", + "cloudtrail:getEventSelectors", + "cloudtrail:getInsightSelectors", + "cloudtrail:getTrail", + "cloudtrail:getTrailStatus", + "cloudtrail:listPublicKeys", + "cloudtrail:listTags", + "cloudtrail:listTrails", + "cloudtrail:lookupEvents", + "cloudwatch:describeAlarmHistory", + "cloudwatch:describeAlarms", + "cloudwatch:describeAlarmsForMetric", + "cloudwatch:describeAnomalyDetectors", + "cloudwatch:describeInsightRules", + "cloudwatch:getDashboard", + "cloudwatch:getInsightRuleReport", + "cloudwatch:getMetricData", + "cloudwatch:getMetricStatistics", + "cloudwatch:listDashboards", + "cloudwatch:listMetrics", + "codeartifact:describeDomain", + "codeartifact:describePackageVersion", + "codeartifact:describeRepository", + "codeartifact:getDomainPermissionsPolicy", + "codeartifact:getRepositoryEndPoint", + "codeartifact:getRepositoryPermissionsPolicy", + "codeartifact:listDomains", + "codeartifact:listPackages", + "codeartifact:listPackageVersionAssets", + "codeartifact:listPackageVersions", + "codeartifact:listRepositories", + "codeartifact:listRepositoriesInDomain", + "codebuild:batchGetBuildBatches", + "codebuild:batchGetBuilds", + "codebuild:batchGetProjects", + "codebuild:listBuildBatches", + "codebuild:listBuildBatchesForProject", + "codebuild:listBuilds", + "codebuild:listBuildsForProject", + "codebuild:listCuratedEnvironmentImages", + "codebuild:listProjects", + "codebuild:listSourceCredentials", + "codecommit:batchGetRepositories", + "codecommit:getBranch", + "codecommit:getRepository", + "codecommit:getRepositoryTriggers", + "codecommit:listBranches", + "codecommit:listRepositories", + "codedeploy:batchGetApplicationRevisions", + "codedeploy:batchGetApplications", + "codedeploy:batchGetDeploymentGroups", + "codedeploy:batchGetDeploymentInstances", + "codedeploy:batchGetDeployments", + "codedeploy:batchGetDeploymentTargets", + "codedeploy:batchGetOnPremisesInstances", + "codedeploy:getApplication", + "codedeploy:getApplicationRevision", + "codedeploy:getDeployment", + "codedeploy:getDeploymentConfig", + "codedeploy:getDeploymentGroup", + "codedeploy:getDeploymentInstance", + "codedeploy:getDeploymentTarget", + "codedeploy:getOnPremisesInstance", + "codedeploy:listApplicationRevisions", + "codedeploy:listApplications", + "codedeploy:listDeploymentConfigs", + "codedeploy:listDeploymentGroups", + "codedeploy:listDeploymentInstances", + "codedeploy:listDeployments", + "codedeploy:listDeploymentTargets", + "codedeploy:listGitHubAccountTokenNames", + "codedeploy:listOnPremisesInstances", + "codepipeline:getJobDetails", + "codepipeline:getPipeline", + "codepipeline:getPipelineExecution", + "codepipeline:getPipelineState", + "codepipeline:listActionExecutions", + "codepipeline:listActionTypes", + "codepipeline:listPipelineExecutions", + "codepipeline:listPipelines", + "codepipeline:listWebhooks", + "codestar:describeProject", + "codestar:listProjects", + "codestar:listResources", + "codestar:listTeamMembers", + "codestar:listUserProfiles", + "cognito-identity:describeIdentityPool", + "cognito-identity:getIdentityPoolRoles", + "cognito-identity:listIdentities", + "cognito-identity:listIdentityPools", + "cognito-idp:adminGetUser", + "cognito-idp:describeIdentityProvider", + "cognito-idp:describeResourceServer", + "cognito-idp:describeRiskConfiguration", + "cognito-idp:describeUserImportJob", + "cognito-idp:describeUserPool", + "cognito-idp:describeUserPoolClient", + "cognito-idp:describeUserPoolDomain", + "cognito-idp:getGroup", + "cognito-idp:getUICustomization", + "cognito-idp:getUser", + "cognito-idp:getUserPoolMfaConfig", + "cognito-idp:listGroups", + "cognito-idp:listIdentityProviders", + "cognito-idp:listResourceServers", + "cognito-idp:listUserImportJobs", + "cognito-idp:listUserPoolClients", + "cognito-idp:listUserPools", + "cognito-sync:describeDataset", + "cognito-sync:describeIdentityPoolUsage", + "cognito-sync:describeIdentityUsage", + "cognito-sync:getCognitoEvents", + "cognito-sync:getIdentityPoolConfiguration", + "cognito-sync:listDatasets", + "cognito-sync:listIdentityPoolUsage", + "compute-optimizer:getAutoScalingGroupRecommendations", + "compute-optimizer:getEBSVolumeRecommendations", + "compute-optimizer:getEC2InstanceRecommendations", + "compute-optimizer:getEC2RecommendationProjectedMetrics", + "compute-optimizer:getEnrollmentStatus", + "compute-optimizer:getRecommendationSummaries", + "config:describeConfigRuleEvaluationStatus", + "config:describeConfigRules", + "config:describeConfigurationRecorders", + "config:describeConfigurationRecorderStatus", + "config:describeDeliveryChannels", + "config:describeDeliveryChannelStatus", + "config:getResourceConfigHistory", + "config:listDiscoveredResources", + "connect:describeUser", + "connect:getCurrentMetricData", + "connect:getMetricData", + "connect:listRoutingProfiles", + "connect:listSecurityProfiles", + "connect:listUsers", + "controltower:describeAccountFactoryConfig", + "controltower:describeCoreService", + "controltower:describeGuardrail", + "controltower:describeGuardrailForTarget", + "controltower:describeManagedAccount", + "controltower:describeSingleSignOn", + "controltower:getAvailableUpdates", + "controltower:getHomeRegion", + "controltower:getLandingZoneStatus", + "controltower:listDirectoryGroups", + "controltower:listGuardrailsForTarget", + "controltower:listGuardrailViolations", + "controltower:listManagedAccounts", + "controltower:listManagedAccountsForGuardrail", + "controltower:listManagedAccountsForParent", + "controltower:listManagedOrganizationalUnits", + "controltower:listManagedOrganizationalUnitsForGuardrail", + "databrew:describeDataset", + "databrew:describeJob", + "databrew:describeProject", + "databrew:describeRecipe", + "databrew:listDatasets", + "databrew:listJobRuns", + "databrew:listJobs", + "databrew:listProjects", + "databrew:listRecipes", + "databrew:listRecipeVersions", + "databrew:listTagsForResource", + "datapipeline:describeObjects", + "datapipeline:describePipelines", + "datapipeline:getPipelineDefinition", + "datapipeline:listPipelines", + "datapipeline:queryObjects", + "datasync:describeAgent", + "datasync:describeLocationEfs", + "datasync:describeLocationFsxWindows", + "datasync:describeLocationNfs", + "datasync:describeLocationObjectStorage", + "datasync:describeLocationS3", + "datasync:describeLocationSmb", + "datasync:describeTask", + "datasync:describeTaskExecution", + "datasync:listAgents", + "datasync:listLocations", + "datasync:listTaskExecutions", + "datasync:listTasks", + "dax:describeClusters", + "dax:describeDefaultParameters", + "dax:describeEvents", + "dax:describeParameterGroups", + "dax:describeParameters", + "dax:describeSubnetGroups", + "detective:getMembers", + "detective:listGraphs", + "detective:listInvitations", + "detective:listMembers", + "devicefarm:getAccountSettings", + "devicefarm:getDevice", + "devicefarm:getDevicePool", + "devicefarm:getDevicePoolCompatibility", + "devicefarm:getJob", + "devicefarm:getProject", + "devicefarm:getRemoteAccessSession", + "devicefarm:getRun", + "devicefarm:getSuite", + "devicefarm:getTest", + "devicefarm:getTestGridProject", + "devicefarm:getTestGridSession", + "devicefarm:getUpload", + "devicefarm:listArtifacts", + "devicefarm:listDevicePools", + "devicefarm:listDevices", + "devicefarm:listJobs", + "devicefarm:listProjects", + "devicefarm:listRemoteAccessSessions", + "devicefarm:listRuns", + "devicefarm:listSamples", + "devicefarm:listSuites", + "devicefarm:listTestGridProjects", + "devicefarm:listTestGridSessionActions", + "devicefarm:listTestGridSessionArtifacts", + "devicefarm:listTestGridSessions", + "devicefarm:listTests", + "devicefarm:listUniqueProblems", + "devicefarm:listUploads", + "directconnect:describeConnections", + "directconnect:describeConnectionsOnInterconnect", + "directconnect:describeInterconnects", + "directconnect:describeLocations", + "directconnect:describeVirtualGateways", + "directconnect:describeVirtualInterfaces", + "dlm:getLifecyclePolicies", + "dlm:getLifecyclePolicy", + "dms:describeAccountAttributes", + "dms:describeConnections", + "dms:describeEndpoints", + "dms:describeEndpointTypes", + "dms:describeOrderableReplicationInstances", + "dms:describeRefreshSchemasStatus", + "dms:describeReplicationInstances", + "dms:describeReplicationSubnetGroups", + "ds:describeConditionalForwarders", + "ds:describeDirectories", + "ds:describeEventTopics", + "ds:describeSnapshots", + "ds:describeTrusts", + "ds:getDirectoryLimits", + "ds:getSnapshotLimits", + "ds:listIpRoutes", + "ds:listSchemaExtensions", + "ds:listTagsForResource", + "dynamodb:describeBackup", + "dynamodb:describeContinuousBackups", + "dynamodb:describeGlobalTable", + "dynamodb:describeLimits", + "dynamodb:describeStream", + "dynamodb:describeTable", + "dynamodb:describeTimeToLive", + "dynamodb:listBackups", + "dynamodb:listGlobalTables", + "dynamodb:listStreams", + "dynamodb:listTables", + "dynamodb:listTagsOfResource", + "ec2:acceptReservedInstancesExchangeQuote", + "ec2:cancelReservedInstancesListing", + "ec2:createReservedInstancesListing", + "ec2:describeAccountAttributes", + "ec2:describeAddresses", + "ec2:describeAvailabilityZones", + "ec2:describeBundleTasks", + "ec2:describeByoipCidrs", + "ec2:describeCapacityReservations", + "ec2:describeClassicLinkInstances", + "ec2:describeClientVpnAuthorizationRules", + "ec2:describeClientVpnConnections", + "ec2:describeClientVpnEndpoints", + "ec2:describeClientVpnRoutes", + "ec2:describeClientVpnTargetNetworks", + "ec2:describeCoipPools", + "ec2:describeConversionTasks", + "ec2:describeCustomerGateways", + "ec2:describeDhcpOptions", + "ec2:describeElasticGpus", + "ec2:describeExportImageTasks", + "ec2:describeExportTasks", + "ec2:describeFastSnapshotRestores", + "ec2:describeFleetHistory", + "ec2:describeFleetInstances", + "ec2:describeFleets", + "ec2:describeFlowLogs", + "ec2:describeHostReservationOfferings", + "ec2:describeHostReservations", + "ec2:describeHosts", + "ec2:describeIdentityIdFormat", + "ec2:describeIdFormat", + "ec2:describeImageAttribute", + "ec2:describeImages", + "ec2:describeImportImageTasks", + "ec2:describeImportSnapshotTasks", + "ec2:describeInstanceAttribute", + "ec2:describeInstances", + "ec2:describeInstanceStatus", + "ec2:describeInternetGateways", + "ec2:describeKeyPairs", + "ec2:describeLaunchTemplates", + "ec2:describeLaunchTemplateVersions", + "ec2:describeLocalGatewayRouteTables", + "ec2:describeLocalGatewayRouteTableVirtualInterfaceGroupAssociations", + "ec2:describeLocalGatewayRouteTableVpcAssociations", + "ec2:describeLocalGateways", + "ec2:describeLocalGatewayVirtualInterfaceGroups", + "ec2:describeLocalGatewayVirtualInterfaces", + "ec2:describeMovingAddresses", + "ec2:describeNatGateways", + "ec2:describeNetworkAcls", + "ec2:describeNetworkInterfaceAttribute", + "ec2:describeNetworkInterfaces", + "ec2:describePlacementGroups", + "ec2:describePrefixLists", + "ec2:describePublicIpv4Pools", + "ec2:describeRegions", + "ec2:describeReservedInstances", + "ec2:describeReservedInstancesListings", + "ec2:describeReservedInstancesModifications", + "ec2:describeReservedInstancesOfferings", + "ec2:describeRouteTables", + "ec2:describeScheduledInstances", + "ec2:describeSecurityGroups", + "ec2:describeSnapshotAttribute", + "ec2:describeSnapshots", + "ec2:describeSpotDatafeedSubscription", + "ec2:describeSpotFleetInstances", + "ec2:describeSpotFleetRequestHistory", + "ec2:describeSpotFleetRequests", + "ec2:describeSpotInstanceRequests", + "ec2:describeSpotPriceHistory", + "ec2:describeSubnets", + "ec2:describeTags", + "ec2:describeTrafficMirrorFilters", + "ec2:describeTrafficMirrorSessions", + "ec2:describeTrafficMirrorTargets", + "ec2:describeTransitGatewayAttachments", + "ec2:describeTransitGatewayRouteTables", + "ec2:describeTransitGateways", + "ec2:describeTransitGatewayVpcAttachments", + "ec2:describeVolumeAttribute", + "ec2:describeVolumes", + "ec2:describeVolumesModifications", + "ec2:describeVolumeStatus", + "ec2:describeVpcAttribute", + "ec2:describeVpcClassicLink", + "ec2:describeVpcClassicLinkDnsSupport", + "ec2:describeVpcEndpointConnectionNotifications", + "ec2:describeVpcEndpointConnections", + "ec2:describeVpcEndpoints", + "ec2:describeVpcEndpointServiceConfigurations", + "ec2:describeVpcEndpointServicePermissions", + "ec2:describeVpcEndpointServices", + "ec2:describeVpcPeeringConnections", + "ec2:describeVpcs", + "ec2:describeVpnConnections", + "ec2:describeVpnGateways", + "ec2:getCoipPoolUsage", + "ec2:getConsoleScreenshot", + "ec2:getReservedInstancesExchangeQuote", + "ec2:getTransitGatewayAttachmentPropagations", + "ec2:getTransitGatewayRouteTableAssociations", + "ec2:getTransitGatewayRouteTablePropagations", + "ec2:modifyReservedInstances", + "ec2:purchaseReservedInstancesOffering", + "ec2:searchLocalGatewayRoutes", + "ecr-public:describeImages", + "ecr-public:describeImageTags", + "ecr-public:describeRegistries", + "ecr-public:describeRepositories", + "ecr-public:getRegistryCatalogData", + "ecr-public:getRepositoryCatalogData", + "ecr-public:getRepositoryPolicy", + "ecr-public:listTagsForResource", + "ecr:batchCheckLayerAvailability", + "ecr:describeImages", + "ecr:describeImageScanFindings", + "ecr:describeRegistry", + "ecr:describeRepositories", + "ecr:getLifecyclePolicy", + "ecr:getRegistryPolicy", + "ecr:getRepositoryPolicy", + "ecr:listImages", + "ecr:listTagsForResource", + "ecs:describeCapacityProviders", + "ecs:describeClusters", + "ecs:describeContainerInstances", + "ecs:describeServices", + "ecs:describeTaskDefinition", + "ecs:describeTasks", + "ecs:describeTaskSets", + "ecs:listAccountSettings", + "ecs:listAttributes", + "ecs:listClusters", + "ecs:listContainerInstances", + "ecs:listServices", + "ecs:listTagsForResource", + "ecs:listTaskDefinitionFamilies", + "ecs:listTaskDefinitions", + "ecs:listTasks", + "eks:describeCluster", + "eks:describeFargateProfile", + "eks:describeNodegroup", + "eks:describeUpdate", + "eks:listClusters", + "eks:listFargateProfiles", + "eks:listNodegroups", + "eks:listUpdates", + "elasticache:describeCacheClusters", + "elasticache:describeCacheEngineVersions", + "elasticache:describeCacheParameterGroups", + "elasticache:describeCacheParameters", + "elasticache:describeCacheSecurityGroups", + "elasticache:describeCacheSubnetGroups", + "elasticache:describeEngineDefaultParameters", + "elasticache:describeEvents", + "elasticache:describeReplicationGroups", + "elasticache:describeReservedCacheNodes", + "elasticache:describeReservedCacheNodesOfferings", + "elasticache:describeSnapshots", + "elasticache:listAllowedNodeTypeModifications", + "elasticache:listTagsForResource", + "elasticbeanstalk:checkDNSAvailability", + "elasticbeanstalk:describeApplications", + "elasticbeanstalk:describeApplicationVersions", + "elasticbeanstalk:describeConfigurationOptions", + "elasticbeanstalk:describeConfigurationSettings", + "elasticbeanstalk:describeEnvironmentHealth", + "elasticbeanstalk:describeEnvironmentManagedActionHistory", + "elasticbeanstalk:describeEnvironmentManagedActions", + "elasticbeanstalk:describeEnvironmentResources", + "elasticbeanstalk:describeEnvironments", + "elasticbeanstalk:describeEvents", + "elasticbeanstalk:describeInstancesHealth", + "elasticbeanstalk:describePlatformVersion", + "elasticbeanstalk:listAvailableSolutionStacks", + "elasticbeanstalk:listPlatformVersions", + "elasticbeanstalk:validateConfigurationSettings", + "elasticfilesystem:describeAccessPoints", + "elasticfilesystem:describeFileSystemPolicy", + "elasticfilesystem:describeFileSystems", + "elasticfilesystem:describeLifecycleConfiguration", + "elasticfilesystem:describeMountTargets", + "elasticfilesystem:describeMountTargetSecurityGroups", + "elasticfilesystem:describeTags", + "elasticfilesystem:listTagsForResource", + "elasticloadbalancing:describeInstanceHealth", + "elasticloadbalancing:describeListenerCertificates", + "elasticloadbalancing:describeListeners", + "elasticloadbalancing:describeLoadBalancerAttributes", + "elasticloadbalancing:describeLoadBalancerPolicies", + "elasticloadbalancing:describeLoadBalancerPolicyTypes", + "elasticloadbalancing:describeLoadBalancers", + "elasticloadbalancing:describeRules", + "elasticloadbalancing:describeSSLPolicies", + "elasticloadbalancing:describeTags", + "elasticloadbalancing:describeTargetGroupAttributes", + "elasticloadbalancing:describeTargetGroups", + "elasticloadbalancing:describeTargetHealth", + "elasticmapreduce:describeCluster", + "elasticmapreduce:describeSecurityConfiguration", + "elasticmapreduce:describeStep", + "elasticmapreduce:listBootstrapActions", + "elasticmapreduce:listClusters", + "elasticmapreduce:listInstanceGroups", + "elasticmapreduce:listInstances", + "elasticmapreduce:listSecurityConfigurations", + "elasticmapreduce:listSteps", + "elastictranscoder:listJobsByPipeline", + "elastictranscoder:listJobsByStatus", + "elastictranscoder:listPipelines", + "elastictranscoder:listPresets", + "elastictranscoder:readPipeline", + "elastictranscoder:readPreset", + "es:describeElasticsearchDomain", + "es:describeElasticsearchDomainConfig", + "es:describeElasticsearchDomains", + "es:listDomainNames", + "es:listTags", + "events:describeApiDestination", + "events:describeEventBus", + "events:describeEventSource", + "events:describePartnerEventSource", + "events:describeRule", + "events:listApiDestinations", + "events:listConnections", + "events:listEventBuses", + "events:listEventSources", + "events:listPartnerEventSourceAccounts", + "events:listPartnerEventSources", + "events:listRuleNamesByTarget", + "events:listRules", + "events:listTargetsByRule", + "events:testEventPattern", + "firehose:describeDeliveryStream", + "firehose:listDeliveryStreams", + "fms:getAdminAccount", + "fms:getComplianceDetail", + "fms:getNotificationChannel", + "fms:getPolicy", + "fms:getProtectionStatus", + "fms:listComplianceStatus", + "fms:listMemberAccounts", + "fms:listPolicies", + "forecast:describeDataset", + "forecast:describeDatasetGroup", + "forecast:describeDatasetImportJob", + "forecast:describeForecast", + "forecast:describeForecastExportJob", + "forecast:describePredictor", + "forecast:getAccuracyMetrics", + "forecast:listDatasetGroups", + "forecast:listDatasetImportJobs", + "forecast:listDatasets", + "forecast:listForecastExportJobs", + "forecast:listForecasts", + "forecast:listPredictors", + "fsx:describeBackups", + "fsx:describeDataRepositoryTasks", + "fsx:describeFileSystems", + "fsx:listTagsForResource", + "glacier:describeJob", + "glacier:describeVault", + "glacier:getDataRetrievalPolicy", + "glacier:getVaultAccessPolicy", + "glacier:getVaultLock", + "glacier:getVaultNotifications", + "glacier:listJobs", + "glacier:listTagsForVault", + "glacier:listVaults", + "globalaccelerator:describeAccelerator", + "globalaccelerator:describeAcceleratorAttributes", + "globalaccelerator:describeEndpointGroup", + "globalaccelerator:describeListener", + "globalaccelerator:listAccelerators", + "globalaccelerator:listEndpointGroups", + "globalaccelerator:listListeners", + "glue:batchGetPartition", + "glue:checkSchemaVersionValidity", + "glue:getCatalogImportStatus", + "glue:getClassifier", + "glue:getClassifiers", + "glue:getCrawler", + "glue:getCrawlerMetrics", + "glue:getCrawlers", + "glue:getDatabase", + "glue:getDatabases", + "glue:getDataflowGraph", + "glue:getDevEndpoint", + "glue:getDevEndpoints", + "glue:getJob", + "glue:getJobRun", + "glue:getJobRuns", + "glue:getJobs", + "glue:getMapping", + "glue:getPartition", + "glue:getPartitions", + "glue:getRegistry", + "glue:getSchema", + "glue:getSchemaByDefinition", + "glue:getSchemaVersion", + "glue:getSchemaVersionsDiff", + "glue:getTable", + "glue:getTables", + "glue:getTableVersions", + "glue:getTrigger", + "glue:getTriggers", + "glue:getUserDefinedFunction", + "glue:getUserDefinedFunctions", + "glue:listRegistries", + "glue:listSchemas", + "glue:listSchemaVersions", + "glue:querySchemaVersionMetadata", + "greengrass:getConnectivityInfo", + "greengrass:getCoreDefinition", + "greengrass:getCoreDefinitionVersion", + "greengrass:getDeploymentStatus", + "greengrass:getDeviceDefinition", + "greengrass:getDeviceDefinitionVersion", + "greengrass:getFunctionDefinition", + "greengrass:getFunctionDefinitionVersion", + "greengrass:getGroup", + "greengrass:getGroupCertificateAuthority", + "greengrass:getGroupVersion", + "greengrass:getLoggerDefinition", + "greengrass:getLoggerDefinitionVersion", + "greengrass:getResourceDefinitionVersion", + "greengrass:getServiceRoleForAccount", + "greengrass:getSubscriptionDefinition", + "greengrass:getSubscriptionDefinitionVersion", + "greengrass:listCoreDefinitions", + "greengrass:listCoreDefinitionVersions", + "greengrass:listDeployments", + "greengrass:listDeviceDefinitions", + "greengrass:listDeviceDefinitionVersions", + "greengrass:listFunctionDefinitions", + "greengrass:listFunctionDefinitionVersions", + "greengrass:listGroups", + "greengrass:listGroupVersions", + "greengrass:listLoggerDefinitions", + "greengrass:listLoggerDefinitionVersions", + "greengrass:listResourceDefinitions", + "greengrass:listResourceDefinitionVersions", + "greengrass:listSubscriptionDefinitions", + "greengrass:listSubscriptionDefinitionVersions", + "guardduty:getDetector", + "guardduty:getFindings", + "guardduty:getFindingsStatistics", + "guardduty:getInvitationsCount", + "guardduty:getIPSet", + "guardduty:getMasterAccount", + "guardduty:getMembers", + "guardduty:getThreatIntelSet", + "guardduty:listDetectors", + "guardduty:listFindings", + "guardduty:listInvitations", + "guardduty:listIPSets", + "guardduty:listMembers", + "guardduty:listThreatIntelSets", + "health:describeAffectedAccountsForOrganization", + "health:describeAffectedEntities", + "health:describeAffectedEntitiesForOrganization", + "health:describeEntityAggregates", + "health:describeEventAggregates", + "health:describeEventDetails", + "health:describeEventDetailsForOrganization", + "health:describeEvents", + "health:describeEventsForOrganization", + "health:describeEventTypes", + "health:describeHealthServiceStatusForOrganization", + "iam:getAccessKeyLastUsed", + "iam:getAccountAuthorizationDetails", + "iam:getAccountPasswordPolicy", + "iam:getAccountSummary", + "iam:getContextKeysForCustomPolicy", + "iam:getContextKeysForPrincipalPolicy", + "iam:getCredentialReport", + "iam:getGroup", + "iam:getGroupPolicy", + "iam:getInstanceProfile", + "iam:getLoginProfile", + "iam:getOpenIDConnectProvider", + "iam:getPolicy", + "iam:getPolicyVersion", + "iam:getRole", + "iam:getRolePolicy", + "iam:getSAMLProvider", + "iam:getServerCertificate", + "iam:getSSHPublicKey", + "iam:getUser", + "iam:getUserPolicy", + "iam:listAccessKeys", + "iam:listAccountAliases", + "iam:listAttachedGroupPolicies", + "iam:listAttachedRolePolicies", + "iam:listAttachedUserPolicies", + "iam:listEntitiesForPolicy", + "iam:listGroupPolicies", + "iam:listGroups", + "iam:listGroupsForUser", + "iam:listInstanceProfiles", + "iam:listInstanceProfilesForRole", + "iam:listMFADevices", + "iam:listOpenIDConnectProviders", + "iam:listPolicies", + "iam:listPolicyVersions", + "iam:listRolePolicies", + "iam:listRoles", + "iam:listSAMLProviders", + "iam:listServerCertificates", + "iam:listSigningCertificates", + "iam:listSSHPublicKeys", + "iam:listUserPolicies", + "iam:listUsers", + "iam:listVirtualMFADevices", + "iam:simulateCustomPolicy", + "iam:simulatePrincipalPolicy", + "imagebuilder:getComponent", + "imagebuilder:getComponentPolicy", + "imagebuilder:getContainerRecipe", + "imagebuilder:getDistributionConfiguration", + "imagebuilder:getImage", + "imagebuilder:getImagePipeline", + "imagebuilder:getImagePolicy", + "imagebuilder:getImageRecipe", + "imagebuilder:getImageRecipePolicy", + "imagebuilder:getInfrastructureConfiguration", + "imagebuilder:listComponentBuildVersions", + "imagebuilder:listComponents", + "imagebuilder:listContainerRecipes", + "imagebuilder:listDistributionConfigurations", + "imagebuilder:listImageBuildVersions", + "imagebuilder:listImagePipelineImages", + "imagebuilder:listImagePipelines", + "imagebuilder:listImageRecipes", + "imagebuilder:listImages", + "imagebuilder:listInfrastructureConfigurations", + "imagebuilder:listTagsForResource", + "importexport:getStatus", + "importexport:listJobs", + "inspector:describeAssessmentRuns", + "inspector:describeAssessmentTargets", + "inspector:describeAssessmentTemplates", + "inspector:describeCrossAccountAccessRole", + "inspector:describeResourceGroups", + "inspector:describeRulesPackages", + "inspector:getTelemetryMetadata", + "inspector:listAssessmentRunAgents", + "inspector:listAssessmentRuns", + "inspector:listAssessmentTargets", + "inspector:listAssessmentTemplates", + "inspector:listEventSubscriptions", + "inspector:listRulesPackages", + "inspector:listTagsForResource", + "iot:describeAuthorizer", + "iot:describeCACertificate", + "iot:describeCertificate", + "iot:describeDefaultAuthorizer", + "iot:describeEndpoint", + "iot:describeIndex", + "iot:describeJobExecution", + "iot:describeThing", + "iot:describeThingGroup", + "iot:describeTunnel", + "iot:getEffectivePolicies", + "iot:getIndexingConfiguration", + "iot:getLoggingOptions", + "iot:getPolicy", + "iot:getPolicyVersion", + "iot:getTopicRule", + "iot:getV2LoggingOptions", + "iot:listAttachedPolicies", + "iot:listAuthorizers", + "iot:listCACertificates", + "iot:listCertificates", + "iot:listCertificatesByCA", + "iot:listJobExecutionsForJob", + "iot:listJobExecutionsForThing", + "iot:listJobs", + "iot:listOutgoingCertificates", + "iot:listPolicies", + "iot:listPolicyPrincipals", + "iot:listPolicyVersions", + "iot:listPrincipalPolicies", + "iot:listPrincipalThings", + "iot:listRoleAliases", + "iot:listTargetsForPolicy", + "iot:listThingGroups", + "iot:listThingGroupsForThing", + "iot:listThingPrincipals", + "iot:listThingRegistrationTasks", + "iot:listThings", + "iot:listThingTypes", + "iot:listTopicRules", + "iot:listTunnels", + "iot:listV2LoggingLevels", + "iotevents:describeDetector", + "iotevents:describeDetectorModel", + "iotevents:describeInput", + "iotevents:describeLoggingOptions", + "iotevents:listDetectorModels", + "iotevents:listDetectorModelVersions", + "iotevents:listDetectors", + "iotevents:listInputs", + "iotsitewise:describeAccessPolicy", + "iotsitewise:describeAsset", + "iotsitewise:describeAssetModel", + "iotsitewise:describeAssetProperty", + "iotsitewise:describeDashboard", + "iotsitewise:describeGateway", + "iotsitewise:describeGatewayCapabilityConfiguration", + "iotsitewise:describeLoggingOptions", + "iotsitewise:describePortal", + "iotsitewise:describeProject", + "iotsitewise:listAccessPolicies", + "iotsitewise:listAssetModels", + "iotsitewise:listAssets", + "iotsitewise:listAssociatedAssets", + "iotsitewise:listDashboards", + "iotsitewise:listGateways", + "iotsitewise:listPortals", + "iotsitewise:listProjectAssets", + "iotsitewise:listProjects", + "iotwireless:getDestination", + "iotwireless:getDeviceProfile", + "iotwireless:getPartnerAccount", + "iotwireless:getServiceEndpoint", + "iotwireless:getServiceProfile", + "iotwireless:getWirelessDevice", + "iotwireless:getWirelessDeviceStatistics", + "iotwireless:getWirelessGateway", + "iotwireless:getWirelessGatewayCertificate", + "iotwireless:getWirelessGatewayFirmwareInformation", + "iotwireless:getWirelessGatewayStatistics", + "iotwireless:getWirelessGatewayTask", + "iotwireless:getWirelessGatewayTaskDefinition", + "iotwireless:listDestinations", + "iotwireless:listDeviceProfiles", + "iotwireless:listPartnerAccounts", + "iotwireless:listServiceProfiles", + "iotwireless:listTagsForResource", + "iotwireless:listWirelessDevices", + "iotwireless:listWirelessGateways", + "iotwireless:listWirelessGatewayTaskDefinitions", + "kafka:describeCluster", + "kafka:getBootstrapBrokers", + "kafka:listClusters", + "kafka:listNodes", + "kendra:describeDataSource", + "kendra:describeFaq", + "kendra:describeIndex", + "kendra:listDataSources", + "kendra:listFaqs", + "kendra:listIndices", + "kinesis:describeStream", + "kinesis:listStreams", + "kinesis:listTagsForStream", + "kinesisanalytics:describeApplication", + "kinesisanalytics:describeApplicationSnapshot", + "kinesisanalytics:listApplications", + "kinesisanalytics:listApplicationSnapshots", + "kms:describeKey", + "kms:getKeyPolicy", + "kms:getKeyRotationStatus", + "kms:listAliases", + "kms:listGrants", + "kms:listKeyPolicies", + "kms:listKeys", + "kms:listResourceTags", + "kms:listRetirableGrants", + "lambda:getAccountSettings", + "lambda:getAlias", + "lambda:getCodeSigningConfig", + "lambda:getEventSourceMapping", + "lambda:getFunction", + "lambda:getFunctionCodeSigningConfig", + "lambda:getFunctionConcurrency", + "lambda:getFunctionConfiguration", + "lambda:getFunctionEventInvokeConfig", + "lambda:getLayerVersion", + "lambda:getLayerVersionPolicy", + "lambda:getPolicy", + "lambda:getProvisionedConcurrencyConfig", + "lambda:listAliases", + "lambda:listCodeSigningConfigs", + "lambda:listEventSourceMappings", + "lambda:listFunctionEventInvokeConfigs", + "lambda:listFunctions", + "lambda:listFunctionsByCodeSigningConfig", + "lambda:listLayers", + "lambda:listLayerVersions", + "lambda:listProvisionedConcurrencyConfigs", + "lambda:listVersionsByFunction", + "launchwizard:describeProvisionedApp", + "launchwizard:describeProvisioningEvents", + "launchwizard:listProvisionedApps", + "lex:getBot", + "lex:getBotAlias", + "lex:getBotAliases", + "lex:getBotChannelAssociation", + "lex:getBotChannelAssociations", + "lex:getBots", + "lex:getBotVersions", + "lex:getBuiltinIntent", + "lex:getBuiltinIntents", + "lex:getBuiltinSlotTypes", + "lex:getIntent", + "lex:getIntents", + "lex:getIntentVersions", + "lex:getSlotType", + "lex:getSlotTypes", + "lex:getSlotTypeVersions", + "license-manager:getLicenseConfiguration", + "license-manager:getServiceSettings", + "license-manager:listAssociationsForLicenseConfiguration", + "license-manager:listFailuresForLicenseConfigurationOperations", + "license-manager:listLicenseConfigurations", + "license-manager:listLicenseSpecificationsForResource", + "license-manager:listResourceInventory", + "license-manager:listUsageForLicenseConfiguration", + "lightsail:getActiveNames", + "lightsail:getAlarms", + "lightsail:getAutoSnapshots", + "lightsail:getBlueprints", + "lightsail:getBundles", + "lightsail:getCertificates", + "lightsail:getContainerImages", + "lightsail:getContainerServiceDeployments", + "lightsail:getContainerServices", + "lightsail:getDisk", + "lightsail:getDisks", + "lightsail:getDiskSnapshot", + "lightsail:getDiskSnapshots", + "lightsail:getDistributions", + "lightsail:getDomain", + "lightsail:getDomains", + "lightsail:getExportSnapshotRecords", + "lightsail:getInstance", + "lightsail:getInstanceMetricData", + "lightsail:getInstancePortStates", + "lightsail:getInstances", + "lightsail:getInstanceSnapshot", + "lightsail:getInstanceSnapshots", + "lightsail:getInstanceState", + "lightsail:getKeyPair", + "lightsail:getKeyPairs", + "lightsail:getLoadBalancer", + "lightsail:getLoadBalancers", + "lightsail:getLoadBalancerTlsCertificates", + "lightsail:getOperation", + "lightsail:getOperations", + "lightsail:getOperationsForResource", + "lightsail:getRegions", + "lightsail:getRelationalDatabase", + "lightsail:getRelationalDatabases", + "lightsail:getRelationalDatabaseSnapshot", + "lightsail:getRelationalDatabaseSnapshots", + "lightsail:getStaticIp", + "lightsail:getStaticIps", + "logs:describeDestinations", + "logs:describeExportTasks", + "logs:describeLogGroups", + "logs:describeLogStreams", + "logs:describeMetricFilters", + "logs:describeQueries", + "logs:describeSubscriptionFilters", + "logs:testMetricFilter", + "lookoutmetrics:describeAlert", + "lookoutmetrics:describeAnomalyDetectionExecutions", + "lookoutmetrics:describeAnomalyDetector", + "lookoutmetrics:describeMetricSet", + "lookoutmetrics:getAnomalyGroup", + "lookoutmetrics:getDataQualityMetrics", + "lookoutmetrics:getFeedback", + "lookoutmetrics:getSampleData", + "lookoutmetrics:listAlerts", + "lookoutmetrics:listAnomalyDetectors", + "lookoutmetrics:listAnomalyGroupSummaries", + "lookoutmetrics:listAnomalyGroupTimeSeries", + "lookoutmetrics:listMetricSets", + "lookoutmetrics:listTagsForResource", + "machinelearning:describeBatchPredictions", + "machinelearning:describeDataSources", + "machinelearning:describeEvaluations", + "machinelearning:describeMLModels", + "machinelearning:getBatchPrediction", + "machinelearning:getDataSource", + "machinelearning:getEvaluation", + "machinelearning:getMLModel", + "managedblockchain:getMember", + "managedblockchain:getNetwork", + "managedblockchain:getNode", + "managedblockchain:listMembers", + "managedblockchain:listNetworks", + "managedblockchain:listNodes", + "mediaconnect:describeFlow", + "mediaconnect:listEntitlements", + "mediaconnect:listFlows", + "mediaconvert:describeEndpoints", + "mediaconvert:getJob", + "mediaconvert:getJobTemplate", + "mediaconvert:getPreset", + "mediaconvert:getQueue", + "mediaconvert:listJobs", + "mediaconvert:listJobTemplates", + "medialive:describeChannel", + "medialive:describeInput", + "medialive:describeInputDevice", + "medialive:describeInputSecurityGroup", + "medialive:describeMultiplex", + "medialive:describeOffering", + "medialive:describeReservation", + "medialive:describeSchedule", + "medialive:listChannels", + "medialive:listInputDevices", + "medialive:listInputs", + "medialive:listInputSecurityGroups", + "medialive:listMultiplexes", + "medialive:listOfferings", + "medialive:listReservations", + "mediapackage:describeChannel", + "mediapackage:describeOriginEndpoint", + "mediapackage:listChannels", + "mediapackage:listOriginEndpoints", + "mediastore:describeContainer", + "mediastore:describeObject", + "mediastore:getContainerPolicy", + "mediastore:getCorsPolicy", + "mediastore:listContainers", + "mediastore:listItems", + "mediatailor:getPlaybackConfiguration", + "mediatailor:listPlaybackConfigurations", + "mgn:describeJobLogItems", + "mgn:describeJobs", + "mgn:describeReplicationConfigurationTemplates", + "mgn:describeSourceServers", + "mgn:getLaunchConfiguration", + "mgn:getReplicationConfiguration", + "mobiletargeting:getAdmChannel", + "mobiletargeting:getApnsChannel", + "mobiletargeting:getApnsSandboxChannel", + "mobiletargeting:getApnsVoipChannel", + "mobiletargeting:getApnsVoipSandboxChannel", + "mobiletargeting:getApp", + "mobiletargeting:getApplicationSettings", + "mobiletargeting:getApps", + "mobiletargeting:getBaiduChannel", + "mobiletargeting:getCampaign", + "mobiletargeting:getCampaignActivities", + "mobiletargeting:getCampaigns", + "mobiletargeting:getCampaignVersion", + "mobiletargeting:getCampaignVersions", + "mobiletargeting:getEmailChannel", + "mobiletargeting:getEndpoint", + "mobiletargeting:getEventStream", + "mobiletargeting:getExportJob", + "mobiletargeting:getExportJobs", + "mobiletargeting:getGcmChannel", + "mobiletargeting:getImportJob", + "mobiletargeting:getImportJobs", + "mobiletargeting:getSegment", + "mobiletargeting:getSegmentImportJobs", + "mobiletargeting:getSegments", + "mobiletargeting:getSegmentVersion", + "mobiletargeting:getSegmentVersions", + "mobiletargeting:getSmsChannel", + "mq:describeBroker", + "mq:describeConfiguration", + "mq:describeConfigurationRevision", + "mq:describeUser", + "mq:listBrokers", + "mq:listConfigurationRevisions", + "mq:listConfigurations", + "mq:listUsers", + "network-firewall:describeFirewall", + "network-firewall:describeFirewallPolicy", + "network-firewall:describeLoggingConfiguration", + "network-firewall:describeRuleGroup", + "network-firewall:listFirewallPolicies", + "network-firewall:listFirewalls", + "network-firewall:listRuleGroups", + "networkmanager:describeGlobalNetworks", + "networkmanager:getCustomerGatewayAssociations", + "networkmanager:getDevices", + "networkmanager:getLinkAssociations", + "networkmanager:getLinks", + "networkmanager:getSites", + "networkmanager:getTransitGatewayRegistrations", + "opsworks-cm:describeAccountAttributes", + "opsworks-cm:describeBackups", + "opsworks-cm:describeEvents", + "opsworks-cm:describeNodeAssociationStatus", + "opsworks-cm:describeServers", + "opsworks:describeAgentVersions", + "opsworks:describeApps", + "opsworks:describeCommands", + "opsworks:describeDeployments", + "opsworks:describeEcsClusters", + "opsworks:describeElasticIps", + "opsworks:describeElasticLoadBalancers", + "opsworks:describeInstances", + "opsworks:describeLayers", + "opsworks:describeLoadBasedAutoScaling", + "opsworks:describeMyUserProfile", + "opsworks:describePermissions", + "opsworks:describeRaidArrays", + "opsworks:describeRdsDbInstances", + "opsworks:describeServiceErrors", + "opsworks:describeStackProvisioningParameters", + "opsworks:describeStacks", + "opsworks:describeStackSummary", + "opsworks:describeTimeBasedAutoScaling", + "opsworks:describeUserProfiles", + "opsworks:describeVolumes", + "opsworks:getHostnameSuggestion", + "organizations:listAccounts", + "organizations:listTagsForResource", + "outposts:getOutpost", + "outposts:getOutpostInstanceTypes", + "outposts:listOutposts", + "outposts:listSites", + "personalize:describeAlgorithm", + "personalize:describeCampaign", + "personalize:describeDataset", + "personalize:describeDatasetGroup", + "personalize:describeDatasetImportJob", + "personalize:describeEventTracker", + "personalize:describeFeatureTransformation", + "personalize:describeRecipe", + "personalize:describeSchema", + "personalize:describeSolution", + "personalize:describeSolutionVersion", + "personalize:listCampaigns", + "personalize:listDatasetGroups", + "personalize:listDatasetImportJobs", + "personalize:listDatasets", + "personalize:listEventTrackers", + "personalize:listRecipes", + "personalize:listSchemas", + "personalize:listSolutions", + "personalize:listSolutionVersions", + "polly:describeVoices", + "polly:getLexicon", + "polly:listLexicons", + "pricing:describeServices", + "pricing:getAttributeValues", + "pricing:getProducts", + "quicksight:describeDashboard", + "quicksight:describeDashboardPermissions", + "quicksight:describeGroup", + "quicksight:describeIAMPolicyAssignment", + "quicksight:describeTemplate", + "quicksight:describeTemplateAlias", + "quicksight:describeTemplatePermissions", + "quicksight:describeUser", + "quicksight:listDashboards", + "quicksight:listGroupMemberships", + "quicksight:listGroups", + "quicksight:listIAMPolicyAssignments", + "quicksight:listIAMPolicyAssignmentsForUser", + "quicksight:listTemplateAliases", + "quicksight:listTemplates", + "quicksight:listTemplateVersions", + "quicksight:listUserGroups", + "quicksight:listUsers", + "ram:getPermission", + "ram:getResourceShareAssociations", + "ram:getResourceShareInvitations", + "ram:getResourceShares", + "ram:listPendingInvitationResources", + "ram:listPrincipals", + "ram:listResources", + "ram:listResourceSharePermissions", + "rds:describeAccountAttributes", + "rds:describeCertificates", + "rds:describeDBClusterParameterGroups", + "rds:describeDBClusterParameters", + "rds:describeDBClusters", + "rds:describeDBClusterSnapshots", + "rds:describeDBEngineVersions", + "rds:describeDBInstances", + "rds:describeDBParameterGroups", + "rds:describeDBParameters", + "rds:describeDBSecurityGroups", + "rds:describeDBSnapshotAttributes", + "rds:describeDBSnapshots", + "rds:describeDBSubnetGroups", + "rds:describeEngineDefaultClusterParameters", + "rds:describeEngineDefaultParameters", + "rds:describeEventCategories", + "rds:describeEvents", + "rds:describeEventSubscriptions", + "rds:describeExportTasks", + "rds:describeOptionGroupOptions", + "rds:describeOptionGroups", + "rds:describeOrderableDBInstanceOptions", + "rds:describePendingMaintenanceActions", + "rds:describeReservedDBInstances", + "rds:describeReservedDBInstancesOfferings", + "rds:listTagsForResource", + "redshift-data:describeStatement", + "redshift-data:listStatements", + "redshift:describeClusterParameterGroups", + "redshift:describeClusterParameters", + "redshift:describeClusters", + "redshift:describeClusterSecurityGroups", + "redshift:describeClusterSnapshots", + "redshift:describeClusterSubnetGroups", + "redshift:describeClusterVersions", + "redshift:describeDefaultClusterParameters", + "redshift:describeEventCategories", + "redshift:describeEvents", + "redshift:describeEventSubscriptions", + "redshift:describeHsmClientCertificates", + "redshift:describeHsmConfigurations", + "redshift:describeLoggingStatus", + "redshift:describeOrderableClusterOptions", + "redshift:describeReservedNodeOfferings", + "redshift:describeReservedNodes", + "redshift:describeResize", + "redshift:describeSnapshotCopyGrants", + "redshift:describeStorage", + "redshift:describeTableRestoreStatus", + "redshift:describeTags", + "rekognition:listCollections", + "rekognition:listFaces", + "resource-groups:getGroup", + "resource-groups:getGroupQuery", + "resource-groups:getTags", + "resource-groups:listGroupResources", + "resource-groups:listGroups", + "resource-groups:searchResources", + "robomaker:batchDescribeSimulationJob", + "robomaker:describeDeploymentJob", + "robomaker:describeFleet", + "robomaker:describeRobot", + "robomaker:describeRobotApplication", + "robomaker:describeSimulationApplication", + "robomaker:describeSimulationJob", + "robomaker:listDeploymentJobs", + "robomaker:listFleets", + "robomaker:listRobotApplications", + "robomaker:listRobots", + "robomaker:listSimulationApplications", + "robomaker:listSimulationJobs", + "route53-recovery-readiness:getCell", + "route53-recovery-readiness:getCellReadinessSummary", + "route53-recovery-readiness:getReadinessCheck", + "route53-recovery-readiness:getReadinessCheckResourceStatus", + "route53-recovery-readiness:getReadinessCheckStatus", + "route53-recovery-readiness:getRecoveryGroup", + "route53-recovery-readiness:getRecoveryGroupReadinessSummary", + "route53-recovery-readiness:listCells", + "route53-recovery-readiness:listReadinessChecks", + "route53-recovery-readiness:listRecoveryGroups", + "route53-recovery-readiness:listResourceSets", + "route53:getChange", + "route53:getCheckerIpRanges", + "route53:getGeoLocation", + "route53:getHealthCheck", + "route53:getHealthCheckCount", + "route53:getHealthCheckLastFailureReason", + "route53:getHealthCheckStatus", + "route53:getHostedZone", + "route53:getHostedZoneCount", + "route53:getReusableDelegationSet", + "route53:getTrafficPolicy", + "route53:getTrafficPolicyInstance", + "route53:getTrafficPolicyInstanceCount", + "route53:listGeoLocations", + "route53:listHealthChecks", + "route53:listHostedZones", + "route53:listHostedZonesByName", + "route53:listResourceRecordSets", + "route53:listReusableDelegationSets", + "route53:listTagsForResource", + "route53:listTagsForResources", + "route53:listTrafficPolicies", + "route53:listTrafficPolicyInstances", + "route53:listTrafficPolicyInstancesByHostedZone", + "route53:listTrafficPolicyInstancesByPolicy", + "route53:listTrafficPolicyVersions", + "route53domains:checkDomainAvailability", + "route53domains:getContactReachabilityStatus", + "route53domains:getDomainDetail", + "route53domains:getOperationDetail", + "route53domains:listDomains", + "route53domains:listOperations", + "route53domains:listTagsForDomain", + "route53domains:viewBilling", + "route53resolver:getFirewallConfig", + "route53resolver:getFirewallDomainList", + "route53resolver:getFirewallRuleGroup", + "route53resolver:getFirewallRuleGroupAssociation", + "route53resolver:getResolverDnssecConfig", + "route53resolver:getResolverRulePolicy", + "route53resolver:listFirewallConfigs", + "route53resolver:listFirewallDomainLists", + "route53resolver:listFirewallDomains", + "route53resolver:listFirewallRuleGroupAssociations", + "route53resolver:listFirewallRuleGroups", + "route53resolver:listFirewallRules", + "route53resolver:listResolverDnssecConfigs", + "route53resolver:listResolverEndpointIpAddresses", + "route53resolver:listResolverEndpoints", + "route53resolver:listResolverRuleAssociations", + "route53resolver:listResolverRules", + "route53resolver:listTagsForResource", + "s3:getAccelerateConfiguration", + "s3:getAccessPointConfigurationForObjectLambda", + "s3:getAccessPointForObjectLambda", + "s3:getAccessPointPolicyStatusForObjectLambda", + "s3:getAnalyticsConfiguration", + "s3:getBucketAcl", + "s3:getBucketCORS", + "s3:getBucketLocation", + "s3:getBucketLogging", + "s3:getBucketNotification", + "s3:getBucketPolicy", + "s3:getBucketRequestPayment", + "s3:getBucketTagging", + "s3:getBucketVersioning", + "s3:getBucketWebsite", + "s3:getEncryptionConfiguration", + "s3:getInventoryConfiguration", + "s3:getLifecycleConfiguration", + "s3:getMetricsConfiguration", + "s3:getReplicationConfiguration", + "s3:listAccessPointsForObjectLambda", + "s3:listAllMyBuckets", + "s3:listBucket", + "s3:listBucketMultipartUploads", + "sagemaker:describeAction", + "sagemaker:describeAlgorithm", + "sagemaker:describeApp", + "sagemaker:describeArtifact", + "sagemaker:describeAutoMLJob", + "sagemaker:describeCompilationJob", + "sagemaker:describeContext", + "sagemaker:describeDataQualityJobDefinition", + "sagemaker:describeDevice", + "sagemaker:describeDeviceFleet", + "sagemaker:describeDomain", + "sagemaker:describeEdgePackagingJob", + "sagemaker:describeEndpoint", + "sagemaker:describeEndpointConfig", + "sagemaker:describeExperiment", + "sagemaker:describeFeatureGroup", + "sagemaker:describeHumanTaskUi", + "sagemaker:describeHyperParameterTuningJob", + "sagemaker:describeImage", + "sagemaker:describeImageVersion", + "sagemaker:describeLabelingJob", + "sagemaker:describeModel", + "sagemaker:describeModelBiasJobDefinition", + "sagemaker:describeModelExplainabilityJobDefinition", + "sagemaker:describeModelPackage", + "sagemaker:describeModelPackageGroup", + "sagemaker:describeModelQualityJobDefinition", + "sagemaker:describeMonitoringSchedule", + "sagemaker:describeNotebookInstance", + "sagemaker:describeNotebookInstanceLifecycleConfig", + "sagemaker:describePipeline", + "sagemaker:describePipelineDefinitionForExecution", + "sagemaker:describePipelineExecution", + "sagemaker:describeProcessingJob", + "sagemaker:describeProject", + "sagemaker:describeSubscribedWorkteam", + "sagemaker:describeTrainingJob", + "sagemaker:describeTransformJob", + "sagemaker:describeTrial", + "sagemaker:describeTrialComponent", + "sagemaker:describeUserProfile", + "sagemaker:describeWorkteam", + "sagemaker:listActions", + "sagemaker:listAlgorithms", + "sagemaker:listApps", + "sagemaker:listArtifacts", + "sagemaker:listAssociations", + "sagemaker:listAutoMLJobs", + "sagemaker:listCandidatesForAutoMLJob", + "sagemaker:listCodeRepositories", + "sagemaker:listCompilationJobs", + "sagemaker:listContexts", + "sagemaker:listDataQualityJobDefinitions", + "sagemaker:listDeviceFleets", + "sagemaker:listDevices", + "sagemaker:listDomains", + "sagemaker:listEdgePackagingJobs", + "sagemaker:listEndpointConfigs", + "sagemaker:listEndpoints", + "sagemaker:listExperiments", + "sagemaker:listFeatureGroups", + "sagemaker:listFlowDefinitions", + "sagemaker:listHumanTaskUis", + "sagemaker:listHyperParameterTuningJobs", + "sagemaker:listImages", + "sagemaker:listImageVersions", + "sagemaker:listLabelingJobs", + "sagemaker:listLabelingJobsForWorkteam", + "sagemaker:listModelBiasJobDefinitions", + "sagemaker:listModelExplainabilityJobDefinitions", + "sagemaker:listModelPackageGroups", + "sagemaker:listModelPackages", + "sagemaker:listModelQualityJobDefinitions", + "sagemaker:listModels", + "sagemaker:listMonitoringExecutions", + "sagemaker:listMonitoringSchedules", + "sagemaker:listNotebookInstanceLifecycleConfigs", + "sagemaker:listNotebookInstances", + "sagemaker:listPipelineExecutions", + "sagemaker:listPipelineExecutionSteps", + "sagemaker:listPipelineParametersForExecution", + "sagemaker:listPipelines", + "sagemaker:listProcessingJobs", + "sagemaker:listProjects", + "sagemaker:listSubscribedWorkteams", + "sagemaker:listTags", + "sagemaker:listTrainingJobs", + "sagemaker:listTrainingJobsForHyperParameterTuningJob", + "sagemaker:listTransformJobs", + "sagemaker:listTrialComponents", + "sagemaker:listTrials", + "sagemaker:listUserProfiles", + "sagemaker:listWorkteams", + "sdb:domainMetadata", + "sdb:listDomains", + "secretsmanager:describeSecret", + "secretsmanager:getResourcePolicy", + "secretsmanager:listSecrets", + "secretsmanager:listSecretVersionIds", + "securityhub:getEnabledStandards", + "securityhub:getFindings", + "securityhub:getInsightResults", + "securityhub:getInsights", + "securityhub:getMasterAccount", + "securityhub:getMembers", + "securityhub:listEnabledProductsForImport", + "securityhub:listInvitations", + "securityhub:listMembers", + "servicecatalog:describeConstraint", + "servicecatalog:describePortfolio", + "servicecatalog:describeProduct", + "servicecatalog:describeProductAsAdmin", + "servicecatalog:describeProductView", + "servicecatalog:describeProvisioningArtifact", + "servicecatalog:describeProvisioningParameters", + "servicecatalog:describeRecord", + "servicecatalog:listAcceptedPortfolioShares", + "servicecatalog:listConstraintsForPortfolio", + "servicecatalog:listLaunchPaths", + "servicecatalog:listPortfolioAccess", + "servicecatalog:listPortfolios", + "servicecatalog:listPortfoliosForProduct", + "servicecatalog:listPrincipalsForPortfolio", + "servicecatalog:listProvisioningArtifacts", + "servicecatalog:listRecordHistory", + "servicecatalog:scanProvisionedProducts", + "servicecatalog:searchProducts", + "servicequotas:getAssociationForServiceQuotaTemplate", + "servicequotas:getAWSDefaultServiceQuota", + "servicequotas:getRequestedServiceQuotaChange", + "servicequotas:getServiceQuota", + "servicequotas:getServiceQuotaIncreaseRequestFromTemplate", + "servicequotas:listAWSDefaultServiceQuotas", + "servicequotas:listRequestedServiceQuotaChangeHistory", + "servicequotas:listRequestedServiceQuotaChangeHistoryByQuota", + "servicequotas:listServiceQuotaIncreaseRequestsInTemplate", + "servicequotas:listServiceQuotas", + "servicequotas:listServices", + "ses:describeActiveReceiptRuleSet", + "ses:describeReceiptRule", + "ses:describeReceiptRuleSet", + "ses:getAccount", + "ses:getBlacklistReports", + "ses:getConfigurationSet", + "ses:getConfigurationSetEventDestinations", + "ses:getDedicatedIp", + "ses:getDedicatedIps", + "ses:getDeliverabilityDashboardOptions", + "ses:getDeliverabilityTestReport", + "ses:getDomainDeliverabilityCampaign", + "ses:getDomainStatisticsReport", + "ses:getEmailIdentity", + "ses:getIdentityDkimAttributes", + "ses:getIdentityMailFromDomainAttributes", + "ses:getIdentityNotificationAttributes", + "ses:getIdentityPolicies", + "ses:getIdentityVerificationAttributes", + "ses:getSendQuota", + "ses:getSendStatistics", + "ses:listConfigurationSets", + "ses:listDedicatedIpPools", + "ses:listDeliverabilityTestReports", + "ses:listDomainDeliverabilityCampaigns", + "ses:listEmailIdentities", + "ses:listIdentities", + "ses:listIdentityPolicies", + "ses:listReceiptFilters", + "ses:listReceiptRuleSets", + "ses:listTagsForResource", + "ses:listVerifiedEmailAddresses", + "shield:describeAttack", + "shield:describeProtection", + "shield:describeSubscription", + "shield:listAttacks", + "shield:listProtections", + "sms-voice:getConfigurationSetEventDestinations", + "sms:getConnectors", + "sms:getReplicationJobs", + "sms:getReplicationRuns", + "sms:getServers", + "snowball:describeAddress", + "snowball:describeAddresses", + "snowball:describeJob", + "snowball:getSnowballUsage", + "snowball:listJobs", + "sns:checkIfPhoneNumberIsOptedOut", + "sns:getEndpointAttributes", + "sns:getPlatformApplicationAttributes", + "sns:getSMSAttributes", + "sns:getSubscriptionAttributes", + "sns:getTopicAttributes", + "sns:listEndpointsByPlatformApplication", + "sns:listPhoneNumbersOptedOut", + "sns:listPlatformApplications", + "sns:listSubscriptions", + "sns:listSubscriptionsByTopic", + "sns:listTopics", + "sqs:getQueueAttributes", + "sqs:getQueueUrl", + "sqs:listDeadLetterSourceQueues", + "sqs:listQueues", + "ssm-contacts:describeEngagement", + "ssm-contacts:describePage", + "ssm-contacts:getContact", + "ssm-contacts:getContactChannel", + "ssm-contacts:listContactChannels", + "ssm-contacts:listContacts", + "ssm-contacts:listEngagements", + "ssm-contacts:listPageReceipts", + "ssm-contacts:listPagesByContact", + "ssm-contacts:listPagesByEngagement", + "ssm-incidents:getIncidentRecord", + "ssm-incidents:getReplicationSet", + "ssm-incidents:getResponsePlan", + "ssm-incidents:listIncidentRecords", + "ssm-incidents:listReplicationSets", + "ssm-incidents:listResponsePlans", + "ssm-incidents:listTimelineEvents", + "ssm:describeActivations", + "ssm:describeAssociation", + "ssm:describeAssociationExecutions", + "ssm:describeAssociationExecutionTargets", + "ssm:describeAutomationExecutions", + "ssm:describeAutomationStepExecutions", + "ssm:describeAvailablePatches", + "ssm:describeDocument", + "ssm:describeDocumentPermission", + "ssm:describeEffectiveInstanceAssociations", + "ssm:describeEffectivePatchesForPatchBaseline", + "ssm:describeInstanceAssociationsStatus", + "ssm:describeInstanceInformation", + "ssm:describeInstancePatches", + "ssm:describeInstancePatchStates", + "ssm:describeInstancePatchStatesForPatchGroup", + "ssm:describeInventoryDeletions", + "ssm:describeMaintenanceWindowExecutions", + "ssm:describeMaintenanceWindowExecutionTaskInvocations", + "ssm:describeMaintenanceWindowExecutionTasks", + "ssm:describeMaintenanceWindows", + "ssm:describeMaintenanceWindowSchedule", + "ssm:describeMaintenanceWindowsForTarget", + "ssm:describeMaintenanceWindowTargets", + "ssm:describeMaintenanceWindowTasks", + "ssm:describeOpsItems", + "ssm:describeParameters", + "ssm:describePatchBaselines", + "ssm:describePatchGroups", + "ssm:describePatchGroupState", + "ssm:describePatchProperties", + "ssm:describeSessions", + "ssm:getAutomationExecution", + "ssm:getCommandInvocation", + "ssm:getConnectionStatus", + "ssm:getDefaultPatchBaseline", + "ssm:getDeployablePatchSnapshotForInstance", + "ssm:getInventorySchema", + "ssm:getMaintenanceWindow", + "ssm:getMaintenanceWindowExecution", + "ssm:getMaintenanceWindowExecutionTask", + "ssm:getMaintenanceWindowExecutionTaskInvocation", + "ssm:getMaintenanceWindowTask", + "ssm:getOpsItem", + "ssm:getPatchBaseline", + "ssm:getPatchBaselineForPatchGroup", + "ssm:getServiceSetting", + "ssm:labelParameterVersion", + "ssm:listAssociations", + "ssm:listAssociationVersions", + "ssm:listCommandInvocations", + "ssm:listCommands", + "ssm:listComplianceItems", + "ssm:listComplianceSummaries", + "ssm:listDocuments", + "ssm:listDocumentVersions", + "ssm:listOpsItemEvents", + "ssm:listResourceComplianceSummaries", + "ssm:listResourceDataSync", + "ssm:listTagsForResource", + "states:describeActivity", + "states:describeExecution", + "states:describeStateMachine", + "states:describeStateMachineForExecution", + "states:getExecutionHistory", + "states:listActivities", + "states:listExecutions", + "states:listStateMachines", + "storagegateway:describeBandwidthRateLimit", + "storagegateway:describeCache", + "storagegateway:describeCachediSCSIVolumes", + "storagegateway:describeFileSystemAssociations", + "storagegateway:describeGatewayInformation", + "storagegateway:describeMaintenanceStartTime", + "storagegateway:describeNFSFileShares", + "storagegateway:describeSMBFileShares", + "storagegateway:describeSMBSettings", + "storagegateway:describeSnapshotSchedule", + "storagegateway:describeStorediSCSIVolumes", + "storagegateway:describeTapeArchives", + "storagegateway:describeTapeRecoveryPoints", + "storagegateway:describeTapes", + "storagegateway:describeUploadBuffer", + "storagegateway:describeVTLDevices", + "storagegateway:describeWorkingStorage", + "storagegateway:listFileShares", + "storagegateway:listFileSystemAssociations", + "storagegateway:listGateways", + "storagegateway:listLocalDisks", + "storagegateway:listTagsForResource", + "storagegateway:listTapes", + "storagegateway:listVolumeInitiators", + "storagegateway:listVolumeRecoveryPoints", + "storagegateway:listVolumes", + "swf:countClosedWorkflowExecutions", + "swf:countOpenWorkflowExecutions", + "swf:countPendingActivityTasks", + "swf:countPendingDecisionTasks", + "swf:describeActivityType", + "swf:describeDomain", + "swf:describeWorkflowExecution", + "swf:describeWorkflowType", + "swf:getWorkflowExecutionHistory", + "swf:listActivityTypes", + "swf:listClosedWorkflowExecutions", + "swf:listDomains", + "swf:listOpenWorkflowExecutions", + "swf:listWorkflowTypes", + "synthetics:describeCanaries", + "synthetics:describeCanariesLastRun", + "synthetics:describeRuntimeVersions", + "synthetics:getCanary", + "synthetics:getCanaryRuns", + "transfer:describeServer", + "transfer:describeUser", + "transfer:listServers", + "transfer:listTagsForResource", + "transfer:listUsers", + "waf-regional:getByteMatchSet", + "waf-regional:getChangeTokenStatus", + "waf-regional:getIPSet", + "waf-regional:getRule", + "waf-regional:getSqlInjectionMatchSet", + "waf-regional:getWebACL", + "waf-regional:getWebACLForResource", + "waf-regional:listByteMatchSets", + "waf-regional:listIPSets", + "waf-regional:listResourcesForWebACL", + "waf-regional:listRules", + "waf-regional:listSqlInjectionMatchSets", + "waf-regional:listWebACLs", + "waf:getByteMatchSet", + "waf:getChangeTokenStatus", + "waf:getIPSet", + "waf:getRule", + "waf:getSampledRequests", + "waf:getSizeConstraintSet", + "waf:getSqlInjectionMatchSet", + "waf:getWebACL", + "waf:getXssMatchSet", + "waf:listByteMatchSets", + "waf:listIPSets", + "waf:listRules", + "waf:listSizeConstraintSets", + "waf:listSqlInjectionMatchSets", + "waf:listWebACLs", + "waf:listXssMatchSets", + "wafv2:checkCapacity", + "wafv2:describeManagedRuleGroup", + "wafv2:getIPSet", + "wafv2:getLoggingConfiguration", + "wafv2:getPermissionPolicy", + "wafv2:getRateBasedStatementManagedKeys", + "wafv2:getRegexPatternSet", + "wafv2:getRuleGroup", + "wafv2:getSampledRequests", + "wafv2:getWebACL", + "wafv2:getWebACLForResource", + "wafv2:listAvailableManagedRuleGroups", + "wafv2:listIPSets", + "wafv2:listLoggingConfigurations", + "wafv2:listRegexPatternSets", + "wafv2:listResourcesForWebACL", + "wafv2:listRuleGroups", + "wafv2:listTagsForResource", + "wafv2:listWebACLs", + "workdocs:checkAlias", + "workdocs:describeAvailableDirectories", + "workdocs:describeInstances", + "worklink:describeAuditStreamConfiguration", + "worklink:describeCompanyNetworkConfiguration", + "worklink:describeDevice", + "worklink:describeDevicePolicyConfiguration", + "worklink:describeDomain", + "worklink:describeFleetMetadata", + "worklink:describeIdentityProviderConfiguration", + "worklink:describeWebsiteCertificateAuthority", + "worklink:listDevices", + "worklink:listDomains", + "worklink:listFleets", + "worklink:listWebsiteAuthorizationProviders", + "worklink:listWebsiteCertificateAuthorities", + "workmail:describeGroup", + "workmail:describeOrganization", + "workmail:describeResource", + "workmail:describeUser", + "workmail:listAliases", + "workmail:listGroupMembers", + "workmail:listGroups", + "workmail:listMailboxPermissions", + "workmail:listOrganizations", + "workmail:listResourceDelegates", + "workmail:listResources", + "workmail:listUsers", + "workspaces:describeAccount", + "workspaces:describeAccountModifications", + "workspaces:describeIpGroups", + "workspaces:describeTags", + "workspaces:describeWorkspaceBundles", + "workspaces:describeWorkspaceDirectories", + "workspaces:describeWorkspaceImages", + "workspaces:describeWorkspaces", + "workspaces:describeWorkspacesConnectionStatus" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "arn": "arn:aws:iam::aws:policy/aws-service-role/AWSSupportServiceRolePolicy", + "attached_to": { + "roles": [ + { + "id": "AROAJCXETX2ROIWUKOPGG", + "name": "AWSServiceRoleForSupport" + } + ] + }, + "id": "ANPAJ7W6266ELXF5MISDS", + "name": "AWSSupportServiceRolePolicy" + }, + "ANPAJH4QJ2WMHBOB47BUE": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "autoscaling:DescribeAccountLimits", + "autoscaling:DescribeAutoScalingGroups", + "autoscaling:DescribeLaunchConfigurations", + "cloudformation:DescribeAccountLimits", + "cloudformation:DescribeStacks", + "cloudformation:ListStacks", + "cloudfront:ListDistributions", + "cloudtrail:DescribeTrails", + "cloudtrail:GetTrailStatus", + "dynamodb:DescribeLimits", + "dynamodb:DescribeTable", + "dynamodb:ListTables", + "ec2:DescribeAddresses", + "ec2:DescribeReservedInstances", + "ec2:DescribeInstances", + "ec2:DescribeVpcs", + "ec2:DescribeInternetGateways", + "ec2:DescribeImages", + "ec2:DescribeVolumes", + "ec2:DescribeSecurityGroups", + "ec2:DescribeReservedInstancesOfferings", + "ec2:DescribeSnapshots", + "ec2:DescribeVpnConnections", + "ec2:DescribeVpnGateways", + "ec2:DescribeLaunchTemplateVersions", + "elasticloadbalancing:DescribeAccountLimits", + "elasticloadbalancing:DescribeInstanceHealth", + "elasticloadbalancing:DescribeLoadBalancerAttributes", + "elasticloadbalancing:DescribeLoadBalancerPolicies", + "elasticloadbalancing:DescribeLoadBalancerPolicyTypes", + "elasticloadbalancing:DescribeLoadBalancers", + "elasticloadbalancing:DescribeTargetGroups", + "iam:GenerateCredentialReport", + "iam:GetAccountPasswordPolicy", + "iam:GetAccountSummary", + "iam:GetCredentialReport", + "iam:GetServerCertificate", + "iam:ListServerCertificates", + "kinesis:DescribeLimits", + "rds:DescribeAccountAttributes", + "rds:DescribeDBClusters", + "rds:DescribeDBEngineVersions", + "rds:DescribeDBInstances", + "rds:DescribeDBParameterGroups", + "rds:DescribeDBParameters", + "rds:DescribeDBSecurityGroups", + "rds:DescribeDBSnapshots", + "rds:DescribeDBSubnetGroups", + "rds:DescribeEngineDefaultParameters", + "rds:DescribeEvents", + "rds:DescribeOptionGroupOptions", + "rds:DescribeOptionGroups", + "rds:DescribeOrderableDBInstanceOptions", + "rds:DescribeReservedDBInstances", + "rds:DescribeReservedDBInstancesOfferings", + "rds:ListTagsForResource", + "redshift:DescribeClusters", + "redshift:DescribeReservedNodeOfferings", + "redshift:DescribeReservedNodes", + "route53:GetAccountLimit", + "route53:GetHealthCheck", + "route53:GetHostedZone", + "route53:ListHealthChecks", + "route53:ListHostedZones", + "route53:ListHostedZonesByName", + "route53:ListResourceRecordSets", + "s3:GetAccountPublicAccessBlock", + "s3:GetBucketAcl", + "s3:GetBucketPolicy", + "s3:GetBucketPolicyStatus", + "s3:GetBucketLocation", + "s3:GetBucketLogging", + "s3:GetBucketVersioning", + "s3:GetBucketPublicAccessBlock", + "s3:ListBucket", + "s3:ListAllMyBuckets", + "ses:GetSendQuota", + "sqs:ListQueues", + "cloudwatch:GetMetricStatistics", + "ce:GetReservationPurchaseRecommendation", + "ce:GetSavingsPlansPurchaseRecommendation" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "arn": "arn:aws:iam::aws:policy/aws-service-role/AWSTrustedAdvisorServiceRolePolicy", + "attached_to": { + "roles": [ + { + "id": "AROAJCHEQKY4NYQFQWP5K", + "name": "AWSServiceRoleForTrustedAdvisor" + } + ] + }, + "id": "ANPAJH4QJ2WMHBOB47BUE", + "name": "AWSTrustedAdvisorServiceRolePolicy" + }, + "ANPAJQPCESDDYDLLSOGYO": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "cloudtrail:DescribeTrails", + "cloudtrail:GetTrailStatus", + "cloudtrail:GetEventSelectors", + "cloudwatch:DescribeAlarms", + "cloudwatch:DescribeAlarmsForMetric", + "logs:DescribeMetricFilters", + "sns:ListSubscriptionsByTopic", + "config:DescribeConfigurationRecorders", + "config:DescribeConfigurationRecorderStatus", + "config:DescribeConfigRules", + "config:BatchGetResourceConfig", + "config:SelectResourceConfig", + "iam:GenerateCredentialReport", + "iam:GetCredentialReport", + "organizations:ListAccounts", + "organizations:DescribeAccount", + "organizations:DescribeOrganization", + "config:PutEvaluations" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "config:PutConfigRule", + "config:DeleteConfigRule", + "config:GetComplianceDetailsByConfigRule", + "config:DescribeConfigRuleEvaluationStatus" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:config:*:*:config-rule/aws-service-rule/*securityhub*" + ] + } + ], + "Version": "2012-10-17" + }, + "arn": "arn:aws:iam::aws:policy/aws-service-role/AWSSecurityHubServiceRolePolicy", + "attached_to": { + "roles": [ + { + "id": "AROAWIJXQGZ5HSCDUOZE5", + "name": "AWSServiceRoleForSecurityHub" + } + ] + }, + "id": "ANPAJQPCESDDYDLLSOGYO", + "name": "AWSSecurityHubServiceRolePolicy" + }, + "ANPAJSVXG6QHPE6VHDZ4Q": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "cloudwatch:DescribeAlarms", + "elasticmapreduce:ListInstanceGroups", + "elasticmapreduce:ModifyInstanceGroups" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "arn": "arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceforAutoScalingRole", + "attached_to": { + "roles": [ + { + "id": "AROAIH747R37LKSEOZ2MA", + "name": "EMR_AutoScaling_DefaultRole" + } + ] + }, + "id": "ANPAJSVXG6QHPE6VHDZ4Q", + "name": "AmazonElasticMapReduceforAutoScalingRole" + }, + "ANPAZKAPJZG4CAIXDDRI2": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ec2:DescribeAddresses", + "ec2:DescribeByoipCidrs", + "ec2:DescribeVpcEndpoints", + "ec2:DescribeVpcs", + "iam:GetRole", + "iam:ListRoles", + "kms:DescribeKey", + "kms:GetKeyPolicy", + "kms:ListGrants", + "kms:ListKeyPolicies", + "kms:ListKeys", + "lambda:GetLayerVersionPolicy", + "lambda:GetPolicy", + "lambda:ListAliases", + "lambda:ListFunctions", + "lambda:ListLayers", + "lambda:ListLayerVersions", + "lambda:ListVersionsByFunction", + "organizations:DescribeAccount", + "organizations:DescribeOrganization", + "organizations:DescribeOrganizationalUnit", + "organizations:ListAccounts", + "organizations:ListAccountsForParent", + "organizations:ListAWSServiceAccessForOrganization", + "organizations:ListChildren", + "organizations:ListDelegatedAdministrators", + "organizations:ListOrganizationalUnitsForParent", + "organizations:ListParents", + "organizations:ListRoots", + "s3:DescribeMultiRegionAccessPointOperation", + "s3:GetAccessPoint", + "s3:GetAccessPointPolicy", + "s3:GetAccessPointPolicyStatus", + "s3:GetAccountPublicAccessBlock", + "s3:GetBucketAcl", + "s3:GetBucketLocation", + "s3:GetBucketPolicyStatus", + "s3:GetBucketPolicy", + "s3:GetBucketPublicAccessBlock", + "s3:GetMultiRegionAccessPoint", + "s3:GetMultiRegionAccessPointPolicy", + "s3:GetMultiRegionAccessPointPolicyStatus", + "s3:ListAccessPoints", + "s3:ListAllMyBuckets", + "s3:ListMultiRegionAccessPoints", + "sns:GetTopicAttributes", + "sns:ListTopics", + "secretsmanager:DescribeSecret", + "secretsmanager:GetResourcePolicy", + "secretsmanager:ListSecrets", + "sqs:GetQueueAttributes", + "sqs:ListQueues" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "arn": "arn:aws:iam::aws:policy/aws-service-role/AccessAnalyzerServiceRolePolicy", + "attached_to": { + "roles": [ + { + "id": "AROAWIJXQGZ5OSPI4PBJL", + "name": "AWSServiceRoleForAccessAnalyzer" + } + ] + }, + "id": "ANPAZKAPJZG4CAIXDDRI2", + "name": "AccessAnalyzerServiceRolePolicy" + } + }, + "policies_count": 9, + "roles": { + "AROAI265GPNVMDZAKJPPA": { + "arn": "arn:aws:iam::430150006394:role/EMR_EC2_DefaultRole", + "assume_role_policy": { + "PolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + }, + "Sid": "" + } + ], + "Version": "2008-10-17" + } + }, + "awslambdas_count": 0, + "create_date": "2019-01-26 09:04:06+00:00", + "description": null, + "id": "AROAI265GPNVMDZAKJPPA", + "inline_policies": {}, + "inline_policies_count": 0, + "instance_profiles": { + "AIPAJLM3SI3PSXMHLNA24": { + "arn": "arn:aws:iam::430150006394:instance-profile/EMR_EC2_DefaultRole", + "name": "EMR_EC2_DefaultRole" + } + }, + "instances_count": 0, + "max_session_duration": 3600, + "name": "EMR_EC2_DefaultRole", + "path": "/", + "policies": [ + "ANPAIGALS5RCDLZLB3PGS" + ], + "policies_counts": 1 + }, + "AROAIH747R37LKSEOZ2MA": { + "arn": "arn:aws:iam::430150006394:role/EMR_AutoScaling_DefaultRole", + "assume_role_policy": { + "PolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": [ + "application-autoscaling.amazonaws.com", + "elasticmapreduce.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + } + }, + "awslambdas_count": 0, + "create_date": "2019-01-26 09:04:06+00:00", + "description": null, + "id": "AROAIH747R37LKSEOZ2MA", + "inline_policies": {}, + "inline_policies_count": 0, + "instance_profiles": {}, + "instances_count": 0, + "max_session_duration": 3600, + "name": "EMR_AutoScaling_DefaultRole", + "path": "/", + "policies": [ + "ANPAJSVXG6QHPE6VHDZ4Q" + ], + "policies_counts": 1 + }, + "AROAIXBSWIKGEEDLMO53I": { + "arn": "arn:aws:iam::430150006394:role/EMR_DefaultRole", + "assume_role_policy": { + "PolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "elasticmapreduce.amazonaws.com" + }, + "Sid": "" + } + ], + "Version": "2008-10-17" + } + }, + "awslambdas_count": 0, + "create_date": "2019-01-26 09:04:06+00:00", + "description": null, + "id": "AROAIXBSWIKGEEDLMO53I", + "inline_policies": {}, + "inline_policies_count": 0, + "instance_profiles": {}, + "instances_count": 0, + "max_session_duration": 3600, + "name": "EMR_DefaultRole", + "path": "/", + "policies": [ + "ANPAIDI2BQT2LKXZG36TW" + ], + "policies_counts": 1 + }, + "AROAJ2LRZXYT2USPF2ZTY": { + "arn": "arn:aws:iam::430150006394:role/aws-service-role/elasticmapreduce.amazonaws.com/AWSServiceRoleForEMRCleanup", + "assume_role_policy": { + "PolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "elasticmapreduce.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + }, + "awslambdas_count": 0, + "create_date": "2019-01-26 09:04:23+00:00", + "description": null, + "id": "AROAJ2LRZXYT2USPF2ZTY", + "inline_policies": {}, + "inline_policies_count": 0, + "instance_profiles": {}, + "instances_count": 0, + "max_session_duration": 3600, + "name": "AWSServiceRoleForEMRCleanup", + "path": "/aws-service-role/elasticmapreduce.amazonaws.com/", + "policies": [ + "ANPAI4YEZURRMKACW56EA" + ], + "policies_counts": 1 + }, + "AROAJCHEQKY4NYQFQWP5K": { + "arn": "arn:aws:iam::430150006394:role/aws-service-role/trustedadvisor.amazonaws.com/AWSServiceRoleForTrustedAdvisor", + "assume_role_policy": { + "PolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "trustedadvisor.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + }, + "awslambdas_count": 0, + "create_date": "2018-08-15 22:08:26+00:00", + "description": "Access for the AWS Trusted Advisor Service to help reduce cost, increase performance, and improve security of your AWS environment.", + "id": "AROAJCHEQKY4NYQFQWP5K", + "inline_policies": {}, + "inline_policies_count": 0, + "instance_profiles": {}, + "instances_count": 0, + "max_session_duration": 3600, + "name": "AWSServiceRoleForTrustedAdvisor", + "path": "/aws-service-role/trustedadvisor.amazonaws.com/", + "policies": [ + "ANPAJH4QJ2WMHBOB47BUE" + ], + "policies_counts": 1 + }, + "AROAJCXETX2ROIWUKOPGG": { + "arn": "arn:aws:iam::430150006394:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport", + "assume_role_policy": { + "PolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "support.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + }, + "awslambdas_count": 0, + "create_date": "2018-08-09 19:34:27+00:00", + "description": "Enables resource access for AWS to provide billing, administrative and support services", + "id": "AROAJCXETX2ROIWUKOPGG", + "inline_policies": {}, + "inline_policies_count": 0, + "instance_profiles": {}, + "instances_count": 0, + "max_session_duration": 3600, + "name": "AWSServiceRoleForSupport", + "path": "/aws-service-role/support.amazonaws.com/", + "policies": [ + "ANPAJ7W6266ELXF5MISDS" + ], + "policies_counts": 1 + }, + "AROAJY5MNJYDKGD2UIATQ": { + "arn": "arn:aws:iam::430150006394:role/service-role/load-wikipedia", + "assume_role_policy": { + "PolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + }, + "awslambdas": { + "load-wikipedia": { + "access_policy": { + "Id": "default", + "Statement": [], + "Version": "2012-10-17" + }, + "arn": "arn:aws:lambda:eu-west-1:430150006394:function:load-wikipedia", + "code_sha256": "txY7sj38mwfot6uoeqMhNs4P/VycimyJcRBdlDBTyik=", + "code_size": 506, + "description": "", + "env_variable_names": [], + "env_variable_values": [], + "env_variables": [], + "execution_role": { + "Arn": "arn:aws:iam::430150006394:role/service-role/load-wikipedia", + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "CreateDate": "2019-01-23 17:01:24+00:00", + "MaxSessionDuration": 3600, + "Path": "/service-role/", + "RoleId": "AROAJY5MNJYDKGD2UIATQ", + "RoleLastUsed": {}, + "RoleName": "load-wikipedia", + "policies": [ + { + "Document": { + "Statement": [ + { + "Action": "logs:CreateLogGroup", + "Effect": "Allow", + "Resource": "arn:aws:logs:eu-west-1:430150006394:*" + }, + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:eu-west-1:430150006394:log-group:/aws/lambda/load-wikipedia:*" + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyArn": "arn:aws:iam::430150006394:policy/service-role/AWSLambdaBasicExecutionRole-676647ec-377e-496c-8355-37f23bf12c85", + "PolicyName": "AWSLambdaBasicExecutionRole-676647ec-377e-496c-8355-37f23bf12c85" + } + ], + "policy_statements": [ + { + "Action": "logs:CreateLogGroup", + "Effect": "Allow", + "Resource": "arn:aws:logs:eu-west-1:430150006394:*" + }, + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:eu-west-1:430150006394:log-group:/aws/lambda/load-wikipedia:*" + ] + } + ] + }, + "handler": "lambda_function.lambda_handler", + "last_modified": "2019-01-25T17:47:21.038+0000", + "memory_size": 128, + "name": "load-wikipedia", + "region": "eu-west-1", + "revision_id": "9ec6c002-9048-4d53-a4c2-001e406827b3", + "role_arn": "arn:aws:iam::430150006394:role/service-role/load-wikipedia", + "runtime": "python2.7", + "timeout": 3, + "tracing_config": { + "Mode": "PassThrough" + }, + "version": "$LATEST" + } + }, + "awslambdas_count": 1, + "create_date": "2019-01-23 17:01:24+00:00", + "description": null, + "id": "AROAJY5MNJYDKGD2UIATQ", + "inline_policies": {}, + "inline_policies_count": 0, + "instance_profiles": {}, + "instances_count": 0, + "max_session_duration": 3600, + "name": "load-wikipedia", + "path": "/service-role/", + "policies": [ + "ANPAIDFYJXP7KKG7FLVWO" + ], + "policies_counts": 1 + }, + "AROAWIJXQGZ5HSCDUOZE5": { + "arn": "arn:aws:iam::430150006394:role/aws-service-role/securityhub.amazonaws.com/AWSServiceRoleForSecurityHub", + "assume_role_policy": { + "PolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "securityhub.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + }, + "awslambdas_count": 0, + "create_date": "2021-04-28 13:12:07+00:00", + "description": "A service-linked role required for AWS Security Hub to access your resources.", + "id": "AROAWIJXQGZ5HSCDUOZE5", + "inline_policies": {}, + "inline_policies_count": 0, + "instance_profiles": {}, + "instances_count": 0, + "max_session_duration": 3600, + "name": "AWSServiceRoleForSecurityHub", + "path": "/aws-service-role/securityhub.amazonaws.com/", + "policies": [ + "ANPAJQPCESDDYDLLSOGYO" + ], + "policies_counts": 1 + }, + "AROAWIJXQGZ5OSPI4PBJL": { + "arn": "arn:aws:iam::430150006394:role/aws-service-role/access-analyzer.amazonaws.com/AWSServiceRoleForAccessAnalyzer", + "assume_role_policy": { + "PolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "access-analyzer.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + }, + "awslambdas_count": 0, + "create_date": "2021-04-28 13:17:38+00:00", + "description": null, + "id": "AROAWIJXQGZ5OSPI4PBJL", + "inline_policies": {}, + "inline_policies_count": 0, + "instance_profiles": {}, + "instances_count": 0, + "max_session_duration": 3600, + "name": "AWSServiceRoleForAccessAnalyzer", + "path": "/aws-service-role/access-analyzer.amazonaws.com/", + "policies": [ + "ANPAZKAPJZG4CAIXDDRI2" + ], + "policies_counts": 1 + } + }, + "roles_count": 9, + "users": { + "AIDAJUK77MEJCW5J3DWZU": { + "AccessKeys": [ + { + "AccessKeyId": "", + "CreateDate": "2013-12-19 09:13:40+00:00", + "Status": "Active", + "UserName": "dams" + }, + { + "AccessKeyId": "", + "CreateDate": "2019-01-25 17:58:41+00:00", + "Status": "Active", + "UserName": "dams" + } + ], + "CreateDate": "2013-12-19 09:13:40+00:00", + "MFADevices": [], + "Path": "/", + "arn": "arn:aws:iam::430150006394:user/dams", + "groups": [ + "devs" + ], + "id": "AIDAJUK77MEJCW5J3DWZU", + "inline_policies": {}, + "inline_policies_count": 0, + "name": "dams", + "tags": { + "IsTruncated": false, + "ResponseMetadata": { + "HTTPHeaders": { + "content-length": "300", + "content-type": "text/xml", + "date": "Fri, 01 Oct 2021 18:47:29 GMT", + "x-amzn-requestid": "3fe4d555-c7cc-46e3-ab08-63c4a6b4aca3" + }, + "HTTPStatusCode": 200, + "RequestId": "3fe4d555-c7cc-46e3-ab08-63c4a6b4aca3", + "RetryAttempts": 0 + }, + "Tags": [] + } + } + }, + "users_count": 1 + }, + "kms": { + "filters": {}, + "findings": { + "kms-cmk-rotation-disabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.8", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.8", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.8", + "version": "1.2.0" + } + ], + "dashboard_name": "Keys", + "description": "KMS Customer Master Keys (CMKs) with Rotation Disabled", + "display_path": "kms.regions.id.keys.id", + "flagged_items": 0, + "id_suffix": "rotation_enabled", + "items": [], + "level": "warning", + "path": "kms.regions.id.keys.id", + "rationale": "Cryptographic best practices discourage extensive reuse of encryption keys. Consequently, Customer Master Keys (CMKs) should be rotated to prevent usage of compromised keys.

Note that AWS KMS supports optional automatic key rotation only for customer managed CMKs.", + "references": [ + "https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html" + ], + "remediation": "For every KMS Customer Master Keys (CMKs), ensure that Rotate this key every year is enabled", + "service": "KMS" + } + }, + "keys_count": 0, + "regions": { + "ap-northeast-1": { + "id": "ap-northeast-1", + "keys": {}, + "keys_count": 0, + "name": "ap-northeast-1", + "region": "ap-northeast-1" + }, + "ap-northeast-2": { + "id": "ap-northeast-2", + "keys": {}, + "keys_count": 0, + "name": "ap-northeast-2", + "region": "ap-northeast-2" + }, + "ap-northeast-3": { + "id": "ap-northeast-3", + "keys": {}, + "keys_count": 0, + "name": "ap-northeast-3", + "region": "ap-northeast-3" + }, + "ap-south-1": { + "id": "ap-south-1", + "keys": {}, + "keys_count": 0, + "name": "ap-south-1", + "region": "ap-south-1" + }, + "ap-southeast-1": { + "id": "ap-southeast-1", + "keys": {}, + "keys_count": 0, + "name": "ap-southeast-1", + "region": "ap-southeast-1" + }, + "ap-southeast-2": { + "id": "ap-southeast-2", + "keys": {}, + "keys_count": 0, + "name": "ap-southeast-2", + "region": "ap-southeast-2" + }, + "ca-central-1": { + "id": "ca-central-1", + "keys": {}, + "keys_count": 0, + "name": "ca-central-1", + "region": "ca-central-1" + }, + "eu-central-1": { + "id": "eu-central-1", + "keys": {}, + "keys_count": 0, + "name": "eu-central-1", + "region": "eu-central-1" + }, + "eu-north-1": { + "id": "eu-north-1", + "keys": {}, + "keys_count": 0, + "name": "eu-north-1", + "region": "eu-north-1" + }, + "eu-west-1": { + "id": "eu-west-1", + "keys": {}, + "keys_count": 0, + "name": "eu-west-1", + "region": "eu-west-1" + }, + "eu-west-2": { + "id": "eu-west-2", + "keys": {}, + "keys_count": 0, + "name": "eu-west-2", + "region": "eu-west-2" + }, + "eu-west-3": { + "id": "eu-west-3", + "keys": {}, + "keys_count": 0, + "name": "eu-west-3", + "region": "eu-west-3" + }, + "sa-east-1": { + "id": "sa-east-1", + "keys": {}, + "keys_count": 0, + "name": "sa-east-1", + "region": "sa-east-1" + }, + "us-east-1": { + "id": "us-east-1", + "keys": {}, + "keys_count": 0, + "name": "us-east-1", + "region": "us-east-1" + }, + "us-east-2": { + "id": "us-east-2", + "keys": {}, + "keys_count": 0, + "name": "us-east-2", + "region": "us-east-2" + }, + "us-west-1": { + "id": "us-west-1", + "keys": {}, + "keys_count": 0, + "name": "us-west-1", + "region": "us-west-1" + }, + "us-west-2": { + "id": "us-west-2", + "keys": {}, + "keys_count": 0, + "name": "us-west-2", + "region": "us-west-2" + } + }, + "regions_count": 17 + }, + "rds": { + "filters": {}, + "findings": { + "rds-instance-backup-disabled": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Instances", + "description": "Backup Disabled", + "flagged_items": 0, + "id_suffix": "BackupRetentionPeriod", + "items": [], + "level": "danger", + "path": "rds.regions.id.vpcs.id.instances.id", + "rationale": "Backups should be enabled to enable disaster recovery.", + "references": [ + "https://aws.amazon.com/rds/details/backup/" + ], + "remediation": null, + "service": "RDS" + }, + "rds-instance-ca-certificate-deprecated": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Instances", + "description": "Deprecated Certificate Authority Assigned to RDS Instance", + "flagged_items": 0, + "id_suffix": "CACertificateIdentifier", + "items": [], + "level": "warning", + "path": "rds.regions.id.vpcs.id.instances.id", + "rationale": "Amazon Web Services is deprecating the RDS Certificate Authority created in 2015 (rds-ca-2015). Any endpoints using TLS to protect RDS communications will fail after March 5th, 2020.", + "references": [ + "https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL-certificate-rotation.html" + ], + "remediation": null, + "service": "RDS" + }, + "rds-instance-no-minor-upgrade": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Instances", + "description": "Auto Minor Version Upgrade Disabled", + "flagged_items": 0, + "id_suffix": "AutoMinorVersionUpgrade", + "items": [], + "level": "danger", + "path": "rds.regions.id.vpcs.id.instances.id", + "rationale": "Auto Minor Version Upgrade is a feature that you can enable to have your database automatically upgraded when a new minor database engine version is available. Minor version upgrades often patch security vulnerabilities and fix bugs, and therefor should be applied.", + "references": [ + "https://aws.amazon.com/blogs/database/best-practices-for-upgrading-amazon-rds-to-major-and-minor-versions-of-postgresql/", + "https://aws.amazon.com/about-aws/whats-new/2018/12/amazon-rds-enhances-auto-minor-version-upgrades/" + ], + "remediation": null, + "service": "RDS" + }, + "rds-instance-short-backup-retention-period": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Instances", + "description": "Short Backup Retention Period", + "flagged_items": 0, + "id_suffix": "BackupRetentionPeriod", + "items": [], + "level": "warning", + "path": "rds.regions.id.vpcs.id.instances.id", + "rationale": "The backup retention period is a period of time between 0 and 35 days for which you can perform a point-in-time restore. Setting the backup retention period to 0 disables automated backups.

It is recommended that the retention period is set to at least 30 days. Having a short retention period will impact how far back in time the database can be restored to, and may affect integrity and availability of data.", + "references": [ + "https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithAutomatedBackups.html" + ], + "remediation": null, + "service": "RDS" + }, + "rds-instance-single-az": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Instances", + "description": "Single AZ RDS Instance", + "flagged_items": 0, + "id_suffix": "MultiAZ", + "items": [], + "level": "danger", + "path": "rds.regions.id.vpcs.id.instances.id", + "rationale": "In case of failure, with a single-AZ deployment configuration, should an availability zone specific database failure occur, Amazon RDS can not automatically fail over to the standby availability zone.", + "references": [ + "https://aws.amazon.com/rds/features/multi-az/" + ], + "remediation": null, + "service": "RDS" + }, + "rds-instance-storage-not-encrypted": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Instances", + "description": "Instance Storage Not Encrypted", + "flagged_items": 0, + "id_suffix": "StorageEncrypted", + "items": [], + "level": "warning", + "path": "rds.regions.id.vpcs.id.instances.id", + "rationale": "Data-at-rest should be encrypted.", + "references": [ + "https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.Encryption.html" + ], + "remediation": null, + "service": "RDS" + }, + "rds-security-group-allows-all": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Security Groups", + "description": "Security Group Allows All IP Addresses", + "display_path": "rds.regions.id.vpcs.id.security_groups.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "rds.regions.id.vpcs.id.security_groups.id.ip_ranges", + "rationale": "The security group allows access to RDS instances from any source address, which creates a wider attack surface for resources assigned to it. Source address restrictions should be implemented", + "references": null, + "remediation": null, + "service": "RDS" + }, + "rds-snapshot-public": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Snapshots", + "description": "Publicly Accessible RDS Snapshot", + "display_path": "rds.regions.id.vpcs.id.snapshots.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "rds.regions.id.vpcs.id.snapshots.id.attributes.id", + "rationale": "Snapshots should never be public, as this risks exposing sensitive data.", + "references": [ + "https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ShareSnapshot.html" + ], + "remediation": null, + "service": "RDS" + } + }, + "instances_count": 0, + "parameter_groups_count": 0, + "regions": { + "ap-northeast-1": { + "id": "ap-northeast-1", + "instances_count": 0, + "name": "ap-northeast-1", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "ap-northeast-1", + "security_groups": { + "default": { + "DBSecurityGroupDescription": "default", + "EC2SecurityGroups": [], + "IPRanges": [], + "OwnerId": "430150006394", + "arn": "arn:aws:rds:ap-northeast-1:430150006394:secgrp:default", + "name": "default" + } + }, + "security_groups_count": 1, + "snapshots_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-0cbc506a": { + "arn": "arn:aws:vpc:ap-northeast-1:430150006394:virtual-private-cloud/vpc-0cbc506a", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-0cbc506a", + "instances": {}, + "instances_count": 0, + "name": "vpc-0cbc506a", + "snapshots": {}, + "snapshots_count": 0, + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "ap-northeast-2": { + "id": "ap-northeast-2", + "instances_count": 0, + "name": "ap-northeast-2", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "ap-northeast-2", + "security_groups": { + "default": { + "DBSecurityGroupDescription": "default", + "EC2SecurityGroups": [], + "IPRanges": [], + "OwnerId": "430150006394", + "arn": "arn:aws:rds:ap-northeast-2:430150006394:secgrp:default", + "name": "default" + } + }, + "security_groups_count": 1, + "snapshots_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-73f44e18": { + "arn": "arn:aws:vpc:ap-northeast-2:430150006394:virtual-private-cloud/vpc-73f44e18", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-73f44e18", + "instances": {}, + "instances_count": 0, + "name": "vpc-73f44e18", + "snapshots": {}, + "snapshots_count": 0, + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "ap-northeast-3": { + "id": "ap-northeast-3", + "instances_count": 0, + "name": "ap-northeast-3", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "ap-northeast-3", + "security_groups": { + "default": { + "DBSecurityGroupDescription": "default", + "EC2SecurityGroups": [], + "IPRanges": [], + "OwnerId": "430150006394", + "arn": "arn:aws:rds:ap-northeast-3:430150006394:secgrp:default", + "name": "default" + } + }, + "security_groups_count": 1, + "snapshots_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-47b7dd2e": { + "arn": "arn:aws:vpc:ap-northeast-3:430150006394:virtual-private-cloud/vpc-47b7dd2e", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-47b7dd2e", + "instances": {}, + "instances_count": 0, + "name": "vpc-47b7dd2e", + "snapshots": {}, + "snapshots_count": 0, + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "ap-south-1": { + "id": "ap-south-1", + "instances_count": 0, + "name": "ap-south-1", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "ap-south-1", + "security_groups": { + "default": { + "DBSecurityGroupDescription": "default", + "EC2SecurityGroups": [], + "IPRanges": [], + "OwnerId": "430150006394", + "arn": "arn:aws:rds:ap-south-1:430150006394:secgrp:default", + "name": "default" + } + }, + "security_groups_count": 1, + "snapshots_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-2651a14d": { + "arn": "arn:aws:vpc:ap-south-1:430150006394:virtual-private-cloud/vpc-2651a14d", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-2651a14d", + "instances": {}, + "instances_count": 0, + "name": "vpc-2651a14d", + "snapshots": {}, + "snapshots_count": 0, + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "ap-southeast-1": { + "id": "ap-southeast-1", + "instances_count": 0, + "name": "ap-southeast-1", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "ap-southeast-1", + "security_groups": { + "default": { + "DBSecurityGroupDescription": "default", + "EC2SecurityGroups": [], + "IPRanges": [], + "OwnerId": "430150006394", + "arn": "arn:aws:rds:ap-southeast-1:430150006394:secgrp:default", + "name": "default" + } + }, + "security_groups_count": 1, + "snapshots_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-04ed1062": { + "arn": "arn:aws:vpc:ap-southeast-1:430150006394:virtual-private-cloud/vpc-04ed1062", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-04ed1062", + "instances": {}, + "instances_count": 0, + "name": "vpc-04ed1062", + "snapshots": {}, + "snapshots_count": 0, + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "ap-southeast-2": { + "id": "ap-southeast-2", + "instances_count": 0, + "name": "ap-southeast-2", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "ap-southeast-2", + "security_groups": { + "default": { + "DBSecurityGroupDescription": "default", + "EC2SecurityGroups": [], + "IPRanges": [], + "OwnerId": "430150006394", + "arn": "arn:aws:rds:ap-southeast-2:430150006394:secgrp:default", + "name": "default" + } + }, + "security_groups_count": 1, + "snapshots_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-5d22c33b": { + "arn": "arn:aws:vpc:ap-southeast-2:430150006394:virtual-private-cloud/vpc-5d22c33b", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-5d22c33b", + "instances": {}, + "instances_count": 0, + "name": "vpc-5d22c33b", + "snapshots": {}, + "snapshots_count": 0, + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "ca-central-1": { + "id": "ca-central-1", + "instances_count": 0, + "name": "ca-central-1", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "ca-central-1", + "security_groups": { + "default": { + "DBSecurityGroupDescription": "default", + "EC2SecurityGroups": [], + "IPRanges": [], + "OwnerId": "430150006394", + "arn": "arn:aws:rds:ca-central-1:430150006394:secgrp:default", + "name": "default" + } + }, + "security_groups_count": 1, + "snapshots_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-b5113ddd": { + "arn": "arn:aws:vpc:ca-central-1:430150006394:virtual-private-cloud/vpc-b5113ddd", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-b5113ddd", + "instances": {}, + "instances_count": 0, + "name": "vpc-b5113ddd", + "snapshots": {}, + "snapshots_count": 0, + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "eu-central-1": { + "id": "eu-central-1", + "instances_count": 0, + "name": "eu-central-1", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "eu-central-1", + "security_groups": { + "default": { + "DBSecurityGroupDescription": "default", + "EC2SecurityGroups": [], + "IPRanges": [], + "OwnerId": "430150006394", + "arn": "arn:aws:rds:eu-central-1:430150006394:secgrp:default", + "name": "default" + } + }, + "security_groups_count": 1, + "snapshots_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-78b43312": { + "arn": "arn:aws:vpc:eu-central-1:430150006394:virtual-private-cloud/vpc-78b43312", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-78b43312", + "instances": {}, + "instances_count": 0, + "name": "vpc-78b43312", + "snapshots": {}, + "snapshots_count": 0, + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "eu-north-1": { + "id": "eu-north-1", + "instances_count": 0, + "name": "eu-north-1", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "eu-north-1", + "security_groups": { + "default": { + "DBSecurityGroupDescription": "default", + "EC2SecurityGroups": [], + "IPRanges": [], + "OwnerId": "430150006394", + "arn": "arn:aws:rds:eu-north-1:430150006394:secgrp:default", + "name": "default" + } + }, + "security_groups_count": 1, + "snapshots_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-fa259d93": { + "arn": "arn:aws:vpc:eu-north-1:430150006394:virtual-private-cloud/vpc-fa259d93", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-fa259d93", + "instances": {}, + "instances_count": 0, + "name": "vpc-fa259d93", + "snapshots": {}, + "snapshots_count": 0, + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "eu-west-1": { + "id": "eu-west-1", + "instances_count": 0, + "name": "eu-west-1", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "eu-west-1", + "security_groups": { + "default": { + "DBSecurityGroupDescription": "default", + "EC2SecurityGroups": [], + "IPRanges": [], + "OwnerId": "430150006394", + "arn": "arn:aws:rds:eu-west-1:430150006394:secgrp:default", + "name": "default" + } + }, + "security_groups_count": 1, + "snapshots_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-f24c7994": { + "arn": "arn:aws:vpc:eu-west-1:430150006394:virtual-private-cloud/vpc-f24c7994", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-f24c7994", + "instances": {}, + "instances_count": 0, + "name": "vpc-f24c7994", + "snapshots": {}, + "snapshots_count": 0, + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "eu-west-2": { + "id": "eu-west-2", + "instances_count": 0, + "name": "eu-west-2", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "eu-west-2", + "security_groups": { + "default": { + "DBSecurityGroupDescription": "default", + "EC2SecurityGroups": [], + "IPRanges": [], + "OwnerId": "430150006394", + "arn": "arn:aws:rds:eu-west-2:430150006394:secgrp:default", + "name": "default" + } + }, + "security_groups_count": 1, + "snapshots_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-3fa2fa57": { + "arn": "arn:aws:vpc:eu-west-2:430150006394:virtual-private-cloud/vpc-3fa2fa57", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-3fa2fa57", + "instances": {}, + "instances_count": 0, + "name": "vpc-3fa2fa57", + "snapshots": {}, + "snapshots_count": 0, + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "eu-west-3": { + "id": "eu-west-3", + "instances_count": 0, + "name": "eu-west-3", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "eu-west-3", + "security_groups": { + "default": { + "DBSecurityGroupDescription": "default", + "EC2SecurityGroups": [], + "IPRanges": [], + "OwnerId": "430150006394", + "arn": "arn:aws:rds:eu-west-3:430150006394:secgrp:default", + "name": "default" + } + }, + "security_groups_count": 1, + "snapshots_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-87d3fdee": { + "arn": "arn:aws:vpc:eu-west-3:430150006394:virtual-private-cloud/vpc-87d3fdee", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-87d3fdee", + "instances": {}, + "instances_count": 0, + "name": "vpc-87d3fdee", + "snapshots": {}, + "snapshots_count": 0, + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "sa-east-1": { + "id": "sa-east-1", + "instances_count": 0, + "name": "sa-east-1", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "sa-east-1", + "security_groups": { + "default": { + "DBSecurityGroupDescription": "default", + "EC2SecurityGroups": [], + "IPRanges": [], + "OwnerId": "430150006394", + "arn": "arn:aws:rds:sa-east-1:430150006394:secgrp:default", + "name": "default" + } + }, + "security_groups_count": 1, + "snapshots_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-b14fa4d7": { + "arn": "arn:aws:vpc:sa-east-1:430150006394:virtual-private-cloud/vpc-b14fa4d7", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-b14fa4d7", + "instances": {}, + "instances_count": 0, + "name": "vpc-b14fa4d7", + "snapshots": {}, + "snapshots_count": 0, + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "us-east-1": { + "id": "us-east-1", + "instances_count": 0, + "name": "us-east-1", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "us-east-1", + "security_groups": { + "default": { + "DBSecurityGroupDescription": "default", + "EC2SecurityGroups": [], + "IPRanges": [], + "OwnerId": "430150006394", + "arn": "arn:aws:rds:us-east-1:430150006394:secgrp:default", + "name": "default" + } + }, + "security_groups_count": 1, + "snapshots_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-ba1cbdc7": { + "arn": "arn:aws:vpc:us-east-1:430150006394:virtual-private-cloud/vpc-ba1cbdc7", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-ba1cbdc7", + "instances": {}, + "instances_count": 0, + "name": "vpc-ba1cbdc7", + "snapshots": {}, + "snapshots_count": 0, + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "us-east-2": { + "id": "us-east-2", + "instances_count": 0, + "name": "us-east-2", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "us-east-2", + "security_groups": { + "default": { + "DBSecurityGroupDescription": "default", + "EC2SecurityGroups": [], + "IPRanges": [], + "OwnerId": "430150006394", + "arn": "arn:aws:rds:us-east-2:430150006394:secgrp:default", + "name": "default" + } + }, + "security_groups_count": 1, + "snapshots_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-e429ad8f": { + "arn": "arn:aws:vpc:us-east-2:430150006394:virtual-private-cloud/vpc-e429ad8f", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-e429ad8f", + "instances": {}, + "instances_count": 0, + "name": "vpc-e429ad8f", + "snapshots": {}, + "snapshots_count": 0, + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "us-west-1": { + "id": "us-west-1", + "instances_count": 0, + "name": "us-west-1", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "us-west-1", + "security_groups": { + "default": { + "DBSecurityGroupDescription": "default", + "EC2SecurityGroups": [], + "IPRanges": [], + "OwnerId": "430150006394", + "arn": "arn:aws:rds:us-west-1:430150006394:secgrp:default", + "name": "default" + } + }, + "security_groups_count": 1, + "snapshots_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-6e6fa508": { + "arn": "arn:aws:vpc:us-west-1:430150006394:virtual-private-cloud/vpc-6e6fa508", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-6e6fa508", + "instances": {}, + "instances_count": 0, + "name": "vpc-6e6fa508", + "snapshots": {}, + "snapshots_count": 0, + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + }, + "us-west-2": { + "id": "us-west-2", + "instances_count": 0, + "name": "us-west-2", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "us-west-2", + "security_groups": { + "default": { + "DBSecurityGroupDescription": "default", + "EC2SecurityGroups": [], + "IPRanges": [], + "OwnerId": "430150006394", + "arn": "arn:aws:rds:us-west-2:430150006394:secgrp:default", + "name": "default" + } + }, + "security_groups_count": 1, + "snapshots_count": 0, + "subnet_groups_count": 0, + "vpcs": { + "vpc-d45709ac": { + "arn": "arn:aws:vpc:us-west-2:430150006394:virtual-private-cloud/vpc-d45709ac", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-d45709ac", + "instances": {}, + "instances_count": 0, + "name": "vpc-d45709ac", + "snapshots": {}, + "snapshots_count": 0, + "state": "available", + "subnet_groups": {}, + "subnet_groups_count": 0 + } + }, + "vpcs_count": 1 + } + }, + "regions_count": 17, + "security_groups_count": 17, + "snapshots_count": 0, + "subnet_groups_count": 0 + }, + "redshift": { + "filters": {}, + "findings": { + "redshift-cluster-database-not-encrypted": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Clusters", + "description": "Cluster Database Encryption Disabled", + "flagged_items": 0, + "id_suffix": "Encrypted", + "items": [], + "level": "warning", + "path": "redshift.regions.id.vpcs.id.clusters.id", + "rationale": "Data-at-rest should be encrypted.", + "references": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-db-encryption.html" + ], + "remediation": null, + "service": "RedShift" + }, + "redshift-cluster-no-version-upgrade": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Clusters", + "description": "Version Upgrade Disabled", + "flagged_items": 0, + "id_suffix": "AllowVersionUpgrade", + "items": [], + "level": "danger", + "path": "redshift.regions.id.vpcs.id.clusters.id", + "rationale": "Version upgrade is necessary to ensure major version upgrades will be applied automatically to the cluster within the maintenance window.", + "references": [ + "https://docs.aws.amazon.com/redshift/latest/APIReference/API_ModifyCluster.html" + ], + "remediation": null, + "service": "RedShift" + }, + "redshift-cluster-publicly-accessible": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Clusters", + "description": "Cluster Publicly Accessible", + "flagged_items": 0, + "id_suffix": "PubliclyAccessible", + "items": [], + "level": "warning", + "path": "redshift.regions.id.vpcs.id.clusters.id", + "rationale": "Redshift clusters should never be public, as this increases the risk of exposing sensitive data. Public accessibility means that other AWS users can access your cluster and the data stored in it.", + "references": [ + "https://docs.aws.amazon.com/redshift/latest/gsg/getting-started.html" + ], + "remediation": null, + "service": "RedShift" + }, + "redshift-parameter-group-logging-disabled": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Parameter Groups", + "description": "User Activity Logging Disabled", + "flagged_items": 0, + "id_suffix": "enable_user_activity_logging", + "items": [], + "level": "warning", + "path": "redshift.regions.id.parameter_groups.id", + "rationale": "Audit logging is not enabled by default in Amazon Redshift. A lack of user activity logging could impede the ability to investigate issues involving misuse, malicious access or performance.

Note that this rule will only flag non-default parameter groups, as default parameter groups cannot be modified. It is recommended to use custom groups and configure them according to security best practice.", + "references": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html" + ], + "remediation": null, + "service": "RedShift" + }, + "redshift-parameter-group-ssl-not-required": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Parameter Groups", + "description": "SSL Not Required", + "flagged_items": 0, + "id_suffix": "require_ssl", + "items": [], + "level": "danger", + "path": "redshift.regions.id.parameter_groups.id", + "rationale": "Parameter groups associated with Redshift clusters should have the \"require_ssl\" parameter enabled, to ensure that data in transit is encrypted.

Note that this rule will only flag non-default parameter groups, as default parameter groups cannot be modified. It is recommended to use custom groups and configure them according to security best practice.", + "references": [ + "https://docs.aws.amazon.com/redshift/latest/mgmt/connecting-ssl-support.html" + ], + "remediation": null, + "service": "RedShift" + }, + "redshift-security-group-whitelists-all": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Security Groups", + "description": "Security Group Allows All Traffic", + "display_path": "redshift.regions.id.vpcs.id.security_groups.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "redshift.regions.id.vpcs.id.security_groups.id.IPRanges.id.CIDRIP", + "rationale": "The security group allows access to Redshift instances from any source address, which creates a wider attack surface for resources assigned to it. Source address restrictions should be implemented", + "references": null, + "remediation": null, + "service": "RedShift" + } + }, + "parameter_groups_count": 0, + "regions": { + "ap-northeast-1": { + "id": "ap-northeast-1", + "name": "ap-northeast-1", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "ap-northeast-1", + "security_groups": {}, + "security_groups_count": 0, + "vpcs": { + "vpc-0cbc506a": { + "arn": "arn:aws:vpc:ap-northeast-1:430150006394:virtual-private-cloud/vpc-0cbc506a", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-0cbc506a", + "name": "vpc-0cbc506a", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ap-northeast-2": { + "id": "ap-northeast-2", + "name": "ap-northeast-2", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "ap-northeast-2", + "security_groups": {}, + "security_groups_count": 0, + "vpcs": { + "vpc-73f44e18": { + "arn": "arn:aws:vpc:ap-northeast-2:430150006394:virtual-private-cloud/vpc-73f44e18", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-73f44e18", + "name": "vpc-73f44e18", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ap-northeast-3": { + "id": "ap-northeast-3", + "name": "ap-northeast-3", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "ap-northeast-3", + "security_groups": {}, + "security_groups_count": 0, + "vpcs": { + "vpc-47b7dd2e": { + "arn": "arn:aws:vpc:ap-northeast-3:430150006394:virtual-private-cloud/vpc-47b7dd2e", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-47b7dd2e", + "name": "vpc-47b7dd2e", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ap-south-1": { + "id": "ap-south-1", + "name": "ap-south-1", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "ap-south-1", + "security_groups": {}, + "security_groups_count": 0, + "vpcs": { + "vpc-2651a14d": { + "arn": "arn:aws:vpc:ap-south-1:430150006394:virtual-private-cloud/vpc-2651a14d", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-2651a14d", + "name": "vpc-2651a14d", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ap-southeast-1": { + "id": "ap-southeast-1", + "name": "ap-southeast-1", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "ap-southeast-1", + "security_groups": {}, + "security_groups_count": 0, + "vpcs": { + "vpc-04ed1062": { + "arn": "arn:aws:vpc:ap-southeast-1:430150006394:virtual-private-cloud/vpc-04ed1062", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-04ed1062", + "name": "vpc-04ed1062", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ap-southeast-2": { + "id": "ap-southeast-2", + "name": "ap-southeast-2", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "ap-southeast-2", + "security_groups": {}, + "security_groups_count": 0, + "vpcs": { + "vpc-5d22c33b": { + "arn": "arn:aws:vpc:ap-southeast-2:430150006394:virtual-private-cloud/vpc-5d22c33b", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-5d22c33b", + "name": "vpc-5d22c33b", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "ca-central-1": { + "id": "ca-central-1", + "name": "ca-central-1", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "ca-central-1", + "security_groups": {}, + "security_groups_count": 0, + "vpcs": { + "vpc-b5113ddd": { + "arn": "arn:aws:vpc:ca-central-1:430150006394:virtual-private-cloud/vpc-b5113ddd", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-b5113ddd", + "name": "vpc-b5113ddd", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "eu-central-1": { + "id": "eu-central-1", + "name": "eu-central-1", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "eu-central-1", + "security_groups": {}, + "security_groups_count": 0, + "vpcs": { + "vpc-78b43312": { + "arn": "arn:aws:vpc:eu-central-1:430150006394:virtual-private-cloud/vpc-78b43312", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-78b43312", + "name": "vpc-78b43312", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "eu-north-1": { + "id": "eu-north-1", + "name": "eu-north-1", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "eu-north-1", + "security_groups": {}, + "security_groups_count": 0, + "vpcs": { + "vpc-fa259d93": { + "arn": "arn:aws:vpc:eu-north-1:430150006394:virtual-private-cloud/vpc-fa259d93", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-fa259d93", + "name": "vpc-fa259d93", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "eu-west-1": { + "id": "eu-west-1", + "name": "eu-west-1", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "eu-west-1", + "security_groups": {}, + "security_groups_count": 0, + "vpcs": { + "vpc-f24c7994": { + "arn": "arn:aws:vpc:eu-west-1:430150006394:virtual-private-cloud/vpc-f24c7994", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-f24c7994", + "name": "vpc-f24c7994", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "eu-west-2": { + "id": "eu-west-2", + "name": "eu-west-2", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "eu-west-2", + "security_groups": {}, + "security_groups_count": 0, + "vpcs": { + "vpc-3fa2fa57": { + "arn": "arn:aws:vpc:eu-west-2:430150006394:virtual-private-cloud/vpc-3fa2fa57", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-3fa2fa57", + "name": "vpc-3fa2fa57", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "eu-west-3": { + "id": "eu-west-3", + "name": "eu-west-3", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "eu-west-3", + "security_groups": {}, + "security_groups_count": 0, + "vpcs": { + "vpc-87d3fdee": { + "arn": "arn:aws:vpc:eu-west-3:430150006394:virtual-private-cloud/vpc-87d3fdee", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-87d3fdee", + "name": "vpc-87d3fdee", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "sa-east-1": { + "id": "sa-east-1", + "name": "sa-east-1", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "sa-east-1", + "security_groups": {}, + "security_groups_count": 0, + "vpcs": { + "vpc-b14fa4d7": { + "arn": "arn:aws:vpc:sa-east-1:430150006394:virtual-private-cloud/vpc-b14fa4d7", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-b14fa4d7", + "name": "vpc-b14fa4d7", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "us-east-1": { + "id": "us-east-1", + "name": "us-east-1", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "us-east-1", + "security_groups": {}, + "security_groups_count": 0, + "vpcs": { + "vpc-ba1cbdc7": { + "arn": "arn:aws:vpc:us-east-1:430150006394:virtual-private-cloud/vpc-ba1cbdc7", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-ba1cbdc7", + "name": "vpc-ba1cbdc7", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "us-east-2": { + "id": "us-east-2", + "name": "us-east-2", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "us-east-2", + "security_groups": {}, + "security_groups_count": 0, + "vpcs": { + "vpc-e429ad8f": { + "arn": "arn:aws:vpc:us-east-2:430150006394:virtual-private-cloud/vpc-e429ad8f", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-e429ad8f", + "name": "vpc-e429ad8f", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "us-west-1": { + "id": "us-west-1", + "name": "us-west-1", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "us-west-1", + "security_groups": {}, + "security_groups_count": 0, + "vpcs": { + "vpc-6e6fa508": { + "arn": "arn:aws:vpc:us-west-1:430150006394:virtual-private-cloud/vpc-6e6fa508", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-6e6fa508", + "name": "vpc-6e6fa508", + "state": "available" + } + }, + "vpcs_count": 1 + }, + "us-west-2": { + "id": "us-west-2", + "name": "us-west-2", + "parameter_groups": {}, + "parameter_groups_count": 0, + "region": "us-west-2", + "security_groups": {}, + "security_groups_count": 0, + "vpcs": { + "vpc-d45709ac": { + "arn": "arn:aws:vpc:us-west-2:430150006394:virtual-private-cloud/vpc-d45709ac", + "cidr_block": "172.31.0.0/16", + "clusters": {}, + "clusters_count": 0, + "default": true, + "id": "vpc-d45709ac", + "name": "vpc-d45709ac", + "state": "available" + } + }, + "vpcs_count": 1 + } + }, + "regions_count": 17, + "security_groups_count": 0 + }, + "route53": { + "domains_count": 0, + "filters": {}, + "findings": { + "route53-domain-no-autorenew": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Domains", + "description": "Automatic Renewal Not Set for Domain", + "flagged_items": 0, + "id_suffix": "auto_renew", + "items": [], + "level": "danger", + "path": "route53.regions.id.domains.id", + "rationale": "Enable automatic renewal to remove the risk of losing control over your domain names.", + "references": [ + "https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-enable-disable-auto-renewal.html" + ], + "remediation": null, + "service": "Route53" + }, + "route53-domain-no-transferlock": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Domains", + "description": "Domain Transfer Not Locked", + "flagged_items": 0, + "id_suffix": "transfer_lock", + "items": [], + "level": "danger", + "path": "route53.regions.id.domains.id", + "rationale": "A domain lock prevents someone from transferring your domain to another registrar without your permission.", + "references": [ + "https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-lock.html" + ], + "remediation": null, + "service": "Route53" + }, + "route53-domain-transferlock-not-authorized": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Domains", + "description": "Domain Transfer Lock Not Supported by TLD", + "flagged_items": 0, + "id_suffix": "transfer_lock", + "items": [], + "level": "danger", + "path": "route53.regions.id.domains.id", + "rationale": "A domain lock prevents someone from transferring your domain to another registrar without your permission. Your domain's TLD does not support this feature.", + "references": [ + "https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/registrar-tld-list.html" + ], + "remediation": null, + "service": "Route53" + } + }, + "hosted_zones_count": 0, + "regions": { + "us-east-1": { + "domains": {}, + "domains_count": 0, + "hosted_zones": {}, + "hosted_zones_count": 0, + "id": "us-east-1", + "name": "us-east-1", + "region": "us-east-1" + } + }, + "regions_count": 1 + }, + "s3": { + "buckets": { + "49db3c2810ba973e0a870403be5c8eac6157223c": { + "CreationDate": "2020-06-25 05:33:02+00:00", + "arn": "arn:aws:s3:::wikipedia-bff/*", + "default_encryption_enabled": false, + "grantees": { + "a63aba602186926290f04476eec5c7dd1bbce3fd75694d0eec1431b54a978e0e": { + "DisplayName": "damien.carol", + "permissions": { + "read": true, + "read_acp": true, + "write": true, + "write_acp": true + } + } + }, + "groups": { + "AGPAIW3P3726RZDVZBZL2": { + "inline_policies": { + "58cd3df92811df89e93933e00cd5a76813cf6258": { + "condition": null + } + } + } + }, + "groups_count": 1, + "id": "49db3c2810ba973e0a870403be5c8eac6157223c", + "logging": "Disabled", + "name": "wikipedia-bff", + "public_access_block_configuration": { + "BlockPublicAcls": true, + "BlockPublicPolicy": true, + "IgnorePublicAcls": true, + "RestrictPublicBuckets": true + }, + "region": "eu-west-1", + "roles": { + "AROAI265GPNVMDZAKJPPA": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + }, + "AROAIXBSWIKGEEDLMO53I": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + }, + "AROAJCHEQKY4NYQFQWP5K": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + }, + "AROAJCXETX2ROIWUKOPGG": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "AROAWIJXQGZ5OSPI4PBJL": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + }, + "roles_count": 5, + "secure_transport_enabled": false, + "version_mfa_delete_enabled": false, + "versioning_status_enabled": false, + "web_hosting_enabled": false + }, + "5eb65545fecb56b5aad0f2e39ff0adfed160cbd2": { + "CreationDate": "2020-06-23 20:19:43+00:00", + "arn": "arn:aws:s3:::aws-logs-430150006394-eu-west-1/*", + "default_encryption_enabled": false, + "grantees": { + "a63aba602186926290f04476eec5c7dd1bbce3fd75694d0eec1431b54a978e0e": { + "DisplayName": "damien.carol", + "permissions": { + "read": true, + "read_acp": true, + "write": true, + "write_acp": true + } + } + }, + "groups": { + "AGPAIW3P3726RZDVZBZL2": { + "inline_policies": { + "58cd3df92811df89e93933e00cd5a76813cf6258": { + "condition": null + } + } + } + }, + "groups_count": 1, + "id": "5eb65545fecb56b5aad0f2e39ff0adfed160cbd2", + "logging": "Disabled", + "name": "aws-logs-430150006394-eu-west-1", + "public_access_block_configuration": { + "BlockPublicAcls": false, + "BlockPublicPolicy": false, + "IgnorePublicAcls": false, + "RestrictPublicBuckets": false + }, + "region": "eu-west-1", + "roles": { + "AROAI265GPNVMDZAKJPPA": { + "policies": { + "ANPAIGALS5RCDLZLB3PGS": { + "condition": null + } + } + }, + "AROAIXBSWIKGEEDLMO53I": { + "policies": { + "ANPAIDI2BQT2LKXZG36TW": { + "condition": null + } + } + }, + "AROAJCHEQKY4NYQFQWP5K": { + "policies": { + "ANPAJH4QJ2WMHBOB47BUE": { + "condition": null + } + } + }, + "AROAJCXETX2ROIWUKOPGG": { + "policies": { + "ANPAJ7W6266ELXF5MISDS": { + "condition": null + } + } + }, + "AROAWIJXQGZ5OSPI4PBJL": { + "policies": { + "ANPAZKAPJZG4CAIXDDRI2": { + "condition": null + } + } + } + }, + "roles_count": 5, + "secure_transport_enabled": false, + "version_mfa_delete_enabled": false, + "versioning_status_enabled": false, + "web_hosting_enabled": false + } + }, + "buckets_count": 2, + "filters": { + "s3-bucket-website-enabled": { + "checked_items": 2, + "compliance": null, + "dashboard_name": "Buckets", + "description": "Bucket with static website enabled", + "display_path": "s3.buckets.id", + "flagged_items": 0, + "id_suffix": "web_hosting_enabled", + "items": [], + "level": "", + "path": "s3.buckets.id", + "rationale": null, + "references": null, + "remediation": null, + "service": "S3" + } + }, + "findings": { + "s3-bucket-AllUsers-read": { + "checked_items": 2, + "compliance": null, + "dashboard_name": "Bucket ACLs", + "description": "Bucket world-listable (anonymous)", + "display_path": "s3.buckets.id", + "flagged_items": 0, + "id_suffix": "read", + "items": [], + "level": "warning", + "path": "s3.buckets.id.grantees.id", + "rationale": "An S3 bucket has been found that was accessible for AllUsers. If sensitive information is stored in this bucket, it could be at risk of being accessed by potential attackers.", + "references": null, + "remediation": null, + "service": "S3" + }, + "s3-bucket-AllUsers-read_acp": { + "checked_items": 2, + "compliance": null, + "dashboard_name": "Bucket ACLs", + "description": "Bucket's permissions world-readable (anonymous)", + "display_path": "s3.buckets.id", + "flagged_items": 0, + "id_suffix": "read_acp", + "items": [], + "level": "warning", + "path": "s3.buckets.id.grantees.id", + "rationale": "An S3 bucket has been found that was accessible for AllUsers. If sensitive information is stored in this bucket, it could be at risk of being accessed by potential attackers.", + "references": null, + "remediation": null, + "service": "S3" + }, + "s3-bucket-AllUsers-write": { + "checked_items": 2, + "compliance": null, + "dashboard_name": "Bucket ACLs", + "description": "Bucket world-writable (anonymous)", + "display_path": "s3.buckets.id", + "flagged_items": 0, + "id_suffix": "write", + "items": [], + "level": "danger", + "path": "s3.buckets.id.grantees.id", + "rationale": "An S3 bucket has been found that was accessible for AllUsers. If sensitive information is stored in this bucket, it could be at risk of being accessed by potential attackers.", + "references": null, + "remediation": null, + "service": "S3" + }, + "s3-bucket-AllUsers-write_acp": { + "checked_items": 2, + "compliance": null, + "dashboard_name": "Bucket ACLs", + "description": "Bucket's permissions world-writable (anonymous)", + "display_path": "s3.buckets.id", + "flagged_items": 0, + "id_suffix": "write_acp", + "items": [], + "level": "danger", + "path": "s3.buckets.id.grantees.id", + "rationale": "An S3 bucket has been found that was accessible for AllUsers. If sensitive information is stored in this bucket, it could be at risk of being accessed by potential attackers.", + "references": null, + "remediation": null, + "service": "S3" + }, + "s3-bucket-AuthenticatedUsers-read": { + "checked_items": 2, + "compliance": null, + "dashboard_name": "Bucket ACLs", + "description": "Bucket world-listable", + "display_path": "s3.buckets.id", + "flagged_items": 0, + "id_suffix": "read", + "items": [], + "level": "danger", + "path": "s3.buckets.id.grantees.id", + "rationale": "An S3 bucket has been found that was accessible for AuthenticatedUsers. If sensitive information is stored in this bucket, it could be at risk of being accessed by potential attackers.", + "references": null, + "remediation": null, + "service": "S3" + }, + "s3-bucket-AuthenticatedUsers-read_acp": { + "checked_items": 2, + "compliance": null, + "dashboard_name": "Bucket ACLs", + "description": "Bucket's permissions world-readable", + "display_path": "s3.buckets.id", + "flagged_items": 0, + "id_suffix": "read_acp", + "items": [], + "level": "warning", + "path": "s3.buckets.id.grantees.id", + "rationale": "An S3 bucket has been found that was accessible for AuthenticatedUsers. If sensitive information is stored in this bucket, it could be at risk of being accessed by potential attackers.", + "references": null, + "remediation": null, + "service": "S3" + }, + "s3-bucket-AuthenticatedUsers-write": { + "checked_items": 2, + "compliance": null, + "dashboard_name": "Bucket ACLs", + "description": "Bucket world-writable", + "display_path": "s3.buckets.id", + "flagged_items": 0, + "id_suffix": "write", + "items": [], + "level": "danger", + "path": "s3.buckets.id.grantees.id", + "rationale": "An S3 bucket has been found that was accessible for AuthenticatedUsers. If sensitive information is stored in this bucket, it could be at risk of being accessed by potential attackers.", + "references": null, + "remediation": null, + "service": "S3" + }, + "s3-bucket-AuthenticatedUsers-write_acp": { + "checked_items": 2, + "compliance": null, + "dashboard_name": "Bucket ACLs", + "description": "Bucket's permissions world-writable", + "display_path": "s3.buckets.id", + "flagged_items": 0, + "id_suffix": "write_acp", + "items": [], + "level": "danger", + "path": "s3.buckets.id.grantees.id", + "rationale": "An S3 bucket has been found that was accessible for AuthenticatedUsers. If sensitive information is stored in this bucket, it could be at risk of being accessed by potential attackers.", + "references": null, + "remediation": null, + "service": "S3" + }, + "s3-bucket-allowing-cleartext": { + "checked_items": 2, + "compliance": null, + "dashboard_name": "Buckets", + "description": "Bucket Allowing Clear Text (HTTP) Communication", + "flagged_items": 2, + "id_suffix": "secure_transport_enabled", + "items": [ + "s3.buckets.5eb65545fecb56b5aad0f2e39ff0adfed160cbd2.secure_transport_enabled", + "s3.buckets.49db3c2810ba973e0a870403be5c8eac6157223c.secure_transport_enabled" + ], + "level": "warning", + "path": "s3.buckets.id", + "rationale": "If HTTPS is not enforced on the bucket policy, communication between clients and S3 buckets can use unencrypted HTTP. As a result, sensitive information could be transmitted in clear text over the network|Internet.", + "references": [ + "https://docs.aws.amazon.com/AmazonS3/latest/dev/security-best-practices.html" + ], + "remediation": null, + "service": "S3" + }, + "s3-bucket-no-default-encryption": { + "checked_items": 2, + "compliance": null, + "dashboard_name": "Buckets", + "description": "Bucket without Default Encryption Enabled", + "flagged_items": 2, + "id_suffix": "default_encryption_enabled", + "items": [ + "s3.buckets.5eb65545fecb56b5aad0f2e39ff0adfed160cbd2.default_encryption_enabled", + "s3.buckets.49db3c2810ba973e0a870403be5c8eac6157223c.default_encryption_enabled" + ], + "level": "warning", + "path": "s3.buckets.id", + "rationale": "Amazon S3 default encryption provides a way to set the default encryption behavior for an S3 bucket. This will ensure data-at-rest is encrypted", + "references": [ + "https://docs.aws.amazon.com/AmazonS3/latest/dev/security-best-practices.html", + "https://docs.aws.amazon.com/AmazonS3/latest/dev/bucket-encryption.html" + ], + "remediation": null, + "service": "S3" + }, + "s3-bucket-no-logging": { + "checked_items": 2, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.6", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.6", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.6", + "version": "1.2.0" + } + ], + "dashboard_name": "Buckets", + "description": "Bucket Access Logging Disabled", + "flagged_items": 2, + "id_suffix": "logging", + "items": [ + "s3.buckets.5eb65545fecb56b5aad0f2e39ff0adfed160cbd2.logging", + "s3.buckets.49db3c2810ba973e0a870403be5c8eac6157223c.logging" + ], + "level": "warning", + "path": "s3.buckets.id", + "rationale": "Server access logging provides detailed records of the requests that are made to a bucket. Server access logs can assist you in security and access audits, help you learn about your customer base, and understand your Amazon S3 bill.

Note: CloudTrail data events can be used in place of S3 bucket logging. If that is the case, this finding can be considered a false positive.", + "references": [ + "https://docs.aws.amazon.com/AmazonS3/latest/dev/security-best-practices.html" + ], + "remediation": "Ensure that S3 buckets have Logging enabled", + "service": "S3" + }, + "s3-bucket-no-mfa-delete": { + "checked_items": 2, + "compliance": null, + "dashboard_name": "Buckets", + "description": "Bucket without MFA Delete", + "flagged_items": 2, + "id_suffix": "mfa_delete", + "items": [ + "s3.buckets.5eb65545fecb56b5aad0f2e39ff0adfed160cbd2.mfa_delete", + "s3.buckets.49db3c2810ba973e0a870403be5c8eac6157223c.mfa_delete" + ], + "level": "warning", + "path": "s3.buckets.id", + "rationale": "Enable MFA delete to help protect objects from accidental or unauthorized deletion. It should be noted that MFA Delete can only be configured on buckets that have versioning enabled.", + "references": [ + "https://docs.aws.amazon.com/AmazonS3/latest/dev/security-best-practices.html" + ], + "remediation": null, + "service": "S3" + }, + "s3-bucket-no-versioning": { + "checked_items": 2, + "compliance": null, + "dashboard_name": "Buckets", + "description": "Bucket without Versioning", + "flagged_items": 2, + "id_suffix": "versioning", + "items": [ + "s3.buckets.5eb65545fecb56b5aad0f2e39ff0adfed160cbd2.versioning", + "s3.buckets.49db3c2810ba973e0a870403be5c8eac6157223c.versioning" + ], + "level": "warning", + "path": "s3.buckets.id", + "rationale": "Versioning is a means of keeping multiple variants of an object in the same bucket. With versioning, you can easily recover from both unintended user actions and application failures.", + "references": [ + "https://docs.aws.amazon.com/AmazonS3/latest/dev/security-best-practices.html" + ], + "remediation": null, + "service": "S3" + }, + "s3-bucket-world-Delete-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Bucket Policy Statements", + "description": "Delete Actions Authorized to All Principals", + "display_path": "s3.buckets.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "s3.buckets.id.policy.Statement.id", + "rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.", + "references": null, + "remediation": null, + "service": "S3" + }, + "s3-bucket-world-Get-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Bucket Policy Statements", + "description": "Get Actions Authorized to All Principals", + "display_path": "s3.buckets.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "s3.buckets.id.policy.Statement.id", + "rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.", + "references": null, + "remediation": null, + "service": "S3" + }, + "s3-bucket-world-List-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Bucket Policy Statements", + "description": "List Actions Authorized to All Principals", + "display_path": "s3.buckets.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "s3.buckets.id.policy.Statement.id", + "rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.", + "references": null, + "remediation": null, + "service": "S3" + }, + "s3-bucket-world-Put-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Bucket Policy Statements", + "description": "Put Actions Authorized to All Principals", + "display_path": "s3.buckets.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "s3.buckets.id.policy.Statement.id", + "rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.", + "references": null, + "remediation": null, + "service": "S3" + }, + "s3-bucket-world-policy-star": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.3", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.3", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.3", + "version": "1.2.0" + } + ], + "dashboard_name": "Bucket Policy Statements", + "description": "All Actions Authorized to All Principals", + "display_path": "s3.buckets.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "s3.buckets.id.policy.Statement.id", + "rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.", + "references": null, + "remediation": "Remove any Statement having an Effect set to Allow and a Principal set to \"*\" or {\"AWS\":\"*\"} in the affected bucket policy", + "service": "S3" + } + }, + "public_access_block_configuration": { + "BlockPublicAcls": false, + "BlockPublicPolicy": false, + "IgnorePublicAcls": false, + "RestrictPublicBuckets": false + } + }, + "secretsmanager": { + "filters": {}, + "findings": {}, + "regions": { + "ap-northeast-1": { + "id": "ap-northeast-1", + "name": "ap-northeast-1", + "region": "ap-northeast-1", + "secrets": {}, + "secrets_count": 0 + }, + "ap-northeast-2": { + "id": "ap-northeast-2", + "name": "ap-northeast-2", + "region": "ap-northeast-2", + "secrets": {}, + "secrets_count": 0 + }, + "ap-northeast-3": { + "id": "ap-northeast-3", + "name": "ap-northeast-3", + "region": "ap-northeast-3", + "secrets": {}, + "secrets_count": 0 + }, + "ap-south-1": { + "id": "ap-south-1", + "name": "ap-south-1", + "region": "ap-south-1", + "secrets": {}, + "secrets_count": 0 + }, + "ap-southeast-1": { + "id": "ap-southeast-1", + "name": "ap-southeast-1", + "region": "ap-southeast-1", + "secrets": {}, + "secrets_count": 0 + }, + "ap-southeast-2": { + "id": "ap-southeast-2", + "name": "ap-southeast-2", + "region": "ap-southeast-2", + "secrets": {}, + "secrets_count": 0 + }, + "ca-central-1": { + "id": "ca-central-1", + "name": "ca-central-1", + "region": "ca-central-1", + "secrets": {}, + "secrets_count": 0 + }, + "eu-central-1": { + "id": "eu-central-1", + "name": "eu-central-1", + "region": "eu-central-1", + "secrets": {}, + "secrets_count": 0 + }, + "eu-north-1": { + "id": "eu-north-1", + "name": "eu-north-1", + "region": "eu-north-1", + "secrets": {}, + "secrets_count": 0 + }, + "eu-west-1": { + "id": "eu-west-1", + "name": "eu-west-1", + "region": "eu-west-1", + "secrets": {}, + "secrets_count": 0 + }, + "eu-west-2": { + "id": "eu-west-2", + "name": "eu-west-2", + "region": "eu-west-2", + "secrets": {}, + "secrets_count": 0 + }, + "eu-west-3": { + "id": "eu-west-3", + "name": "eu-west-3", + "region": "eu-west-3", + "secrets": {}, + "secrets_count": 0 + }, + "sa-east-1": { + "id": "sa-east-1", + "name": "sa-east-1", + "region": "sa-east-1", + "secrets": {}, + "secrets_count": 0 + }, + "us-east-1": { + "id": "us-east-1", + "name": "us-east-1", + "region": "us-east-1", + "secrets": {}, + "secrets_count": 0 + }, + "us-east-2": { + "id": "us-east-2", + "name": "us-east-2", + "region": "us-east-2", + "secrets": {}, + "secrets_count": 0 + }, + "us-west-1": { + "id": "us-west-1", + "name": "us-west-1", + "region": "us-west-1", + "secrets": {}, + "secrets_count": 0 + }, + "us-west-2": { + "id": "us-west-2", + "name": "us-west-2", + "region": "us-west-2", + "secrets": {}, + "secrets_count": 0 + } + }, + "regions_count": 17, + "secrets_count": 0 + }, + "ses": { + "filters": {}, + "findings": { + "ses-identity-dkim-not-enabled": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Identities", + "description": "DKIM Not Enabled", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "ses.regions.id.identities.id", + "rationale": "DKIM signing is not enabled for emails sent from the identity.", + "references": [ + "https://docs.aws.amazon.com/ses/latest/DeveloperGuide/send-email-authentication-dkim.html" + ], + "remediation": null, + "service": "SES" + }, + "ses-identity-dkim-not-verified": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Identities", + "description": "DKIM Not Verified", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "ses.regions.id.identities.id", + "rationale": "Amazon SES has not verified the DKIM DNS records (tokens) published in the domain name's DNS.", + "references": [ + "https://docs.aws.amazon.com/ses/latest/DeveloperGuide/send-email-authentication-dkim.html" + ], + "remediation": null, + "service": "SES" + }, + "ses-identity-world-SendEmail-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Statements", + "description": "SendEmail Authorized to All Principals", + "display_path": "ses.regions.id.identities.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "ses.regions.id.identities.id.policies.id.Statement.id", + "rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.", + "references": null, + "remediation": null, + "service": "SES" + }, + "ses-identity-world-SendRawEmail-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Statements", + "description": "SendRawEmail Authorized to All Principals", + "display_path": "ses.regions.id.identities.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "ses.regions.id.identities.id.policies.id.Statement.id", + "rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.", + "references": null, + "remediation": null, + "service": "SES" + } + }, + "identities_count": 0, + "regions": { + "ap-south-1": { + "id": "ap-south-1", + "identities": {}, + "identities_count": 0, + "name": "ap-south-1", + "region": "ap-south-1" + }, + "ap-southeast-2": { + "id": "ap-southeast-2", + "identities": {}, + "identities_count": 0, + "name": "ap-southeast-2", + "region": "ap-southeast-2" + }, + "eu-central-1": { + "id": "eu-central-1", + "identities": {}, + "identities_count": 0, + "name": "eu-central-1", + "region": "eu-central-1" + }, + "eu-west-1": { + "id": "eu-west-1", + "identities": {}, + "identities_count": 0, + "name": "eu-west-1", + "region": "eu-west-1" + }, + "us-east-1": { + "id": "us-east-1", + "identities": {}, + "identities_count": 0, + "name": "us-east-1", + "region": "us-east-1" + }, + "us-west-2": { + "id": "us-west-2", + "identities": {}, + "identities_count": 0, + "name": "us-west-2", + "region": "us-west-2" + } + }, + "regions_count": 6 + }, + "sns": { + "filters": {}, + "findings": { + "sns-topic-world-AddPermission-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Statements", + "description": "AddPermission Authorized to All Principals", + "display_path": "sns.regions.id.topics.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "sns.regions.id.topics.id.Policy.Statement.id", + "rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.", + "references": null, + "remediation": null, + "service": "SNS" + }, + "sns-topic-world-DeleteTopic-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Statements", + "description": "DeleteTopic Authorized to All Principals", + "display_path": "sns.regions.id.topics.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "sns.regions.id.topics.id.Policy.Statement.id", + "rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.", + "references": null, + "remediation": null, + "service": "SNS" + }, + "sns-topic-world-Publish-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Statements", + "description": "Publish Authorized to All Principals", + "display_path": "sns.regions.id.topics.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "sns.regions.id.topics.id.Policy.Statement.id", + "rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.", + "references": null, + "remediation": null, + "service": "SNS" + }, + "sns-topic-world-Receive-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Statements", + "description": "Receive Authorized to All Principals", + "display_path": "sns.regions.id.topics.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "sns.regions.id.topics.id.Policy.Statement.id", + "rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.", + "references": null, + "remediation": null, + "service": "SNS" + }, + "sns-topic-world-RemovePermission-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Statements", + "description": "RemovePermission Authorized to All Principals", + "display_path": "sns.regions.id.topics.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "sns.regions.id.topics.id.Policy.Statement.id", + "rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.", + "references": null, + "remediation": null, + "service": "SNS" + }, + "sns-topic-world-SetTopicAttributes-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Statements", + "description": "SetTopicAttributes Authorized to All Principals", + "display_path": "sns.regions.id.topics.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "sns.regions.id.topics.id.Policy.Statement.id", + "rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.", + "references": null, + "remediation": null, + "service": "SNS" + }, + "sns-topic-world-Subscribe-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Statements", + "description": "Subscribe Authorized to All Principals", + "display_path": "sns.regions.id.topics.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "sns.regions.id.topics.id.Policy.Statement.id", + "rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.", + "references": null, + "remediation": null, + "service": "SNS" + } + }, + "regions": { + "ap-northeast-1": { + "id": "ap-northeast-1", + "name": "ap-northeast-1", + "region": "ap-northeast-1", + "topics": {}, + "topics_count": 0 + }, + "ap-northeast-2": { + "id": "ap-northeast-2", + "name": "ap-northeast-2", + "region": "ap-northeast-2", + "topics": {}, + "topics_count": 0 + }, + "ap-northeast-3": { + "id": "ap-northeast-3", + "name": "ap-northeast-3", + "region": "ap-northeast-3", + "topics": {}, + "topics_count": 0 + }, + "ap-south-1": { + "id": "ap-south-1", + "name": "ap-south-1", + "region": "ap-south-1", + "topics": {}, + "topics_count": 0 + }, + "ap-southeast-1": { + "id": "ap-southeast-1", + "name": "ap-southeast-1", + "region": "ap-southeast-1", + "topics": {}, + "topics_count": 0 + }, + "ap-southeast-2": { + "id": "ap-southeast-2", + "name": "ap-southeast-2", + "region": "ap-southeast-2", + "topics": {}, + "topics_count": 0 + }, + "ca-central-1": { + "id": "ca-central-1", + "name": "ca-central-1", + "region": "ca-central-1", + "topics": {}, + "topics_count": 0 + }, + "eu-central-1": { + "id": "eu-central-1", + "name": "eu-central-1", + "region": "eu-central-1", + "topics": {}, + "topics_count": 0 + }, + "eu-north-1": { + "id": "eu-north-1", + "name": "eu-north-1", + "region": "eu-north-1", + "topics": {}, + "topics_count": 0 + }, + "eu-west-1": { + "id": "eu-west-1", + "name": "eu-west-1", + "region": "eu-west-1", + "topics": {}, + "topics_count": 0 + }, + "eu-west-2": { + "id": "eu-west-2", + "name": "eu-west-2", + "region": "eu-west-2", + "topics": {}, + "topics_count": 0 + }, + "eu-west-3": { + "id": "eu-west-3", + "name": "eu-west-3", + "region": "eu-west-3", + "topics": {}, + "topics_count": 0 + }, + "sa-east-1": { + "id": "sa-east-1", + "name": "sa-east-1", + "region": "sa-east-1", + "topics": {}, + "topics_count": 0 + }, + "us-east-1": { + "id": "us-east-1", + "name": "us-east-1", + "region": "us-east-1", + "topics": {}, + "topics_count": 0 + }, + "us-east-2": { + "id": "us-east-2", + "name": "us-east-2", + "region": "us-east-2", + "topics": {}, + "topics_count": 0 + }, + "us-west-1": { + "id": "us-west-1", + "name": "us-west-1", + "region": "us-west-1", + "topics": {}, + "topics_count": 0 + }, + "us-west-2": { + "id": "us-west-2", + "name": "us-west-2", + "region": "us-west-2", + "topics": {}, + "topics_count": 0 + } + }, + "regions_count": 17, + "topics_count": 0 + }, + "sqs": { + "filters": {}, + "findings": { + "sqs-queue-world-ChangeMessageVisibility-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Statements", + "description": "ChangeMessageVisibility Authorized to All Principals", + "display_path": "sqs.regions.id.queues.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "sqs.regions.id.queues.id.Policy.Statement.id", + "rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.", + "references": null, + "remediation": null, + "service": "SQS" + }, + "sqs-queue-world-DeleteMessage-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Statements", + "description": "DeleteMessage Authorized to All Principals", + "display_path": "sqs.regions.id.queues.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "sqs.regions.id.queues.id.Policy.Statement.id", + "rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.", + "references": null, + "remediation": null, + "service": "SQS" + }, + "sqs-queue-world-GetQueueAttributes-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Statements", + "description": "GetQueueAttributes Authorized to All Principals", + "display_path": "sqs.regions.id.queues.id", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "sqs.regions.id.queues.id.Policy.Statement.id", + "rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.", + "references": null, + "remediation": null, + "service": "SQS" + }, + "sqs-queue-world-GetQueueUrl-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Statements", + "description": "GetQueueUrl Authorized to All Principals", + "display_path": "sqs.regions.id.queues.id", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "sqs.regions.id.queues.id.Policy.Statement.id", + "rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.", + "references": null, + "remediation": null, + "service": "SQS" + }, + "sqs-queue-world-PurgeQueue-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Statements", + "description": "PurgeQueue Authorized to All Principals", + "display_path": "sqs.regions.id.queues.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "sqs.regions.id.queues.id.Policy.Statement.id", + "rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.", + "references": null, + "remediation": null, + "service": "SQS" + }, + "sqs-queue-world-ReceiveMessage-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Statements", + "description": "ReceiveMessage Authorized to All Principals", + "display_path": "sqs.regions.id.queues.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "sqs.regions.id.queues.id.Policy.Statement.id", + "rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.", + "references": null, + "remediation": null, + "service": "SQS" + }, + "sqs-queue-world-SendMessage-policy": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Statements", + "description": "SendMessage Authorized to All Principals", + "display_path": "sqs.regions.id.queues.id", + "flagged_items": 0, + "items": [], + "level": "danger", + "path": "sqs.regions.id.queues.id.Policy.Statement.id", + "rationale": "Allowing IAM actions to all principals is contrary to the principle of least privilege and presents an opportunity for abuse. This policy should be reviewed to ensure it is secure and in line with the resource's intended use.", + "references": null, + "remediation": null, + "service": "SQS" + } + }, + "queues_count": 0, + "regions": { + "ap-northeast-1": { + "id": "ap-northeast-1", + "name": "ap-northeast-1", + "queues": {}, + "queues_count": 0, + "region": "ap-northeast-1" + }, + "ap-northeast-2": { + "id": "ap-northeast-2", + "name": "ap-northeast-2", + "queues": {}, + "queues_count": 0, + "region": "ap-northeast-2" + }, + "ap-northeast-3": { + "id": "ap-northeast-3", + "name": "ap-northeast-3", + "queues": {}, + "queues_count": 0, + "region": "ap-northeast-3" + }, + "ap-south-1": { + "id": "ap-south-1", + "name": "ap-south-1", + "queues": {}, + "queues_count": 0, + "region": "ap-south-1" + }, + "ap-southeast-1": { + "id": "ap-southeast-1", + "name": "ap-southeast-1", + "queues": {}, + "queues_count": 0, + "region": "ap-southeast-1" + }, + "ap-southeast-2": { + "id": "ap-southeast-2", + "name": "ap-southeast-2", + "queues": {}, + "queues_count": 0, + "region": "ap-southeast-2" + }, + "ca-central-1": { + "id": "ca-central-1", + "name": "ca-central-1", + "queues": {}, + "queues_count": 0, + "region": "ca-central-1" + }, + "eu-central-1": { + "id": "eu-central-1", + "name": "eu-central-1", + "queues": {}, + "queues_count": 0, + "region": "eu-central-1" + }, + "eu-north-1": { + "id": "eu-north-1", + "name": "eu-north-1", + "queues": {}, + "queues_count": 0, + "region": "eu-north-1" + }, + "eu-west-1": { + "id": "eu-west-1", + "name": "eu-west-1", + "queues": {}, + "queues_count": 0, + "region": "eu-west-1" + }, + "eu-west-2": { + "id": "eu-west-2", + "name": "eu-west-2", + "queues": {}, + "queues_count": 0, + "region": "eu-west-2" + }, + "eu-west-3": { + "id": "eu-west-3", + "name": "eu-west-3", + "queues": {}, + "queues_count": 0, + "region": "eu-west-3" + }, + "sa-east-1": { + "id": "sa-east-1", + "name": "sa-east-1", + "queues": {}, + "queues_count": 0, + "region": "sa-east-1" + }, + "us-east-1": { + "id": "us-east-1", + "name": "us-east-1", + "queues": {}, + "queues_count": 0, + "region": "us-east-1" + }, + "us-east-2": { + "id": "us-east-2", + "name": "us-east-2", + "queues": {}, + "queues_count": 0, + "region": "us-east-2" + }, + "us-west-1": { + "id": "us-west-1", + "name": "us-west-1", + "queues": {}, + "queues_count": 0, + "region": "us-west-1" + }, + "us-west-2": { + "id": "us-west-2", + "name": "us-west-2", + "queues": {}, + "queues_count": 0, + "region": "us-west-2" + } + }, + "regions_count": 17 + }, + "vpc": { + "filters": {}, + "findings": { + "vpc-custom-network-acls-allow-all-egress": { + "checked_items": 17, + "compliance": null, + "dashboard_name": "Network ACLs", + "description": "Network ACLs Allow All egress Traffic (custom)", + "flagged_items": 0, + "id_suffix": "egress._GET_VALUE_AT_(vpc.regions.id.vpcs.id.network_acls.id.allow_all_egress_traffic)", + "items": [], + "level": "warning", + "path": "vpc.regions.id.vpcs.id.network_acls.id", + "rationale": "Network ACLs are designed to provide a secondary layer of security. Adding a rule that allows all network traffic (all protocols, IPs, and destination) prior to any deny rule defeats the purpose of network ACLs.", + "references": null, + "remediation": null, + "service": "VPC" + }, + "vpc-custom-network-acls-allow-all-ingress": { + "checked_items": 17, + "compliance": null, + "dashboard_name": "Network ACLs", + "description": "Network ACLs Allow All ingress Traffic (custom)", + "flagged_items": 0, + "id_suffix": "ingress._GET_VALUE_AT_(vpc.regions.id.vpcs.id.network_acls.id.allow_all_ingress_traffic)", + "items": [], + "level": "warning", + "path": "vpc.regions.id.vpcs.id.network_acls.id", + "rationale": "Network ACLs are designed to provide a secondary layer of security. Adding a rule that allows all network traffic (all protocols, IPs, and source) prior to any deny rule defeats the purpose of network ACLs.", + "references": null, + "remediation": null, + "service": "VPC" + }, + "vpc-default-network-acls-allow-all-egress": { + "checked_items": 17, + "compliance": null, + "dashboard_name": "Network ACLs", + "description": "Network ACLs Allow All egress Traffic (default)", + "flagged_items": 17, + "id_suffix": "egress._GET_VALUE_AT_(vpc.regions.id.vpcs.id.network_acls.id.allow_all_egress_traffic)", + "items": [ + "vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.network_acls.acl-c777e5a1.egress.100", + "vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.network_acls.acl-75e1951e.egress.100", + "vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.network_acls.acl-bb1b62d2.egress.100", + "vpc.regions.ap-south-1.vpcs.vpc-2651a14d.network_acls.acl-a676adcd.egress.100", + "vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.network_acls.acl-8787e0e1.egress.100", + "vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.network_acls.acl-4e4dc228.egress.100", + "vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.network_acls.acl-63e1ed0b.egress.100", + "vpc.regions.eu-central-1.vpcs.vpc-78b43312.network_acls.acl-6ebcec04.egress.100", + "vpc.regions.eu-north-1.vpcs.vpc-fa259d93.network_acls.acl-dfb10ab6.egress.100", + "vpc.regions.eu-west-1.vpcs.vpc-f24c7994.network_acls.acl-ed4be494.egress.100", + "vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.network_acls.acl-003d0768.egress.100", + "vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.network_acls.acl-c74e7dae.egress.100", + "vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.network_acls.acl-43816e25.egress.100", + "vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.network_acls.acl-f1a6ae8c.egress.100", + "vpc.regions.us-east-2.vpcs.vpc-e429ad8f.network_acls.acl-b06507db.egress.100", + "vpc.regions.us-west-1.vpcs.vpc-6e6fa508.network_acls.acl-14a0c772.egress.100", + "vpc.regions.us-west-2.vpcs.vpc-d45709ac.network_acls.acl-f76adc8c.egress.100" + ], + "level": "warning", + "path": "vpc.regions.id.vpcs.id.network_acls.id", + "rationale": "Network ACLs are designed to provide a secondary layer of security. Adding a rule that allows all network traffic (all protocols, IPs, and destination) prior to any deny rule defeats the purpose of network ACLs.", + "references": null, + "remediation": null, + "service": "VPC" + }, + "vpc-default-network-acls-allow-all-ingress": { + "checked_items": 17, + "compliance": null, + "dashboard_name": "Network ACLs", + "description": "Network ACLs Allow All ingress Traffic (default)", + "flagged_items": 17, + "id_suffix": "ingress._GET_VALUE_AT_(vpc.regions.id.vpcs.id.network_acls.id.allow_all_ingress_traffic)", + "items": [ + "vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.network_acls.acl-c777e5a1.ingress.100", + "vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.network_acls.acl-75e1951e.ingress.100", + "vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.network_acls.acl-bb1b62d2.ingress.100", + "vpc.regions.ap-south-1.vpcs.vpc-2651a14d.network_acls.acl-a676adcd.ingress.100", + "vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.network_acls.acl-8787e0e1.ingress.100", + "vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.network_acls.acl-4e4dc228.ingress.100", + "vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.network_acls.acl-63e1ed0b.ingress.100", + "vpc.regions.eu-central-1.vpcs.vpc-78b43312.network_acls.acl-6ebcec04.ingress.100", + "vpc.regions.eu-north-1.vpcs.vpc-fa259d93.network_acls.acl-dfb10ab6.ingress.100", + "vpc.regions.eu-west-1.vpcs.vpc-f24c7994.network_acls.acl-ed4be494.ingress.100", + "vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.network_acls.acl-003d0768.ingress.100", + "vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.network_acls.acl-c74e7dae.ingress.100", + "vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.network_acls.acl-43816e25.ingress.100", + "vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.network_acls.acl-f1a6ae8c.ingress.100", + "vpc.regions.us-east-2.vpcs.vpc-e429ad8f.network_acls.acl-b06507db.ingress.100", + "vpc.regions.us-west-1.vpcs.vpc-6e6fa508.network_acls.acl-14a0c772.ingress.100", + "vpc.regions.us-west-2.vpcs.vpc-d45709ac.network_acls.acl-f76adc8c.ingress.100" + ], + "level": "warning", + "path": "vpc.regions.id.vpcs.id.network_acls.id", + "rationale": "Network ACLs are designed to provide a secondary layer of security. Adding a rule that allows all network traffic (all protocols, IPs, and source) prior to any deny rule defeats the purpose of network ACLs.", + "references": null, + "remediation": null, + "service": "VPC" + }, + "vpc-network-acl-not-used": { + "checked_items": 17, + "compliance": null, + "dashboard_name": "Network ACLs", + "description": "Unused Network ACLs", + "flagged_items": 0, + "id_suffix": "unused", + "items": [], + "level": "warning", + "path": "vpc.regions.id.vpcs.id.network_acls.id", + "rationale": "Maintaining unused resources increases risks of misconfigurations and increases the difficulty of audits.", + "references": null, + "remediation": null, + "service": "VPC" + }, + "vpc-routing-tables-with-peering": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.5", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.4", + "version": "1.2.0" + } + ], + "dashboard_name": "Rulesets", + "description": "Routing Table with VPC Peering", + "flagged_items": 0, + "id_suffix": "default_with_rules", + "items": [], + "level": "warning", + "path": "vpc.regions.id.peering_connections.id", + "rationale": "Being highly selective in peering routing tables minimizes the impact of breach as resources outside of these routes are inaccessible to the peered VPC.", + "references": null, + "remediation": "Ensure route tables contain the least number of subnets or hosts as is required to accomplish the purpose for peering", + "service": "VPC" + }, + "vpc-subnet-with-allow-all-egress-acls": { + "checked_items": 55, + "compliance": null, + "dashboard_name": "Subnets", + "description": "Subnet with \"Allow All\" egress NACLs", + "flagged_items": 55, + "id_suffix": "bad_nacls", + "items": [ + "vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-7f50e154.bad_nacls", + "vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-a668c6ee.bad_nacls", + "vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-593d2502.bad_nacls", + "vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-e6ad198d.bad_nacls", + "vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-af6809d4.bad_nacls", + "vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-8447addb.bad_nacls", + "vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-cf001883.bad_nacls", + "vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-4dcc0924.bad_nacls", + "vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-546a8e2f.bad_nacls", + "vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-c1b6118c.bad_nacls", + "vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-f0fde498.bad_nacls", + "vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-d3c151a8.bad_nacls", + "vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-7d5a1431.bad_nacls", + "vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-2506d06d.bad_nacls", + "vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-a448d5fd.bad_nacls", + "vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-b73197d1.bad_nacls", + "vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-b3fe86eb.bad_nacls", + "vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-0c0bc26a.bad_nacls", + "vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-6cb44e24.bad_nacls", + "vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-1cd98b74.bad_nacls", + "vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-4f896210.bad_nacls", + "vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-85711fff.bad_nacls", + "vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-ecc66390.bad_nacls", + "vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-55d77f19.bad_nacls", + "vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-292d4343.bad_nacls", + "vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-1d972e74.bad_nacls", + "vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-fe16ce85.bad_nacls", + "vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-c98e7484.bad_nacls", + "vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-b3a000e9.bad_nacls", + "vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-b1c2a5d7.bad_nacls", + "vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-214f3969.bad_nacls", + "vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-edaf13a1.bad_nacls", + "vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-e682ec9c.bad_nacls", + "vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-43bf9d2a.bad_nacls", + "vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-b309b8fe.bad_nacls", + "vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-762a450d.bad_nacls", + "vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-e9e1b480.bad_nacls", + "vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-6a4dd723.bad_nacls", + "vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-9aa5c1fc.bad_nacls", + "vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-aaddbef1.bad_nacls", + "vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-6e61f24f.bad_nacls", + "vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-8c27ffbd.bad_nacls", + "vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-30be2f6f.bad_nacls", + "vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-77e07411.bad_nacls", + "vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-cbefcb86.bad_nacls", + "vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-7056187e.bad_nacls", + "vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-fac76891.bad_nacls", + "vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-81a1eccd.bad_nacls", + "vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-18e60365.bad_nacls", + "vpc.regions.us-west-1.vpcs.vpc-6e6fa508.subnets.subnet-3162b36b.bad_nacls", + "vpc.regions.us-west-1.vpcs.vpc-6e6fa508.subnets.subnet-64f07402.bad_nacls", + "vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-64dae84f.bad_nacls", + "vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-113ce95b.bad_nacls", + "vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-25f65d5d.bad_nacls", + "vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-1075cf4d.bad_nacls" + ], + "level": "warning", + "path": "vpc.regions.id.vpcs.id.subnets.id", + "rationale": "Network ACLs associated with subnets and VPCs should not allow all egress traffic.", + "references": null, + "remediation": null, + "service": "VPC" + }, + "vpc-subnet-with-allow-all-ingress-acls": { + "checked_items": 55, + "compliance": null, + "dashboard_name": "Subnets", + "description": "Subnet with \"Allow All\" ingress NACLs", + "flagged_items": 55, + "id_suffix": "bad_nacls", + "items": [ + "vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-7f50e154.bad_nacls", + "vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-a668c6ee.bad_nacls", + "vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-593d2502.bad_nacls", + "vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-e6ad198d.bad_nacls", + "vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-af6809d4.bad_nacls", + "vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-8447addb.bad_nacls", + "vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-cf001883.bad_nacls", + "vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-4dcc0924.bad_nacls", + "vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-546a8e2f.bad_nacls", + "vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-c1b6118c.bad_nacls", + "vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-f0fde498.bad_nacls", + "vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-d3c151a8.bad_nacls", + "vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-7d5a1431.bad_nacls", + "vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-2506d06d.bad_nacls", + "vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-a448d5fd.bad_nacls", + "vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-b73197d1.bad_nacls", + "vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-b3fe86eb.bad_nacls", + "vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-0c0bc26a.bad_nacls", + "vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-6cb44e24.bad_nacls", + "vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-1cd98b74.bad_nacls", + "vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-4f896210.bad_nacls", + "vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-85711fff.bad_nacls", + "vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-ecc66390.bad_nacls", + "vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-55d77f19.bad_nacls", + "vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-292d4343.bad_nacls", + "vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-1d972e74.bad_nacls", + "vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-fe16ce85.bad_nacls", + "vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-c98e7484.bad_nacls", + "vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-b3a000e9.bad_nacls", + "vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-b1c2a5d7.bad_nacls", + "vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-214f3969.bad_nacls", + "vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-edaf13a1.bad_nacls", + "vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-e682ec9c.bad_nacls", + "vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-43bf9d2a.bad_nacls", + "vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-b309b8fe.bad_nacls", + "vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-762a450d.bad_nacls", + "vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-e9e1b480.bad_nacls", + "vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-6a4dd723.bad_nacls", + "vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-9aa5c1fc.bad_nacls", + "vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-aaddbef1.bad_nacls", + "vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-6e61f24f.bad_nacls", + "vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-8c27ffbd.bad_nacls", + "vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-30be2f6f.bad_nacls", + "vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-77e07411.bad_nacls", + "vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-cbefcb86.bad_nacls", + "vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-7056187e.bad_nacls", + "vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-fac76891.bad_nacls", + "vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-81a1eccd.bad_nacls", + "vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-18e60365.bad_nacls", + "vpc.regions.us-west-1.vpcs.vpc-6e6fa508.subnets.subnet-3162b36b.bad_nacls", + "vpc.regions.us-west-1.vpcs.vpc-6e6fa508.subnets.subnet-64f07402.bad_nacls", + "vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-64dae84f.bad_nacls", + "vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-113ce95b.bad_nacls", + "vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-25f65d5d.bad_nacls", + "vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-1075cf4d.bad_nacls" + ], + "level": "warning", + "path": "vpc.regions.id.vpcs.id.subnets.id", + "rationale": "Network ACLs associated with subnets and VPCs should not allow all ingress traffic.", + "references": null, + "remediation": null, + "service": "VPC" + }, + "vpc-subnet-without-flow-log": { + "checked_items": 55, + "compliance": [ + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.3", + "version": "1.0.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "4.3", + "version": "1.1.0" + }, + { + "name": "CIS Amazon Web Services Foundations", + "reference": "2.9", + "version": "1.2.0" + } + ], + "dashboard_name": "Subnets", + "description": "Subnet without a Flow Log", + "flagged_items": 55, + "id_suffix": "no_flowlog", + "items": [ + "vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-7f50e154.no_flowlog", + "vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-a668c6ee.no_flowlog", + "vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-593d2502.no_flowlog", + "vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-e6ad198d.no_flowlog", + "vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-af6809d4.no_flowlog", + "vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-8447addb.no_flowlog", + "vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-cf001883.no_flowlog", + "vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-4dcc0924.no_flowlog", + "vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-546a8e2f.no_flowlog", + "vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-c1b6118c.no_flowlog", + "vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-f0fde498.no_flowlog", + "vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-d3c151a8.no_flowlog", + "vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-7d5a1431.no_flowlog", + "vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-2506d06d.no_flowlog", + "vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-a448d5fd.no_flowlog", + "vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-b73197d1.no_flowlog", + "vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-b3fe86eb.no_flowlog", + "vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-0c0bc26a.no_flowlog", + "vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-6cb44e24.no_flowlog", + "vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-1cd98b74.no_flowlog", + "vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-4f896210.no_flowlog", + "vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-85711fff.no_flowlog", + "vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-ecc66390.no_flowlog", + "vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-55d77f19.no_flowlog", + "vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-292d4343.no_flowlog", + "vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-1d972e74.no_flowlog", + "vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-fe16ce85.no_flowlog", + "vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-c98e7484.no_flowlog", + "vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-b3a000e9.no_flowlog", + "vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-b1c2a5d7.no_flowlog", + "vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-214f3969.no_flowlog", + "vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-edaf13a1.no_flowlog", + "vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-e682ec9c.no_flowlog", + "vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-43bf9d2a.no_flowlog", + "vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-b309b8fe.no_flowlog", + "vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-762a450d.no_flowlog", + "vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-e9e1b480.no_flowlog", + "vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-6a4dd723.no_flowlog", + "vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-9aa5c1fc.no_flowlog", + "vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-aaddbef1.no_flowlog", + "vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-6e61f24f.no_flowlog", + "vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-8c27ffbd.no_flowlog", + "vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-30be2f6f.no_flowlog", + "vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-77e07411.no_flowlog", + "vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-cbefcb86.no_flowlog", + "vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-7056187e.no_flowlog", + "vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-fac76891.no_flowlog", + "vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-81a1eccd.no_flowlog", + "vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-18e60365.no_flowlog", + "vpc.regions.us-west-1.vpcs.vpc-6e6fa508.subnets.subnet-3162b36b.no_flowlog", + "vpc.regions.us-west-1.vpcs.vpc-6e6fa508.subnets.subnet-64f07402.no_flowlog", + "vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-64dae84f.no_flowlog", + "vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-113ce95b.no_flowlog", + "vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-25f65d5d.no_flowlog", + "vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-1075cf4d.no_flowlog" + ], + "level": "warning", + "path": "vpc.regions.id.vpcs.id.subnets.id", + "rationale": "Flow logs enable the investigation of incidents involving unauthorized network traffic, such as an attacker exfiltrating data or pivoting to other hosts.", + "references": [ + "https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html" + ], + "remediation": "Create a flow log for each subnet.", + "service": "VPC" + } + }, + "flow_logs_count": 0, + "peering_connections_count": 0, + "regions": { + "ap-northeast-1": { + "flow_logs": {}, + "flow_logs_count": 0, + "id": "ap-northeast-1", + "name": "ap-northeast-1", + "peering_connections": {}, + "peering_connections_count": 0, + "region": "ap-northeast-1", + "vpcs": { + "vpc-0cbc506a": { + "arn": "arn:aws:vpc:ap-northeast-1:430150006394:virtual-private-cloud/vpc-0cbc506a", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-0cbc506a", + "name": "vpc-0cbc506a", + "network_acls": { + "acl-c777e5a1": { + "Associations": [ + { + "NetworkAclAssociationId": "aclassoc-31486e40", + "NetworkAclId": "acl-c777e5a1", + "SubnetId": "subnet-a668c6ee" + }, + { + "NetworkAclAssociationId": "aclassoc-4e486e3f", + "NetworkAclId": "acl-c777e5a1", + "SubnetId": "subnet-7f50e154" + }, + { + "NetworkAclAssociationId": "aclassoc-4f486e3e", + "NetworkAclId": "acl-c777e5a1", + "SubnetId": "subnet-593d2502" + } + ], + "IsDefault": true, + "OwnerId": "430150006394", + "Tags": [], + "VpcId": "vpc-0cbc506a", + "allow_all_egress_traffic": "100", + "allow_all_ingress_traffic": "100", + "id": "acl-c777e5a1", + "name": "acl-c777e5a1", + "rules": { + "egress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + }, + "ingress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + } + }, + "use_default_egress_rules": true, + "use_default_ingress_rules": true + } + }, + "network_acls_count": 1, + "state": "available", + "subnets": { + "subnet-593d2502": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ap-northeast-1c", + "AvailabilityZoneId": "apne1-az1", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.0.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ap-northeast-1:430150006394:subnet/subnet-593d2502", + "VpcId": "vpc-0cbc506a", + "flow_logs": [], + "id": "subnet-593d2502", + "name": "subnet-593d2502", + "network_acl": "acl-c777e5a1" + }, + "subnet-7f50e154": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ap-northeast-1d", + "AvailabilityZoneId": "apne1-az2", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.16.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ap-northeast-1:430150006394:subnet/subnet-7f50e154", + "VpcId": "vpc-0cbc506a", + "flow_logs": [], + "id": "subnet-7f50e154", + "name": "subnet-7f50e154", + "network_acl": "acl-c777e5a1" + }, + "subnet-a668c6ee": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ap-northeast-1a", + "AvailabilityZoneId": "apne1-az4", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.32.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ap-northeast-1:430150006394:subnet/subnet-a668c6ee", + "VpcId": "vpc-0cbc506a", + "flow_logs": [], + "id": "subnet-a668c6ee", + "name": "subnet-a668c6ee", + "network_acl": "acl-c777e5a1" + } + }, + "subnets_count": 3 + } + }, + "vpcs_count": 1 + }, + "ap-northeast-2": { + "flow_logs": {}, + "flow_logs_count": 0, + "id": "ap-northeast-2", + "name": "ap-northeast-2", + "peering_connections": {}, + "peering_connections_count": 0, + "region": "ap-northeast-2", + "vpcs": { + "vpc-73f44e18": { + "arn": "arn:aws:vpc:ap-northeast-2:430150006394:virtual-private-cloud/vpc-73f44e18", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-73f44e18", + "name": "vpc-73f44e18", + "network_acls": { + "acl-75e1951e": { + "Associations": [ + { + "NetworkAclAssociationId": "aclassoc-37937854", + "NetworkAclId": "acl-75e1951e", + "SubnetId": "subnet-e6ad198d" + }, + { + "NetworkAclAssociationId": "aclassoc-35937856", + "NetworkAclId": "acl-75e1951e", + "SubnetId": "subnet-cf001883" + }, + { + "NetworkAclAssociationId": "aclassoc-36937855", + "NetworkAclId": "acl-75e1951e", + "SubnetId": "subnet-af6809d4" + }, + { + "NetworkAclAssociationId": "aclassoc-34937857", + "NetworkAclId": "acl-75e1951e", + "SubnetId": "subnet-8447addb" + } + ], + "IsDefault": true, + "OwnerId": "430150006394", + "Tags": [], + "VpcId": "vpc-73f44e18", + "allow_all_egress_traffic": "100", + "allow_all_ingress_traffic": "100", + "id": "acl-75e1951e", + "name": "acl-75e1951e", + "rules": { + "egress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + }, + "ingress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + } + }, + "use_default_egress_rules": true, + "use_default_ingress_rules": true + } + }, + "network_acls_count": 1, + "state": "available", + "subnets": { + "subnet-8447addb": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ap-northeast-2d", + "AvailabilityZoneId": "apne2-az4", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.48.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ap-northeast-2:430150006394:subnet/subnet-8447addb", + "VpcId": "vpc-73f44e18", + "flow_logs": [], + "id": "subnet-8447addb", + "name": "subnet-8447addb", + "network_acl": "acl-75e1951e" + }, + "subnet-af6809d4": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ap-northeast-2b", + "AvailabilityZoneId": "apne2-az2", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.16.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ap-northeast-2:430150006394:subnet/subnet-af6809d4", + "VpcId": "vpc-73f44e18", + "flow_logs": [], + "id": "subnet-af6809d4", + "name": "subnet-af6809d4", + "network_acl": "acl-75e1951e" + }, + "subnet-cf001883": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ap-northeast-2c", + "AvailabilityZoneId": "apne2-az3", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.32.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ap-northeast-2:430150006394:subnet/subnet-cf001883", + "VpcId": "vpc-73f44e18", + "flow_logs": [], + "id": "subnet-cf001883", + "name": "subnet-cf001883", + "network_acl": "acl-75e1951e" + }, + "subnet-e6ad198d": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ap-northeast-2a", + "AvailabilityZoneId": "apne2-az1", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.0.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ap-northeast-2:430150006394:subnet/subnet-e6ad198d", + "VpcId": "vpc-73f44e18", + "flow_logs": [], + "id": "subnet-e6ad198d", + "name": "subnet-e6ad198d", + "network_acl": "acl-75e1951e" + } + }, + "subnets_count": 4 + } + }, + "vpcs_count": 1 + }, + "ap-northeast-3": { + "flow_logs": {}, + "flow_logs_count": 0, + "id": "ap-northeast-3", + "name": "ap-northeast-3", + "peering_connections": {}, + "peering_connections_count": 0, + "region": "ap-northeast-3", + "vpcs": { + "vpc-47b7dd2e": { + "arn": "arn:aws:vpc:ap-northeast-3:430150006394:virtual-private-cloud/vpc-47b7dd2e", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-47b7dd2e", + "name": "vpc-47b7dd2e", + "network_acls": { + "acl-bb1b62d2": { + "Associations": [ + { + "NetworkAclAssociationId": "aclassoc-1953e271", + "NetworkAclId": "acl-bb1b62d2", + "SubnetId": "subnet-c1b6118c" + }, + { + "NetworkAclAssociationId": "aclassoc-1853e270", + "NetworkAclId": "acl-bb1b62d2", + "SubnetId": "subnet-4dcc0924" + }, + { + "NetworkAclAssociationId": "aclassoc-0753e26f", + "NetworkAclId": "acl-bb1b62d2", + "SubnetId": "subnet-546a8e2f" + } + ], + "IsDefault": true, + "OwnerId": "430150006394", + "Tags": [], + "VpcId": "vpc-47b7dd2e", + "allow_all_egress_traffic": "100", + "allow_all_ingress_traffic": "100", + "id": "acl-bb1b62d2", + "name": "acl-bb1b62d2", + "rules": { + "egress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + }, + "ingress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + } + }, + "use_default_egress_rules": true, + "use_default_ingress_rules": true + } + }, + "network_acls_count": 1, + "state": "available", + "subnets": { + "subnet-4dcc0924": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ap-northeast-3b", + "AvailabilityZoneId": "apne3-az1", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.16.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ap-northeast-3:430150006394:subnet/subnet-4dcc0924", + "VpcId": "vpc-47b7dd2e", + "flow_logs": [], + "id": "subnet-4dcc0924", + "name": "subnet-4dcc0924", + "network_acl": "acl-bb1b62d2" + }, + "subnet-546a8e2f": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ap-northeast-3c", + "AvailabilityZoneId": "apne3-az2", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.0.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ap-northeast-3:430150006394:subnet/subnet-546a8e2f", + "VpcId": "vpc-47b7dd2e", + "flow_logs": [], + "id": "subnet-546a8e2f", + "name": "subnet-546a8e2f", + "network_acl": "acl-bb1b62d2" + }, + "subnet-c1b6118c": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ap-northeast-3a", + "AvailabilityZoneId": "apne3-az3", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.32.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ap-northeast-3:430150006394:subnet/subnet-c1b6118c", + "VpcId": "vpc-47b7dd2e", + "flow_logs": [], + "id": "subnet-c1b6118c", + "name": "subnet-c1b6118c", + "network_acl": "acl-bb1b62d2" + } + }, + "subnets_count": 3 + } + }, + "vpcs_count": 1 + }, + "ap-south-1": { + "flow_logs": {}, + "flow_logs_count": 0, + "id": "ap-south-1", + "name": "ap-south-1", + "peering_connections": {}, + "peering_connections_count": 0, + "region": "ap-south-1", + "vpcs": { + "vpc-2651a14d": { + "arn": "arn:aws:vpc:ap-south-1:430150006394:virtual-private-cloud/vpc-2651a14d", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-2651a14d", + "name": "vpc-2651a14d", + "network_acls": { + "acl-a676adcd": { + "Associations": [ + { + "NetworkAclAssociationId": "aclassoc-c9d2b0a8", + "NetworkAclId": "acl-a676adcd", + "SubnetId": "subnet-d3c151a8" + }, + { + "NetworkAclAssociationId": "aclassoc-c6d2b0a7", + "NetworkAclId": "acl-a676adcd", + "SubnetId": "subnet-7d5a1431" + }, + { + "NetworkAclAssociationId": "aclassoc-c8d2b0a9", + "NetworkAclId": "acl-a676adcd", + "SubnetId": "subnet-f0fde498" + } + ], + "IsDefault": true, + "OwnerId": "430150006394", + "Tags": [], + "VpcId": "vpc-2651a14d", + "allow_all_egress_traffic": "100", + "allow_all_ingress_traffic": "100", + "id": "acl-a676adcd", + "name": "acl-a676adcd", + "rules": { + "egress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + }, + "ingress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + } + }, + "use_default_egress_rules": true, + "use_default_ingress_rules": true + } + }, + "network_acls_count": 1, + "state": "available", + "subnets": { + "subnet-7d5a1431": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ap-south-1b", + "AvailabilityZoneId": "aps1-az3", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.0.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ap-south-1:430150006394:subnet/subnet-7d5a1431", + "VpcId": "vpc-2651a14d", + "flow_logs": [], + "id": "subnet-7d5a1431", + "name": "subnet-7d5a1431", + "network_acl": "acl-a676adcd" + }, + "subnet-d3c151a8": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ap-south-1c", + "AvailabilityZoneId": "aps1-az2", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.16.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ap-south-1:430150006394:subnet/subnet-d3c151a8", + "VpcId": "vpc-2651a14d", + "flow_logs": [], + "id": "subnet-d3c151a8", + "name": "subnet-d3c151a8", + "network_acl": "acl-a676adcd" + }, + "subnet-f0fde498": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ap-south-1a", + "AvailabilityZoneId": "aps1-az1", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.32.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ap-south-1:430150006394:subnet/subnet-f0fde498", + "VpcId": "vpc-2651a14d", + "flow_logs": [], + "id": "subnet-f0fde498", + "name": "subnet-f0fde498", + "network_acl": "acl-a676adcd" + } + }, + "subnets_count": 3 + } + }, + "vpcs_count": 1 + }, + "ap-southeast-1": { + "flow_logs": {}, + "flow_logs_count": 0, + "id": "ap-southeast-1", + "name": "ap-southeast-1", + "peering_connections": {}, + "peering_connections_count": 0, + "region": "ap-southeast-1", + "vpcs": { + "vpc-04ed1062": { + "arn": "arn:aws:vpc:ap-southeast-1:430150006394:virtual-private-cloud/vpc-04ed1062", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-04ed1062", + "name": "vpc-04ed1062", + "network_acls": { + "acl-8787e0e1": { + "Associations": [ + { + "NetworkAclAssociationId": "aclassoc-a6b2e6d8", + "NetworkAclId": "acl-8787e0e1", + "SubnetId": "subnet-2506d06d" + }, + { + "NetworkAclAssociationId": "aclassoc-a8b2e6d6", + "NetworkAclId": "acl-8787e0e1", + "SubnetId": "subnet-a448d5fd" + }, + { + "NetworkAclAssociationId": "aclassoc-a9b2e6d7", + "NetworkAclId": "acl-8787e0e1", + "SubnetId": "subnet-b73197d1" + } + ], + "IsDefault": true, + "OwnerId": "430150006394", + "Tags": [], + "VpcId": "vpc-04ed1062", + "allow_all_egress_traffic": "100", + "allow_all_ingress_traffic": "100", + "id": "acl-8787e0e1", + "name": "acl-8787e0e1", + "rules": { + "egress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + }, + "ingress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + } + }, + "use_default_egress_rules": true, + "use_default_ingress_rules": true + } + }, + "network_acls_count": 1, + "state": "available", + "subnets": { + "subnet-2506d06d": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ap-southeast-1a", + "AvailabilityZoneId": "apse1-az2", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.32.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ap-southeast-1:430150006394:subnet/subnet-2506d06d", + "VpcId": "vpc-04ed1062", + "flow_logs": [], + "id": "subnet-2506d06d", + "name": "subnet-2506d06d", + "network_acl": "acl-8787e0e1" + }, + "subnet-a448d5fd": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ap-southeast-1c", + "AvailabilityZoneId": "apse1-az3", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.0.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ap-southeast-1:430150006394:subnet/subnet-a448d5fd", + "VpcId": "vpc-04ed1062", + "flow_logs": [], + "id": "subnet-a448d5fd", + "name": "subnet-a448d5fd", + "network_acl": "acl-8787e0e1" + }, + "subnet-b73197d1": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ap-southeast-1b", + "AvailabilityZoneId": "apse1-az1", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.16.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ap-southeast-1:430150006394:subnet/subnet-b73197d1", + "VpcId": "vpc-04ed1062", + "flow_logs": [], + "id": "subnet-b73197d1", + "name": "subnet-b73197d1", + "network_acl": "acl-8787e0e1" + } + }, + "subnets_count": 3 + } + }, + "vpcs_count": 1 + }, + "ap-southeast-2": { + "flow_logs": {}, + "flow_logs_count": 0, + "id": "ap-southeast-2", + "name": "ap-southeast-2", + "peering_connections": {}, + "peering_connections_count": 0, + "region": "ap-southeast-2", + "vpcs": { + "vpc-5d22c33b": { + "arn": "arn:aws:vpc:ap-southeast-2:430150006394:virtual-private-cloud/vpc-5d22c33b", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-5d22c33b", + "name": "vpc-5d22c33b", + "network_acls": { + "acl-4e4dc228": { + "Associations": [ + { + "NetworkAclAssociationId": "aclassoc-fdeb7a8d", + "NetworkAclId": "acl-4e4dc228", + "SubnetId": "subnet-6cb44e24" + }, + { + "NetworkAclAssociationId": "aclassoc-fbeb7a8b", + "NetworkAclId": "acl-4e4dc228", + "SubnetId": "subnet-0c0bc26a" + }, + { + "NetworkAclAssociationId": "aclassoc-fceb7a8c", + "NetworkAclId": "acl-4e4dc228", + "SubnetId": "subnet-b3fe86eb" + } + ], + "IsDefault": true, + "OwnerId": "430150006394", + "Tags": [], + "VpcId": "vpc-5d22c33b", + "allow_all_egress_traffic": "100", + "allow_all_ingress_traffic": "100", + "id": "acl-4e4dc228", + "name": "acl-4e4dc228", + "rules": { + "egress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + }, + "ingress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + } + }, + "use_default_egress_rules": true, + "use_default_ingress_rules": true + } + }, + "network_acls_count": 1, + "state": "available", + "subnets": { + "subnet-0c0bc26a": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ap-southeast-2b", + "AvailabilityZoneId": "apse2-az1", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.0.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ap-southeast-2:430150006394:subnet/subnet-0c0bc26a", + "VpcId": "vpc-5d22c33b", + "flow_logs": [], + "id": "subnet-0c0bc26a", + "name": "subnet-0c0bc26a", + "network_acl": "acl-4e4dc228" + }, + "subnet-6cb44e24": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ap-southeast-2a", + "AvailabilityZoneId": "apse2-az3", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.32.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ap-southeast-2:430150006394:subnet/subnet-6cb44e24", + "VpcId": "vpc-5d22c33b", + "flow_logs": [], + "id": "subnet-6cb44e24", + "name": "subnet-6cb44e24", + "network_acl": "acl-4e4dc228" + }, + "subnet-b3fe86eb": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ap-southeast-2c", + "AvailabilityZoneId": "apse2-az2", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.16.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ap-southeast-2:430150006394:subnet/subnet-b3fe86eb", + "VpcId": "vpc-5d22c33b", + "flow_logs": [], + "id": "subnet-b3fe86eb", + "name": "subnet-b3fe86eb", + "network_acl": "acl-4e4dc228" + } + }, + "subnets_count": 3 + } + }, + "vpcs_count": 1 + }, + "ca-central-1": { + "flow_logs": {}, + "flow_logs_count": 0, + "id": "ca-central-1", + "name": "ca-central-1", + "peering_connections": {}, + "peering_connections_count": 0, + "region": "ca-central-1", + "vpcs": { + "vpc-b5113ddd": { + "arn": "arn:aws:vpc:ca-central-1:430150006394:virtual-private-cloud/vpc-b5113ddd", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-b5113ddd", + "name": "vpc-b5113ddd", + "network_acls": { + "acl-63e1ed0b": { + "Associations": [ + { + "NetworkAclAssociationId": "aclassoc-31d33c50", + "NetworkAclId": "acl-63e1ed0b", + "SubnetId": "subnet-85711fff" + }, + { + "NetworkAclAssociationId": "aclassoc-33d33c52", + "NetworkAclId": "acl-63e1ed0b", + "SubnetId": "subnet-4f896210" + }, + { + "NetworkAclAssociationId": "aclassoc-30d33c51", + "NetworkAclId": "acl-63e1ed0b", + "SubnetId": "subnet-1cd98b74" + } + ], + "IsDefault": true, + "OwnerId": "430150006394", + "Tags": [], + "VpcId": "vpc-b5113ddd", + "allow_all_egress_traffic": "100", + "allow_all_ingress_traffic": "100", + "id": "acl-63e1ed0b", + "name": "acl-63e1ed0b", + "rules": { + "egress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + }, + "ingress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + } + }, + "use_default_egress_rules": true, + "use_default_ingress_rules": true + } + }, + "network_acls_count": 1, + "state": "available", + "subnets": { + "subnet-1cd98b74": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ca-central-1a", + "AvailabilityZoneId": "cac1-az1", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.16.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ca-central-1:430150006394:subnet/subnet-1cd98b74", + "VpcId": "vpc-b5113ddd", + "flow_logs": [], + "id": "subnet-1cd98b74", + "name": "subnet-1cd98b74", + "network_acl": "acl-63e1ed0b" + }, + "subnet-4f896210": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ca-central-1d", + "AvailabilityZoneId": "cac1-az4", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.32.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ca-central-1:430150006394:subnet/subnet-4f896210", + "VpcId": "vpc-b5113ddd", + "flow_logs": [], + "id": "subnet-4f896210", + "name": "subnet-4f896210", + "network_acl": "acl-63e1ed0b" + }, + "subnet-85711fff": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "ca-central-1b", + "AvailabilityZoneId": "cac1-az2", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.0.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:ca-central-1:430150006394:subnet/subnet-85711fff", + "VpcId": "vpc-b5113ddd", + "flow_logs": [], + "id": "subnet-85711fff", + "name": "subnet-85711fff", + "network_acl": "acl-63e1ed0b" + } + }, + "subnets_count": 3 + } + }, + "vpcs_count": 1 + }, + "eu-central-1": { + "flow_logs": {}, + "flow_logs_count": 0, + "id": "eu-central-1", + "name": "eu-central-1", + "peering_connections": {}, + "peering_connections_count": 0, + "region": "eu-central-1", + "vpcs": { + "vpc-78b43312": { + "arn": "arn:aws:vpc:eu-central-1:430150006394:virtual-private-cloud/vpc-78b43312", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-78b43312", + "name": "vpc-78b43312", + "network_acls": { + "acl-6ebcec04": { + "Associations": [ + { + "NetworkAclAssociationId": "aclassoc-36773353", + "NetworkAclId": "acl-6ebcec04", + "SubnetId": "subnet-55d77f19" + }, + { + "NetworkAclAssociationId": "aclassoc-31773354", + "NetworkAclId": "acl-6ebcec04", + "SubnetId": "subnet-292d4343" + }, + { + "NetworkAclAssociationId": "aclassoc-30773355", + "NetworkAclId": "acl-6ebcec04", + "SubnetId": "subnet-ecc66390" + } + ], + "IsDefault": true, + "OwnerId": "430150006394", + "Tags": [], + "VpcId": "vpc-78b43312", + "allow_all_egress_traffic": "100", + "allow_all_ingress_traffic": "100", + "id": "acl-6ebcec04", + "name": "acl-6ebcec04", + "rules": { + "egress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + }, + "ingress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + } + }, + "use_default_egress_rules": true, + "use_default_ingress_rules": true + } + }, + "network_acls_count": 1, + "state": "available", + "subnets": { + "subnet-292d4343": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "eu-central-1a", + "AvailabilityZoneId": "euc1-az2", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.16.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:eu-central-1:430150006394:subnet/subnet-292d4343", + "VpcId": "vpc-78b43312", + "flow_logs": [], + "id": "subnet-292d4343", + "name": "subnet-292d4343", + "network_acl": "acl-6ebcec04" + }, + "subnet-55d77f19": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "eu-central-1c", + "AvailabilityZoneId": "euc1-az1", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.0.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:eu-central-1:430150006394:subnet/subnet-55d77f19", + "VpcId": "vpc-78b43312", + "flow_logs": [], + "id": "subnet-55d77f19", + "name": "subnet-55d77f19", + "network_acl": "acl-6ebcec04" + }, + "subnet-ecc66390": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "eu-central-1b", + "AvailabilityZoneId": "euc1-az3", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.32.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:eu-central-1:430150006394:subnet/subnet-ecc66390", + "VpcId": "vpc-78b43312", + "flow_logs": [], + "id": "subnet-ecc66390", + "name": "subnet-ecc66390", + "network_acl": "acl-6ebcec04" + } + }, + "subnets_count": 3 + } + }, + "vpcs_count": 1 + }, + "eu-north-1": { + "flow_logs": {}, + "flow_logs_count": 0, + "id": "eu-north-1", + "name": "eu-north-1", + "peering_connections": {}, + "peering_connections_count": 0, + "region": "eu-north-1", + "vpcs": { + "vpc-fa259d93": { + "arn": "arn:aws:vpc:eu-north-1:430150006394:virtual-private-cloud/vpc-fa259d93", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-fa259d93", + "name": "vpc-fa259d93", + "network_acls": { + "acl-dfb10ab6": { + "Associations": [ + { + "NetworkAclAssociationId": "aclassoc-8ed1b4e3", + "NetworkAclId": "acl-dfb10ab6", + "SubnetId": "subnet-1d972e74" + }, + { + "NetworkAclAssociationId": "aclassoc-89d1b4e4", + "NetworkAclId": "acl-dfb10ab6", + "SubnetId": "subnet-fe16ce85" + }, + { + "NetworkAclAssociationId": "aclassoc-8fd1b4e2", + "NetworkAclId": "acl-dfb10ab6", + "SubnetId": "subnet-c98e7484" + } + ], + "IsDefault": true, + "OwnerId": "430150006394", + "Tags": [], + "VpcId": "vpc-fa259d93", + "allow_all_egress_traffic": "100", + "allow_all_ingress_traffic": "100", + "id": "acl-dfb10ab6", + "name": "acl-dfb10ab6", + "rules": { + "egress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + }, + "ingress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + } + }, + "use_default_egress_rules": true, + "use_default_ingress_rules": true + } + }, + "network_acls_count": 1, + "state": "available", + "subnets": { + "subnet-1d972e74": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "eu-north-1a", + "AvailabilityZoneId": "eun1-az1", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.16.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:eu-north-1:430150006394:subnet/subnet-1d972e74", + "VpcId": "vpc-fa259d93", + "flow_logs": [], + "id": "subnet-1d972e74", + "name": "subnet-1d972e74", + "network_acl": "acl-dfb10ab6" + }, + "subnet-c98e7484": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "eu-north-1c", + "AvailabilityZoneId": "eun1-az3", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.0.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:eu-north-1:430150006394:subnet/subnet-c98e7484", + "VpcId": "vpc-fa259d93", + "flow_logs": [], + "id": "subnet-c98e7484", + "name": "subnet-c98e7484", + "network_acl": "acl-dfb10ab6" + }, + "subnet-fe16ce85": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "eu-north-1b", + "AvailabilityZoneId": "eun1-az2", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.32.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:eu-north-1:430150006394:subnet/subnet-fe16ce85", + "VpcId": "vpc-fa259d93", + "flow_logs": [], + "id": "subnet-fe16ce85", + "name": "subnet-fe16ce85", + "network_acl": "acl-dfb10ab6" + } + }, + "subnets_count": 3 + } + }, + "vpcs_count": 1 + }, + "eu-west-1": { + "flow_logs": {}, + "flow_logs_count": 0, + "id": "eu-west-1", + "name": "eu-west-1", + "peering_connections": {}, + "peering_connections_count": 0, + "region": "eu-west-1", + "vpcs": { + "vpc-f24c7994": { + "arn": "arn:aws:vpc:eu-west-1:430150006394:virtual-private-cloud/vpc-f24c7994", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-f24c7994", + "name": "vpc-f24c7994", + "network_acls": { + "acl-ed4be494": { + "Associations": [ + { + "NetworkAclAssociationId": "aclassoc-5a508624", + "NetworkAclId": "acl-ed4be494", + "SubnetId": "subnet-b3a000e9" + }, + { + "NetworkAclAssociationId": "aclassoc-5d508623", + "NetworkAclId": "acl-ed4be494", + "SubnetId": "subnet-214f3969" + }, + { + "NetworkAclAssociationId": "aclassoc-5c508622", + "NetworkAclId": "acl-ed4be494", + "SubnetId": "subnet-b1c2a5d7" + } + ], + "IsDefault": true, + "OwnerId": "430150006394", + "Tags": [], + "VpcId": "vpc-f24c7994", + "allow_all_egress_traffic": "100", + "allow_all_ingress_traffic": "100", + "id": "acl-ed4be494", + "name": "acl-ed4be494", + "rules": { + "egress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + }, + "ingress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + } + }, + "use_default_egress_rules": true, + "use_default_ingress_rules": true + } + }, + "network_acls_count": 1, + "state": "available", + "subnets": { + "subnet-214f3969": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "eu-west-1a", + "AvailabilityZoneId": "euw1-az2", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.16.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:eu-west-1:430150006394:subnet/subnet-214f3969", + "VpcId": "vpc-f24c7994", + "flow_logs": [], + "id": "subnet-214f3969", + "name": "subnet-214f3969", + "network_acl": "acl-ed4be494" + }, + "subnet-b1c2a5d7": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "eu-west-1c", + "AvailabilityZoneId": "euw1-az1", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.0.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:eu-west-1:430150006394:subnet/subnet-b1c2a5d7", + "VpcId": "vpc-f24c7994", + "flow_logs": [], + "id": "subnet-b1c2a5d7", + "name": "subnet-b1c2a5d7", + "network_acl": "acl-ed4be494" + }, + "subnet-b3a000e9": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "eu-west-1b", + "AvailabilityZoneId": "euw1-az3", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.32.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:eu-west-1:430150006394:subnet/subnet-b3a000e9", + "VpcId": "vpc-f24c7994", + "flow_logs": [], + "id": "subnet-b3a000e9", + "name": "subnet-b3a000e9", + "network_acl": "acl-ed4be494" + } + }, + "subnets_count": 3 + } + }, + "vpcs_count": 1 + }, + "eu-west-2": { + "flow_logs": {}, + "flow_logs_count": 0, + "id": "eu-west-2", + "name": "eu-west-2", + "peering_connections": {}, + "peering_connections_count": 0, + "region": "eu-west-2", + "vpcs": { + "vpc-3fa2fa57": { + "arn": "arn:aws:vpc:eu-west-2:430150006394:virtual-private-cloud/vpc-3fa2fa57", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-3fa2fa57", + "name": "vpc-3fa2fa57", + "network_acls": { + "acl-003d0768": { + "Associations": [ + { + "NetworkAclAssociationId": "aclassoc-e73eff86", + "NetworkAclId": "acl-003d0768", + "SubnetId": "subnet-43bf9d2a" + }, + { + "NetworkAclAssociationId": "aclassoc-e93eff88", + "NetworkAclId": "acl-003d0768", + "SubnetId": "subnet-edaf13a1" + }, + { + "NetworkAclAssociationId": "aclassoc-e63eff87", + "NetworkAclId": "acl-003d0768", + "SubnetId": "subnet-e682ec9c" + } + ], + "IsDefault": true, + "OwnerId": "430150006394", + "Tags": [], + "VpcId": "vpc-3fa2fa57", + "allow_all_egress_traffic": "100", + "allow_all_ingress_traffic": "100", + "id": "acl-003d0768", + "name": "acl-003d0768", + "rules": { + "egress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + }, + "ingress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + } + }, + "use_default_egress_rules": true, + "use_default_ingress_rules": true + } + }, + "network_acls_count": 1, + "state": "available", + "subnets": { + "subnet-43bf9d2a": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "eu-west-2c", + "AvailabilityZoneId": "euw2-az1", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.0.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:eu-west-2:430150006394:subnet/subnet-43bf9d2a", + "VpcId": "vpc-3fa2fa57", + "flow_logs": [], + "id": "subnet-43bf9d2a", + "name": "subnet-43bf9d2a", + "network_acl": "acl-003d0768" + }, + "subnet-e682ec9c": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "eu-west-2a", + "AvailabilityZoneId": "euw2-az2", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.16.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:eu-west-2:430150006394:subnet/subnet-e682ec9c", + "VpcId": "vpc-3fa2fa57", + "flow_logs": [], + "id": "subnet-e682ec9c", + "name": "subnet-e682ec9c", + "network_acl": "acl-003d0768" + }, + "subnet-edaf13a1": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "eu-west-2b", + "AvailabilityZoneId": "euw2-az3", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.32.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:eu-west-2:430150006394:subnet/subnet-edaf13a1", + "VpcId": "vpc-3fa2fa57", + "flow_logs": [], + "id": "subnet-edaf13a1", + "name": "subnet-edaf13a1", + "network_acl": "acl-003d0768" + } + }, + "subnets_count": 3 + } + }, + "vpcs_count": 1 + }, + "eu-west-3": { + "flow_logs": {}, + "flow_logs_count": 0, + "id": "eu-west-3", + "name": "eu-west-3", + "peering_connections": {}, + "peering_connections_count": 0, + "region": "eu-west-3", + "vpcs": { + "vpc-87d3fdee": { + "arn": "arn:aws:vpc:eu-west-3:430150006394:virtual-private-cloud/vpc-87d3fdee", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-87d3fdee", + "name": "vpc-87d3fdee", + "network_acls": { + "acl-c74e7dae": { + "Associations": [ + { + "NetworkAclAssociationId": "aclassoc-de1211b6", + "NetworkAclId": "acl-c74e7dae", + "SubnetId": "subnet-762a450d" + }, + { + "NetworkAclAssociationId": "aclassoc-dd1211b5", + "NetworkAclId": "acl-c74e7dae", + "SubnetId": "subnet-e9e1b480" + }, + { + "NetworkAclAssociationId": "aclassoc-df1211b7", + "NetworkAclId": "acl-c74e7dae", + "SubnetId": "subnet-b309b8fe" + } + ], + "IsDefault": true, + "OwnerId": "430150006394", + "Tags": [], + "VpcId": "vpc-87d3fdee", + "allow_all_egress_traffic": "100", + "allow_all_ingress_traffic": "100", + "id": "acl-c74e7dae", + "name": "acl-c74e7dae", + "rules": { + "egress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + }, + "ingress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + } + }, + "use_default_egress_rules": true, + "use_default_ingress_rules": true + } + }, + "network_acls_count": 1, + "state": "available", + "subnets": { + "subnet-762a450d": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "eu-west-3b", + "AvailabilityZoneId": "euw3-az2", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.16.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:eu-west-3:430150006394:subnet/subnet-762a450d", + "VpcId": "vpc-87d3fdee", + "flow_logs": [], + "id": "subnet-762a450d", + "name": "subnet-762a450d", + "network_acl": "acl-c74e7dae" + }, + "subnet-b309b8fe": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "eu-west-3c", + "AvailabilityZoneId": "euw3-az3", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.32.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:eu-west-3:430150006394:subnet/subnet-b309b8fe", + "VpcId": "vpc-87d3fdee", + "flow_logs": [], + "id": "subnet-b309b8fe", + "name": "subnet-b309b8fe", + "network_acl": "acl-c74e7dae" + }, + "subnet-e9e1b480": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "eu-west-3a", + "AvailabilityZoneId": "euw3-az1", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.0.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:eu-west-3:430150006394:subnet/subnet-e9e1b480", + "VpcId": "vpc-87d3fdee", + "flow_logs": [], + "id": "subnet-e9e1b480", + "name": "subnet-e9e1b480", + "network_acl": "acl-c74e7dae" + } + }, + "subnets_count": 3 + } + }, + "vpcs_count": 1 + }, + "sa-east-1": { + "flow_logs": {}, + "flow_logs_count": 0, + "id": "sa-east-1", + "name": "sa-east-1", + "peering_connections": {}, + "peering_connections_count": 0, + "region": "sa-east-1", + "vpcs": { + "vpc-b14fa4d7": { + "arn": "arn:aws:vpc:sa-east-1:430150006394:virtual-private-cloud/vpc-b14fa4d7", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-b14fa4d7", + "name": "vpc-b14fa4d7", + "network_acls": { + "acl-43816e25": { + "Associations": [ + { + "NetworkAclAssociationId": "aclassoc-7477890a", + "NetworkAclId": "acl-43816e25", + "SubnetId": "subnet-9aa5c1fc" + }, + { + "NetworkAclAssociationId": "aclassoc-7277890c", + "NetworkAclId": "acl-43816e25", + "SubnetId": "subnet-aaddbef1" + }, + { + "NetworkAclAssociationId": "aclassoc-7577890b", + "NetworkAclId": "acl-43816e25", + "SubnetId": "subnet-6a4dd723" + } + ], + "IsDefault": true, + "OwnerId": "430150006394", + "Tags": [], + "VpcId": "vpc-b14fa4d7", + "allow_all_egress_traffic": "100", + "allow_all_ingress_traffic": "100", + "id": "acl-43816e25", + "name": "acl-43816e25", + "rules": { + "egress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + }, + "ingress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + } + }, + "use_default_egress_rules": true, + "use_default_ingress_rules": true + } + }, + "network_acls_count": 1, + "state": "available", + "subnets": { + "subnet-6a4dd723": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "sa-east-1b", + "AvailabilityZoneId": "sae1-az2", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.16.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:sa-east-1:430150006394:subnet/subnet-6a4dd723", + "VpcId": "vpc-b14fa4d7", + "flow_logs": [], + "id": "subnet-6a4dd723", + "name": "subnet-6a4dd723", + "network_acl": "acl-43816e25" + }, + "subnet-9aa5c1fc": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "sa-east-1a", + "AvailabilityZoneId": "sae1-az1", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.0.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:sa-east-1:430150006394:subnet/subnet-9aa5c1fc", + "VpcId": "vpc-b14fa4d7", + "flow_logs": [], + "id": "subnet-9aa5c1fc", + "name": "subnet-9aa5c1fc", + "network_acl": "acl-43816e25" + }, + "subnet-aaddbef1": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "sa-east-1c", + "AvailabilityZoneId": "sae1-az3", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.32.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:sa-east-1:430150006394:subnet/subnet-aaddbef1", + "VpcId": "vpc-b14fa4d7", + "flow_logs": [], + "id": "subnet-aaddbef1", + "name": "subnet-aaddbef1", + "network_acl": "acl-43816e25" + } + }, + "subnets_count": 3 + } + }, + "vpcs_count": 1 + }, + "us-east-1": { + "flow_logs": {}, + "flow_logs_count": 0, + "id": "us-east-1", + "name": "us-east-1", + "peering_connections": {}, + "peering_connections_count": 0, + "region": "us-east-1", + "vpcs": { + "vpc-ba1cbdc7": { + "arn": "arn:aws:vpc:us-east-1:430150006394:virtual-private-cloud/vpc-ba1cbdc7", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-ba1cbdc7", + "name": "vpc-ba1cbdc7", + "network_acls": { + "acl-f1a6ae8c": { + "Associations": [ + { + "NetworkAclAssociationId": "aclassoc-ad34c3ff", + "NetworkAclId": "acl-f1a6ae8c", + "SubnetId": "subnet-7056187e" + }, + { + "NetworkAclAssociationId": "aclassoc-af34c3fd", + "NetworkAclId": "acl-f1a6ae8c", + "SubnetId": "subnet-30be2f6f" + }, + { + "NetworkAclAssociationId": "aclassoc-ac34c3fe", + "NetworkAclId": "acl-f1a6ae8c", + "SubnetId": "subnet-8c27ffbd" + }, + { + "NetworkAclAssociationId": "aclassoc-5233c400", + "NetworkAclId": "acl-f1a6ae8c", + "SubnetId": "subnet-6e61f24f" + }, + { + "NetworkAclAssociationId": "aclassoc-ae34c3fc", + "NetworkAclId": "acl-f1a6ae8c", + "SubnetId": "subnet-cbefcb86" + }, + { + "NetworkAclAssociationId": "aclassoc-a934c3fb", + "NetworkAclId": "acl-f1a6ae8c", + "SubnetId": "subnet-77e07411" + } + ], + "IsDefault": true, + "OwnerId": "430150006394", + "Tags": [], + "VpcId": "vpc-ba1cbdc7", + "allow_all_egress_traffic": "100", + "allow_all_ingress_traffic": "100", + "id": "acl-f1a6ae8c", + "name": "acl-f1a6ae8c", + "rules": { + "egress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + }, + "ingress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + } + }, + "use_default_egress_rules": true, + "use_default_ingress_rules": true + } + }, + "network_acls_count": 1, + "state": "available", + "subnets": { + "subnet-30be2f6f": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-east-1c", + "AvailabilityZoneId": "use1-az6", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.32.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:us-east-1:430150006394:subnet/subnet-30be2f6f", + "VpcId": "vpc-ba1cbdc7", + "flow_logs": [], + "id": "subnet-30be2f6f", + "name": "subnet-30be2f6f", + "network_acl": "acl-f1a6ae8c" + }, + "subnet-6e61f24f": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-east-1a", + "AvailabilityZoneId": "use1-az2", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.80.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:us-east-1:430150006394:subnet/subnet-6e61f24f", + "VpcId": "vpc-ba1cbdc7", + "flow_logs": [], + "id": "subnet-6e61f24f", + "name": "subnet-6e61f24f", + "network_acl": "acl-f1a6ae8c" + }, + "subnet-7056187e": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-east-1f", + "AvailabilityZoneId": "use1-az5", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.64.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:us-east-1:430150006394:subnet/subnet-7056187e", + "VpcId": "vpc-ba1cbdc7", + "flow_logs": [], + "id": "subnet-7056187e", + "name": "subnet-7056187e", + "network_acl": "acl-f1a6ae8c" + }, + "subnet-77e07411": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-east-1d", + "AvailabilityZoneId": "use1-az1", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.0.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:us-east-1:430150006394:subnet/subnet-77e07411", + "VpcId": "vpc-ba1cbdc7", + "flow_logs": [], + "id": "subnet-77e07411", + "name": "subnet-77e07411", + "network_acl": "acl-f1a6ae8c" + }, + "subnet-8c27ffbd": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-east-1e", + "AvailabilityZoneId": "use1-az3", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.48.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:us-east-1:430150006394:subnet/subnet-8c27ffbd", + "VpcId": "vpc-ba1cbdc7", + "flow_logs": [], + "id": "subnet-8c27ffbd", + "name": "subnet-8c27ffbd", + "network_acl": "acl-f1a6ae8c" + }, + "subnet-cbefcb86": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-east-1b", + "AvailabilityZoneId": "use1-az4", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.16.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:us-east-1:430150006394:subnet/subnet-cbefcb86", + "VpcId": "vpc-ba1cbdc7", + "flow_logs": [], + "id": "subnet-cbefcb86", + "name": "subnet-cbefcb86", + "network_acl": "acl-f1a6ae8c" + } + }, + "subnets_count": 6 + } + }, + "vpcs_count": 1 + }, + "us-east-2": { + "flow_logs": {}, + "flow_logs_count": 0, + "id": "us-east-2", + "name": "us-east-2", + "peering_connections": {}, + "peering_connections_count": 0, + "region": "us-east-2", + "vpcs": { + "vpc-e429ad8f": { + "arn": "arn:aws:vpc:us-east-2:430150006394:virtual-private-cloud/vpc-e429ad8f", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-e429ad8f", + "name": "vpc-e429ad8f", + "network_acls": { + "acl-b06507db": { + "Associations": [ + { + "NetworkAclAssociationId": "aclassoc-164f9a74", + "NetworkAclId": "acl-b06507db", + "SubnetId": "subnet-81a1eccd" + }, + { + "NetworkAclAssociationId": "aclassoc-114f9a73", + "NetworkAclId": "acl-b06507db", + "SubnetId": "subnet-18e60365" + }, + { + "NetworkAclAssociationId": "aclassoc-104f9a72", + "NetworkAclId": "acl-b06507db", + "SubnetId": "subnet-fac76891" + } + ], + "IsDefault": true, + "OwnerId": "430150006394", + "Tags": [], + "VpcId": "vpc-e429ad8f", + "allow_all_egress_traffic": "100", + "allow_all_ingress_traffic": "100", + "id": "acl-b06507db", + "name": "acl-b06507db", + "rules": { + "egress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + }, + "ingress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + } + }, + "use_default_egress_rules": true, + "use_default_ingress_rules": true + } + }, + "network_acls_count": 1, + "state": "available", + "subnets": { + "subnet-18e60365": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-east-2b", + "AvailabilityZoneId": "use2-az2", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.16.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:us-east-2:430150006394:subnet/subnet-18e60365", + "VpcId": "vpc-e429ad8f", + "flow_logs": [], + "id": "subnet-18e60365", + "name": "subnet-18e60365", + "network_acl": "acl-b06507db" + }, + "subnet-81a1eccd": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-east-2c", + "AvailabilityZoneId": "use2-az3", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.32.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:us-east-2:430150006394:subnet/subnet-81a1eccd", + "VpcId": "vpc-e429ad8f", + "flow_logs": [], + "id": "subnet-81a1eccd", + "name": "subnet-81a1eccd", + "network_acl": "acl-b06507db" + }, + "subnet-fac76891": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-east-2a", + "AvailabilityZoneId": "use2-az1", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.0.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:us-east-2:430150006394:subnet/subnet-fac76891", + "VpcId": "vpc-e429ad8f", + "flow_logs": [], + "id": "subnet-fac76891", + "name": "subnet-fac76891", + "network_acl": "acl-b06507db" + } + }, + "subnets_count": 3 + } + }, + "vpcs_count": 1 + }, + "us-west-1": { + "flow_logs": {}, + "flow_logs_count": 0, + "id": "us-west-1", + "name": "us-west-1", + "peering_connections": {}, + "peering_connections_count": 0, + "region": "us-west-1", + "vpcs": { + "vpc-6e6fa508": { + "arn": "arn:aws:vpc:us-west-1:430150006394:virtual-private-cloud/vpc-6e6fa508", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-6e6fa508", + "name": "vpc-6e6fa508", + "network_acls": { + "acl-14a0c772": { + "Associations": [ + { + "NetworkAclAssociationId": "aclassoc-a9f7b7d5", + "NetworkAclId": "acl-14a0c772", + "SubnetId": "subnet-64f07402" + }, + { + "NetworkAclAssociationId": "aclassoc-a8f7b7d4", + "NetworkAclId": "acl-14a0c772", + "SubnetId": "subnet-3162b36b" + } + ], + "IsDefault": true, + "OwnerId": "430150006394", + "Tags": [], + "VpcId": "vpc-6e6fa508", + "allow_all_egress_traffic": "100", + "allow_all_ingress_traffic": "100", + "id": "acl-14a0c772", + "name": "acl-14a0c772", + "rules": { + "egress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + }, + "ingress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + } + }, + "use_default_egress_rules": true, + "use_default_ingress_rules": true + } + }, + "network_acls_count": 1, + "state": "available", + "subnets": { + "subnet-3162b36b": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-west-1c", + "AvailabilityZoneId": "usw1-az3", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.0.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:us-west-1:430150006394:subnet/subnet-3162b36b", + "VpcId": "vpc-6e6fa508", + "flow_logs": [], + "id": "subnet-3162b36b", + "name": "subnet-3162b36b", + "network_acl": "acl-14a0c772" + }, + "subnet-64f07402": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-west-1a", + "AvailabilityZoneId": "usw1-az1", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.16.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:us-west-1:430150006394:subnet/subnet-64f07402", + "VpcId": "vpc-6e6fa508", + "flow_logs": [], + "id": "subnet-64f07402", + "name": "subnet-64f07402", + "network_acl": "acl-14a0c772" + } + }, + "subnets_count": 2 + } + }, + "vpcs_count": 1 + }, + "us-west-2": { + "flow_logs": {}, + "flow_logs_count": 0, + "id": "us-west-2", + "name": "us-west-2", + "peering_connections": {}, + "peering_connections_count": 0, + "region": "us-west-2", + "vpcs": { + "vpc-d45709ac": { + "arn": "arn:aws:vpc:us-west-2:430150006394:virtual-private-cloud/vpc-d45709ac", + "cidr_block": "172.31.0.0/16", + "default": true, + "id": "vpc-d45709ac", + "name": "vpc-d45709ac", + "network_acls": { + "acl-f76adc8c": { + "Associations": [ + { + "NetworkAclAssociationId": "aclassoc-5edb3d1c", + "NetworkAclId": "acl-f76adc8c", + "SubnetId": "subnet-1075cf4d" + }, + { + "NetworkAclAssociationId": "aclassoc-5ddb3d1f", + "NetworkAclId": "acl-f76adc8c", + "SubnetId": "subnet-64dae84f" + }, + { + "NetworkAclAssociationId": "aclassoc-5fdb3d1d", + "NetworkAclId": "acl-f76adc8c", + "SubnetId": "subnet-25f65d5d" + }, + { + "NetworkAclAssociationId": "aclassoc-5cdb3d1e", + "NetworkAclId": "acl-f76adc8c", + "SubnetId": "subnet-113ce95b" + } + ], + "IsDefault": true, + "OwnerId": "430150006394", + "Tags": [], + "VpcId": "vpc-d45709ac", + "allow_all_egress_traffic": "100", + "allow_all_ingress_traffic": "100", + "id": "acl-f76adc8c", + "name": "acl-f76adc8c", + "rules": { + "egress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + }, + "ingress": { + "100": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "allow", + "port_range": "1-65535", + "protocol": "ALL" + }, + "32767": { + "CidrBlock": "0.0.0.0/0", + "RuleAction": "deny", + "port_range": "1-65535", + "protocol": "ALL" + } + } + }, + "use_default_egress_rules": true, + "use_default_ingress_rules": true + } + }, + "network_acls_count": 1, + "state": "available", + "subnets": { + "subnet-1075cf4d": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-west-2c", + "AvailabilityZoneId": "usw2-az3", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.0.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:us-west-2:430150006394:subnet/subnet-1075cf4d", + "VpcId": "vpc-d45709ac", + "flow_logs": [], + "id": "subnet-1075cf4d", + "name": "subnet-1075cf4d", + "network_acl": "acl-f76adc8c" + }, + "subnet-113ce95b": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-west-2b", + "AvailabilityZoneId": "usw2-az2", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.32.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:us-west-2:430150006394:subnet/subnet-113ce95b", + "VpcId": "vpc-d45709ac", + "flow_logs": [], + "id": "subnet-113ce95b", + "name": "subnet-113ce95b", + "network_acl": "acl-f76adc8c" + }, + "subnet-25f65d5d": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-west-2a", + "AvailabilityZoneId": "usw2-az1", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.16.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:us-west-2:430150006394:subnet/subnet-25f65d5d", + "VpcId": "vpc-d45709ac", + "flow_logs": [], + "id": "subnet-25f65d5d", + "name": "subnet-25f65d5d", + "network_acl": "acl-f76adc8c" + }, + "subnet-64dae84f": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-west-2d", + "AvailabilityZoneId": "usw2-az4", + "AvailableIpAddressCount": 4091, + "CidrBlock": "172.31.48.0/20", + "CidrBlockv6": null, + "DefaultForAz": true, + "Ipv6CidrBlockAssociationSet": [], + "MapCustomerOwnedIpOnLaunch": false, + "MapPublicIpOnLaunch": true, + "OwnerId": "430150006394", + "State": "available", + "SubnetArn": "arn:aws:ec2:us-west-2:430150006394:subnet/subnet-64dae84f", + "VpcId": "vpc-d45709ac", + "flow_logs": [], + "id": "subnet-64dae84f", + "name": "subnet-64dae84f", + "network_acl": "acl-f76adc8c" + } + }, + "subnets_count": 4 + } + }, + "vpcs_count": 1 + } + }, + "regions_count": 17 + } + }, + "sg_map": { + "sg-000c4c21c24f75b85": { + "region": "eu-west-3", + "vpc_id": "vpc-87d3fdee" + }, + "sg-02063087593480392": { + "region": "eu-west-1", + "vpc_id": "vpc-f24c7994" + }, + "sg-09c1e96a": { + "region": "eu-north-1", + "vpc_id": "vpc-fa259d93" + }, + "sg-0c59ae38c42100171": { + "region": "eu-west-1", + "vpc_id": "vpc-f24c7994" + }, + "sg-186a6a69": { + "region": "eu-west-1", + "vpc_id": "vpc-f24c7994" + }, + "sg-223b755a": { + "region": "eu-west-2", + "vpc_id": "vpc-3fa2fa57" + }, + "sg-3965844c": { + "region": "sa-east-1", + "vpc_id": "vpc-b14fa4d7" + }, + "sg-3e983346": { + "region": "ap-south-1", + "vpc_id": "vpc-2651a14d" + }, + "sg-4574a94e": { + "region": "us-east-1", + "vpc_id": "vpc-ba1cbdc7" + }, + "sg-4cc9d827": { + "region": "eu-west-3", + "vpc_id": "vpc-87d3fdee" + }, + "sg-62215504": { + "region": "ca-central-1", + "vpc_id": "vpc-b5113ddd" + }, + "sg-6569b32b": { + "region": "ap-northeast-1", + "vpc_id": "vpc-0cbc506a" + }, + "sg-71eb4839": { + "region": "ap-southeast-1", + "vpc_id": "vpc-04ed1062" + }, + "sg-778f4e3e": { + "region": "us-west-1", + "vpc_id": "vpc-6e6fa508" + }, + "sg-854e9bfe": { + "region": "ap-northeast-2", + "vpc_id": "vpc-73f44e18" + }, + "sg-8a48ccc0": { + "region": "ap-southeast-2", + "vpc_id": "vpc-5d22c33b" + }, + "sg-9be71df6": { + "region": "ap-northeast-3", + "vpc_id": "vpc-47b7dd2e" + }, + "sg-a81474db": { + "region": "us-east-2", + "vpc_id": "vpc-e429ad8f" + }, + "sg-a9b5628e": { + "region": "us-west-2", + "vpc_id": "vpc-d45709ac" + }, + "sg-c1194bbf": { + "region": "eu-central-1", + "vpc_id": "vpc-78b43312" + } + }, + "subnet_map": { + "subnet-0c0bc26a": { + "region": "ap-southeast-2", + "vpc_id": "vpc-5d22c33b" + }, + "subnet-1075cf4d": { + "region": "us-west-2", + "vpc_id": "vpc-d45709ac" + }, + "subnet-113ce95b": { + "region": "us-west-2", + "vpc_id": "vpc-d45709ac" + }, + "subnet-18e60365": { + "region": "us-east-2", + "vpc_id": "vpc-e429ad8f" + }, + "subnet-1cd98b74": { + "region": "ca-central-1", + "vpc_id": "vpc-b5113ddd" + }, + "subnet-1d972e74": { + "region": "eu-north-1", + "vpc_id": "vpc-fa259d93" + }, + "subnet-214f3969": { + "region": "eu-west-1", + "vpc_id": "vpc-f24c7994" + }, + "subnet-2506d06d": { + "region": "ap-southeast-1", + "vpc_id": "vpc-04ed1062" + }, + "subnet-25f65d5d": { + "region": "us-west-2", + "vpc_id": "vpc-d45709ac" + }, + "subnet-292d4343": { + "region": "eu-central-1", + "vpc_id": "vpc-78b43312" + }, + "subnet-30be2f6f": { + "region": "us-east-1", + "vpc_id": "vpc-ba1cbdc7" + }, + "subnet-3162b36b": { + "region": "us-west-1", + "vpc_id": "vpc-6e6fa508" + }, + "subnet-43bf9d2a": { + "region": "eu-west-2", + "vpc_id": "vpc-3fa2fa57" + }, + "subnet-4dcc0924": { + "region": "ap-northeast-3", + "vpc_id": "vpc-47b7dd2e" + }, + "subnet-4f896210": { + "region": "ca-central-1", + "vpc_id": "vpc-b5113ddd" + }, + "subnet-546a8e2f": { + "region": "ap-northeast-3", + "vpc_id": "vpc-47b7dd2e" + }, + "subnet-55d77f19": { + "region": "eu-central-1", + "vpc_id": "vpc-78b43312" + }, + "subnet-593d2502": { + "region": "ap-northeast-1", + "vpc_id": "vpc-0cbc506a" + }, + "subnet-64dae84f": { + "region": "us-west-2", + "vpc_id": "vpc-d45709ac" + }, + "subnet-64f07402": { + "region": "us-west-1", + "vpc_id": "vpc-6e6fa508" + }, + "subnet-6a4dd723": { + "region": "sa-east-1", + "vpc_id": "vpc-b14fa4d7" + }, + "subnet-6cb44e24": { + "region": "ap-southeast-2", + "vpc_id": "vpc-5d22c33b" + }, + "subnet-6e61f24f": { + "region": "us-east-1", + "vpc_id": "vpc-ba1cbdc7" + }, + "subnet-7056187e": { + "region": "us-east-1", + "vpc_id": "vpc-ba1cbdc7" + }, + "subnet-762a450d": { + "region": "eu-west-3", + "vpc_id": "vpc-87d3fdee" + }, + "subnet-77e07411": { + "region": "us-east-1", + "vpc_id": "vpc-ba1cbdc7" + }, + "subnet-7d5a1431": { + "region": "ap-south-1", + "vpc_id": "vpc-2651a14d" + }, + "subnet-7f50e154": { + "region": "ap-northeast-1", + "vpc_id": "vpc-0cbc506a" + }, + "subnet-81a1eccd": { + "region": "us-east-2", + "vpc_id": "vpc-e429ad8f" + }, + "subnet-8447addb": { + "region": "ap-northeast-2", + "vpc_id": "vpc-73f44e18" + }, + "subnet-85711fff": { + "region": "ca-central-1", + "vpc_id": "vpc-b5113ddd" + }, + "subnet-8c27ffbd": { + "region": "us-east-1", + "vpc_id": "vpc-ba1cbdc7" + }, + "subnet-9aa5c1fc": { + "region": "sa-east-1", + "vpc_id": "vpc-b14fa4d7" + }, + "subnet-a448d5fd": { + "region": "ap-southeast-1", + "vpc_id": "vpc-04ed1062" + }, + "subnet-a668c6ee": { + "region": "ap-northeast-1", + "vpc_id": "vpc-0cbc506a" + }, + "subnet-aaddbef1": { + "region": "sa-east-1", + "vpc_id": "vpc-b14fa4d7" + }, + "subnet-af6809d4": { + "region": "ap-northeast-2", + "vpc_id": "vpc-73f44e18" + }, + "subnet-b1c2a5d7": { + "region": "eu-west-1", + "vpc_id": "vpc-f24c7994" + }, + "subnet-b309b8fe": { + "region": "eu-west-3", + "vpc_id": "vpc-87d3fdee" + }, + "subnet-b3a000e9": { + "region": "eu-west-1", + "vpc_id": "vpc-f24c7994" + }, + "subnet-b3fe86eb": { + "region": "ap-southeast-2", + "vpc_id": "vpc-5d22c33b" + }, + "subnet-b73197d1": { + "region": "ap-southeast-1", + "vpc_id": "vpc-04ed1062" + }, + "subnet-c1b6118c": { + "region": "ap-northeast-3", + "vpc_id": "vpc-47b7dd2e" + }, + "subnet-c98e7484": { + "region": "eu-north-1", + "vpc_id": "vpc-fa259d93" + }, + "subnet-cbefcb86": { + "region": "us-east-1", + "vpc_id": "vpc-ba1cbdc7" + }, + "subnet-cf001883": { + "region": "ap-northeast-2", + "vpc_id": "vpc-73f44e18" + }, + "subnet-d3c151a8": { + "region": "ap-south-1", + "vpc_id": "vpc-2651a14d" + }, + "subnet-e682ec9c": { + "region": "eu-west-2", + "vpc_id": "vpc-3fa2fa57" + }, + "subnet-e6ad198d": { + "region": "ap-northeast-2", + "vpc_id": "vpc-73f44e18" + }, + "subnet-e9e1b480": { + "region": "eu-west-3", + "vpc_id": "vpc-87d3fdee" + }, + "subnet-ecc66390": { + "region": "eu-central-1", + "vpc_id": "vpc-78b43312" + }, + "subnet-edaf13a1": { + "region": "eu-west-2", + "vpc_id": "vpc-3fa2fa57" + }, + "subnet-f0fde498": { + "region": "ap-south-1", + "vpc_id": "vpc-2651a14d" + }, + "subnet-fac76891": { + "region": "us-east-2", + "vpc_id": "vpc-e429ad8f" + }, + "subnet-fe16ce85": { + "region": "eu-north-1", + "vpc_id": "vpc-fa259d93" + } + } +} \ No newline at end of file diff --git a/unittests/scans/scout_suite/no_vuln.js b/unittests/scans/scout_suite/no_vuln.js index b3b55934c5..b8b8e176e6 100644 --- a/unittests/scans/scout_suite/no_vuln.js +++ b/unittests/scans/scout_suite/no_vuln.js @@ -1,2 +1,1475 @@ scoutsuite_results = -{"account_id": "project-id","all_projects": false,"environment": "default","folder_id": null,"last_run": {"ruleset_about": "This ruleset consists of numerous rules that are considered standard by NCC Group. The rules enabled range from violations of well-known security best practices to gaps resulting from less-known security implications of provider-specific mechanisms. Additional rules exist, some of them requiring extra-parameters to be configured, and some of them being applicable to a limited number of users.","ruleset_name": "default","run_parameters": {"excluded_regions": null,"regions": null,"services": [],"skipped_services": []},"summary": {"cloudsql": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 6},"cloudstorage": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 4},"computeengine": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 11},"iam": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 9},"kms": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 0},"kubernetesengine": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 19},"stackdriverlogging": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 1},"stackdrivermonitoring": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 0}},"time": "2021-01-08 17:16:19+0100","version": "5.10.2"},"metadata": {"compute": {"computeengine": {"resources": {"firewalls": {"cols": 2,"count": 0,"full_path": "services.computeengine.projects.id.firewalls","path": "services.computeengine.projects.id.firewalls","script": "services.computeengine.projects.firewalls"},"instances": {"cols": 2,"count": 0,"full_path": "services.computeengine.projects.id.zones.id.instances","path": "services.computeengine.projects.id.zones.id.instances","script": "services.computeengine.projects.zones.instances"},"networks": {"cols": 2,"count": 0,"full_path": "services.computeengine.projects.id.networks","path": "services.computeengine.projects.id.networks","script": "services.computeengine.projects.networks"},"snapshots": {"cols": 2,"count": 0,"full_path": "services.computeengine.projects.id.snapshots","path": "services.computeengine.projects.id.snapshots","script": "services.computeengine.projects.snapshots"},"subnetworks": {"cols": 2,"count": 0,"full_path": "services.computeengine.projects.id.regions.id.subnetworks","path": "services.computeengine.projects.id.regions.id.subnetworks","script": "services.computeengine.projects.regions.subnetworks"}}},"kubernetesengine": {"resources": {"clusters": {"cols": 2,"count": 0,"full_path": "services.kubernetesengine.projects.id.zones.id.clusters","path": "services.kubernetesengine.projects.id.zones.id.clusters","script": "services.kubernetesengine.projects.zones.clusters"}}}},"database": {"cloudsql": {"resources": {"instances": {"cols": 2,"count": 0,"full_path": "services.cloudsql.projects.id.instances","path": "services.cloudsql.projects.id.instances","script": "services.cloudsql.projects.instances"}}}},"management": {"stackdriverlogging": {"resources": {"metrics": {"cols": 2,"count": 0,"full_path": "services.stackdriverlogging.projects.id.metrics","path": "services.stackdriverlogging.projects.id.metrics","script": "services.stackdriverlogging.projects.metrics"},"sinks": {"cols": 2,"count": 0,"full_path": "services.stackdriverlogging.projects.id.sinks","path": "services.stackdriverlogging.projects.id.sinks","script": "services.stackdriverlogging.projects.sinks"}}},"stackdrivermonitoring": {"resources": {"alert_policies": {"cols": 2,"count": 0,"full_path": "services.stackdrivermonitoring.projects.id.alert_policies","path": "services.stackdrivermonitoring.projects.id.alert_policies","script": "services.stackdrivermonitoring.projects.alert_policies"},"uptime_checks": {"cols": 2,"count": 0,"full_path": "services.stackdrivermonitoring.projects.id.uptime_checks","path": "services.stackdrivermonitoring.projects.id.uptime_checks","script": "services.stackdrivermonitoring.projects.uptime_checks"}}}},"security": {"iam": {"resources": {"bindings": {"cols": 2,"count": 0,"full_path": "services.iam.projects.id.bindings","path": "services.iam.projects.id.bindings","script": "services.iam.projects.bindings"},"groups": {"cols": 2,"count": 0,"full_path": "services.iam.projects.id.groups","path": "services.iam.projects.id.groups","script": "services.iam.projects.groups"},"service_accounts": {"cols": 2,"count": 0,"full_path": "services.iam.projects.id.service_accounts","path": "services.iam.projects.id.service_accounts","script": "services.iam.projects.service_accounts"},"users": {"cols": 2,"count": 0,"full_path": "services.iam.projects.id.users","path": "services.iam.projects.id.users","script": "services.iam.projects.users"}}},"kms": {"resources": {"keyrings": {"cols": 2,"count": 0,"full_path": "services.kms.projects.id.keyrings","path": "services.kms.projects.id.keyrings","script": "services.kms.projects.keyrings"}}}},"storage": {"cloudstorage": {"resources": {"buckets": {"cols": 2,"count": 0,"full_path": "services.cloudstorage.projects.id.buckets","path": "services.cloudstorage.projects.id.buckets","script": "services.cloudstorage.projects.buckets"}}}}},"organization_id": null,"project_id": "project-id","provider_code": "gcp","provider_name": "Google Cloud Platform","result_format": "json","service_list": ["cloudsql","cloudstorage","computeengine","iam","kms","stackdriverlogging","stackdrivermonitoring","kubernetesengine"],"services": {"cloudsql": {"filters": {},"findings": {"cloudsql-allows-root-login-from-any-host": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "6.4","version": "1.0.0"}],"dashboard_name": "Instances","description": "Instance Allows Root Login from Any Host","flagged_items": 0,"id_suffix": "root_access_from_any_host","items": [],"level": "warning","path": "cloudsql.projects.id.instances.id","rationale": "Root access to MySQL Database Instances should be allowed only through trusted IPs.","references": ["https://forsetisecurity.org/docs/latest/concepts/best-practices.html#cloud-sql","https://cloud.google.com/blog/products/gcp/best-practices-for-securing-your-google-cloud-databases"],"remediation": null,"service": "Cloud SQL"},"cloudsql-instance-backups-disabled": {"checked_items": 0,"compliance": null,"dashboard_name": "Instances","description": "Instance with Automatic Backups Disabled","flagged_items": 0,"id_suffix": "automatic_backup_enabled","items": [],"level": "warning","path": "cloudsql.projects.id.instances.id","rationale": "Automatic backups should be configured for Cloud SQL instances in order to ensure backups are created regularly.","references": ["https://cloud.google.com/sql/docs/mysql/backup-recovery/backups"],"remediation": null,"service": "Cloud SQL"},"cloudsql-instance-is-open-to-the-world": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "6.2","version": "1.0.0"}],"dashboard_name": "Instances","description": "Instance Allowing All Incoming Connections","display_path": "cloudsql.projects.id.instances.id","flagged_items": 0,"id_suffix": "open_to_the_world","items": [],"level": "danger","path": "cloudsql.projects.id.instances.id.authorized_networks.id","rationale": "Database instances should accept connections from trusted IPs and networks only.","references": null,"remediation": null,"service": "Cloud SQL"},"cloudsql-instance-no-binary-logging": {"checked_items": 0,"compliance": null,"dashboard_name": "Instances","description": "Instance with Binary Logging Disabled","flagged_items": 0,"id_suffix": "log_enabled","items": [],"level": "warning","path": "cloudsql.projects.id.instances.id","rationale": "The benefits of enabling binary logs (replication, scalability, auditability, point-in-time data recovery, etc.) can improve the security posture of the Cloud SQL instance.","references": ["https://cloud.google.com/sql/docs/mysql/instance-settings","https://cloud.google.com/sql/docs/mysql/replication/tips"],"remediation": null,"service": "Cloud SQL"},"cloudsql-instance-ssl-not-required": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "6.1","version": "1.0.0"}],"dashboard_name": "Instances","description": "Instance Not Requiring SSL for Incoming Connections","flagged_items": 0,"id_suffix": "ssl_required","items": [],"level": "warning","path": "cloudsql.projects.id.instances.id","rationale": "All incoming connections to databases should require the use of SSL.","references": ["https://cloud.google.com/sql/docs/mysql/authorize-ssl"],"remediation": null,"service": "Cloud SQL"},"cloudsql-instance-with-no-backups": {"checked_items": 0,"compliance": null,"dashboard_name": "Instances","description": "Instance with No Backups","flagged_items": 0,"id_suffix": "last_backup_timestamp","items": [],"level": "warning","path": "cloudsql.projects.id.instances.id","rationale": "Weekly or monthly backups should be created of all databases holding sensitive information.","references": ["https://cloud.google.com/sql/docs/mysql/backup-recovery/backups"],"remediation": null,"service": "Cloud SQL"}},"instances_count": 0,"projects": {}},"cloudstorage": {"buckets_count": 0,"filters": {},"findings": {"cloudstorage-bucket-allAuthenticatedUsers": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "5.1","version": "1.0.0"}],"dashboard_name": "Buckets","description": "Bucket Accessible by \"allAuthenticatedUsers\"","display_path": "cloudstorage.projects.id.buckets.id","flagged_items": 0,"id_suffix": "allAuthenticatedUsers","items": [],"level": "danger","path": "cloudstorage.projects.id.buckets.id","rationale": "Allowing anonymous and/or public access grants permissions to anyone to access bucket content. Such access might not be desired if you are storing any sensitive data. Hence, ensure that anonymous and/or public access to a bucket is not allowed.","references": ["https://cloud.google.com/storage/docs/access-control/iam-reference","https://cloud.google.com/storage/docs/access-control/making-data-public"],"remediation": "No role should contain \"allUsers\" and/or \"allAuthenticatedUsers\" as a member.","service": "Cloud Storage"},"cloudstorage-bucket-allUsers": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "5.1","version": "1.0.0"}],"dashboard_name": "Buckets","description": "Bucket Accessible by \"allUsers\"","display_path": "cloudstorage.projects.id.buckets.id","flagged_items": 0,"id_suffix": "allUsers","items": [],"level": "danger","path": "cloudstorage.projects.id.buckets.id","rationale": "Allowing anonymous and/or public access grants permissions to anyone to access bucket content. Such access might not be desired if you are storing any sensitive data. Hence, ensure that anonymous and/or public access to a bucket is not allowed.","references": ["https://cloud.google.com/storage/docs/access-control/iam-reference","https://cloud.google.com/storage/docs/access-control/making-data-public"],"remediation": "No role should contain \"allUsers\" and/or \"allAuthenticatedUsers\" as a member.","service": "Cloud Storage"},"cloudstorage-bucket-no-logging": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "5.3","version": "1.0.0"}],"dashboard_name": "Buckets","description": "Bucket with Logging Disabled","flagged_items": 0,"id_suffix": "logging_enabled","items": [],"level": "warning","path": "cloudstorage.projects.id.buckets.id","rationale": "Enable access and storage logs, in order to capture all events which may affect objects within target buckets.","references": ["https://cloud.google.com/storage/docs/access-logs"],"remediation": null,"service": "Cloud Storage"},"cloudstorage-bucket-no-versioning": {"checked_items": 0,"compliance": null,"dashboard_name": "Buckets","description": "Bucket with Versioning Disabled","flagged_items": 0,"id_suffix": "versioning_enabled","items": [],"level": "warning","path": "cloudstorage.projects.id.buckets.id","rationale": "Enable Object Versioning to protect Cloud Storage data from being overwritten or accidentally deleted.","references": ["https://cloud.google.com/storage/docs/using-object-versioning"],"remediation": null,"service": "Cloud Storage"}},"projects": {}},"computeengine": {"filters": {},"findings": {"computeengine-firewall-default-rule-in-use": {"checked_items": 0,"compliance": null,"dashboard_name": "Firewall Rule","description": "Default Firewall Rule in Use","flagged_items": 0,"id_suffix": "name","items": [],"level": "warning","path": "computeengine.projects.id.firewalls.id","rationale": "Some default firewall rules were in use. This could potentially expose sensitive services or protocols to other networks.","references": null,"remediation": null,"service": "Compute Engine"},"computeengine-firewall-rule-allows-all-ports": {"checked_items": 0,"compliance": null,"dashboard_name": "Firewall Rule Elements","description": "Firewall Rule Opens All Ports (0-65535)","display_path": "computeengine.projects.id.firewalls.id","flagged_items": 0,"id_suffix": "permissive_ports","items": [],"level": "warning","path": "computeengine.projects.id.firewalls.id.allowed_traffic.id.ports.id","rationale": "The firewall rule allows access to all ports. This widens the attack surface of the infrastructure and makes it easier for an attacker to reach potentially sensitive services over the network.","references": null,"remediation": null,"service": "Compute Engine"},"computeengine-firewall-rule-allows-internal-traffic": {"checked_items": 0,"compliance": null,"dashboard_name": "Firewall Rule Elements","description": "Firewall Rule Allows Internal Traffic","display_path": "computeengine.projects.id.firewalls.id","flagged_items": 0,"id_suffix": "permissive_ports","items": [],"level": "warning","path": "computeengine.projects.id.firewalls.id.allowed_traffic.id.ports.id","rationale": "Firewall rule allows ingress connections for all protocols and ports among instances in the network.","references": null,"remediation": null,"service": "Compute Engine"},"computeengine-firewall-rule-allows-port-range": {"checked_items": 0,"compliance": null,"dashboard_name": "Firewall Rule Elements","description": "Firewall Rule Allows Port Range(s)","display_path": "computeengine.projects.id.firewalls.id","flagged_items": 0,"id_suffix": "permissive_ports","items": [],"level": "warning","path": "computeengine.projects.id.firewalls.id.allowed_traffic.id.ports.id","rationale": "It was found that the firewall rule was using port ranges. Sometimes, ranges could include unintended ports that should not be exposed. As a result, when possible, explicit port lists should be used instead.","references": null,"remediation": null,"service": "Compute Engine"},"computeengine-firewall-rule-allows-public-access": {"checked_items": 0,"compliance": null,"dashboard_name": "Firewall Rules","description": "Firewall Rule Allows Public Access (0.0.0.0/0)","flagged_items": 0,"id_suffix": "source_ranges","items": [],"level": "warning","path": "computeengine.projects.id.firewalls.id","rationale": "The firewall rule was found to be exposing potentially open ports to all source addresses. Ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.","references": null,"remediation": null,"service": "Compute Engine"},"computeengine-firewall-rule-opens-all-ports-to-all": {"checked_items": 0,"compliance": null,"dashboard_name": "Firewall Rule Elements","description": "Firewall Rule Allows Public Access (0.0.0.0/0) to All Ports (0-65535)","display_path": "computeengine.projects.id.firewalls.id","flagged_items": 0,"id_suffix": "permissive_ports","items": [],"level": "warning","path": "computeengine.projects.id.firewalls.id.allowed_traffic.id.ports.id","rationale": "The firewall rule was found to be exposing all ports to all source addresses. Ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.","references": null,"remediation": null,"service": "Compute Engine"},"computeengine-firewall-rule-opens-sensitive-port-to-all": {"checked_items": 0,"compliance": null,"dashboard_name": "Firewall Rule Elements","description": "Firewall INGRESS Rule Allows Public Access (0.0.0.0/0) to a Sensitive Port","display_path": "computeengine.projects.id.firewalls.id","flagged_items": 0,"id_suffix": "permissive_ports","items": [],"level": "warning","path": "computeengine.projects.id.firewalls.id.allowed_traffic.id.ports.id","rationale": "The firewall rule was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.","references": null,"remediation": null,"service": "Compute Engine"},"computeengine-instance-disk-with-no-snapshot": {"checked_items": 0,"compliance": null,"dashboard_name": "Instances","description": "Instance Disk without Snapshots","display_path": "computeengine.projects.id.zones.id.instances.id","flagged_items": 0,"id_suffix": "latest_snapshot","items": [],"level": "warning","path": "computeengine.projects.id.zones.id.instances.id.disks.id","rationale": "You should have snapshots of your in-use or available disks taken on a regular basis to enable disaster recovery efforts.","references": ["https://cloud.google.com/compute/docs/disks/create-snapshots","https://cloud.google.com/compute/docs/disks/scheduled-snapshots","https://cloud.google.com/compute/docs/disks/snapshot-best-practices"],"remediation": null,"service": "Compute Engine"},"computeengine-instance-with-deletion-protection-disabled": {"checked_items": 0,"compliance": null,"dashboard_name": "Instances","description": "Instance without Deletion Protection","flagged_items": 0,"id_suffix": "deletion_protection_enabled","items": [],"level": "warning","path": "computeengine.projects.id.zones.id.instances.id","rationale": "It is good practice to enable this feature on production instances, to ensure that they may not be deleted by accident.","references": ["https://cloud.google.com/compute/docs/instances/preventing-accidental-vm-deletion"],"remediation": null,"service": "Compute Engine"},"computeengine-network-with-no-instances": {"checked_items": 0,"compliance": null,"dashboard_name": "Networks","description": "Network without Instances","flagged_items": 0,"items": [],"level": "warning","path": "computeengine.projects.id.networks.id","rationale": "Maintaining unused resources increases risks of misconfigurations and increases the difficulty of audits.","references": null,"remediation": null,"service": "Compute Engine"},"computeengine-old-disk-snapshot": {"checked_items": 0,"compliance": null,"dashboard_name": "Snapshots","description": "Old Instance Disk Snapshot","flagged_items": 0,"items": [],"level": "warning","path": "computeengine.projects.id.snapshots.id","rationale": "Disk snapshots that are over 90 days are likely to be outdated.","references": ["https://cloud.google.com/compute/docs/disks/create-snapshots","https://cloud.google.com/compute/docs/disks/scheduled-snapshots","https://cloud.google.com/compute/docs/disks/snapshot-best-practices"],"remediation": null,"service": "Compute Engine"}},"firewalls_count": 0,"instances_count": 0,"networks_count": 0,"projects": {},"snapshots_count": 0,"subnetworks_count": 0},"iam": {"bindings_count": 0,"filters": {},"findings": {"iam-gmail-accounts-used": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "1.1","version": "1.0.0"}],"dashboard_name": "Users","description": "Gmail Account in Use","flagged_items": 0,"id_suffix": "name","items": [],"level": "warning","path": "iam.projects.id.users.id","rationale": "Gmail accounts are personally created and controllable accounts. Organizations seldom have any control over them. Thus, it is recommended that you use fully managed corporate Google accounts for increased visibility, auditing, and control over access to Cloud Platform resources.","references": null,"remediation": null,"service": "IAM"},"iam-lack-of-service-account-key-rotation": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "1.6","version": "1.0.0"}],"dashboard_name": "Service Accounts","description": "Lack of Service Account Key Rotation","display_path": "iam.projects.id.service_accounts.id","flagged_items": 0,"id_suffix": "valid_after","items": [],"level": "warning","path": "iam.projects.id.service_accounts.id.keys.id","rationale": "Rotating Service Account keys will reduce the window of opportunity for an access key that is associated with a compromised or terminated account to be used. Service Account keys should be rotated to ensure that data cannot be accessed with an old key which might have been lost, cracked, or stolen. It should be ensured that keys are rotated every 90 days.","references": ["https://cloud.google.com/iam/docs/creating-managing-service-account-keys"],"remediation": null,"service": "IAM"},"iam-primitive-role-in-use": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "1.4","version": "1.0.0"}],"dashboard_name": "Bindings","description": "Primitive Role in Use","flagged_items": 0,"id_suffix": "name","items": [],"level": "warning","path": "iam.projects.id.bindings.id","rationale": "Primitive roles grant significant privileges. In most cases, usage of these roles is not recommended and does not follow security best practice.

Note: This rule may flag Google-Managed Service Accounts. Google services rely on these Service Accounts having access to the project, and recommends not removing or changing the Service Account's role (see https://cloud.google.com/iam/docs/service-accounts#google-managed).","references": ["https://cloud.google.com/iam/docs/understanding-roles","https://cloud.google.com/iam/docs/using-iam-securely"],"remediation": null,"service": "IAM"},"iam-role-assigned-to-user": {"checked_items": 0,"compliance": null,"dashboard_name": "Bindings","description": "IAM Role Assigned to User","flagged_items": 0,"id_suffix": "users","items": [],"level": "warning","path": "iam.projects.id.bindings.id","rationale": "Best practices recommends granting roles to a Google Suite group instead of to individual users when possible. It is easier to add members to and remove members from a group instead of updating a Cloud IAM policy to add or remove users.","references": ["https://cloud.google.com/iam/docs/understanding-roles","https://cloud.google.com/iam/docs/using-iam-securely"],"remediation": null,"service": "IAM"},"iam-sa-has-admin-privileges": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "1.4","version": "1.0.0"}],"dashboard_name": "Bindings","description": "Service Account with Admin Privileges","flagged_items": 0,"id_suffix": "service_accounts","items": [],"level": "warning","path": "iam.projects.id.bindings.id","rationale": "Service accounts represent service-level security of the Resources (application or a VM) which can be determined by the roles assigned to it. Enrolling Service Accounts with administrative privileges grants full access to assigned application or a VM, Service Account Access holder can user.

Note: This rule may flag Google-Managed Service Accounts. Google services rely on these Service Accounts having access to the project, and recommends not removing or changing the Service Account's role","references": ["https://cloud.google.com/iam/docs/service-accounts#google-managed","https://cloud.google.com/iam/docs/understanding-roles","https://cloud.google.com/iam/docs/using-iam-securely"],"remediation": null,"service": "IAM"},"iam-service-account-user-allAuthenticatedUsers": {"checked_items": 0,"compliance": null,"dashboard_name": "Service Accounts","description": "Service Account with 'allAuthenticatedUsers' Service Account User","display_path": "iam.projects.id.service_accounts.id","flagged_items": 0,"items": [],"level": "warning","path": "iam.projects.id.service_accounts.id.bindings.id","rationale": "Access to the Service Account User role (roles/iam.serviceAccountUser) should be restricted, as members granted this role on a service account can use it to indirectly access all the resources to which the service account has access. ","references": ["https://cloud.google.com/iam/docs/service-accounts#user-role"],"remediation": null,"service": "IAM"},"iam-service-account-user-allUsers": {"checked_items": 0,"compliance": null,"dashboard_name": "Service Accounts","description": "Service Account with 'allUsers' Service Account User","display_path": "iam.projects.id.service_accounts.id","flagged_items": 0,"items": [],"level": "warning","path": "iam.projects.id.service_accounts.id.bindings.id","rationale": "Access to the Service Account User role (roles/iam.serviceAccountUser) should be restricted, as members granted this role on a service account can use it to indirectly access all the resources to which the service account has access. ","references": ["https://cloud.google.com/iam/docs/service-accounts#user-role"],"remediation": null,"service": "IAM"},"iam-service-account-with-user-managed-keys": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "1.3","version": "1.0.0"}],"dashboard_name": "Service Accounts","description": "User-Managed Service Account Keys","display_path": "iam.projects.id.service_accounts.id","flagged_items": 0,"id_suffix": "key_type","items": [],"level": "warning","path": "iam.projects.id.service_accounts.id.keys.id","rationale": "It is recommended to prevent use of user-managed service account keys, as anyone who has access to the keys will be able to access resources through the service account. Best practice recommends using GCP-managed keys, which are used by Cloud Platform services such as App Engine and Compute Engine. These keys cannot be downloaded. Google will keep the keys and automatically rotate them on an approximately weekly basis.","references": ["https://cloud.google.com/iam/docs/understanding-service-accounts#managing_service_account_keys"],"remediation": null,"service": "IAM"},"iam-user-has-sa-user-role": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "1.5","version": "1.0.0"}],"dashboard_name": "Bindings","description": "User with \"Service Account User\" Role at the Project Level","flagged_items": 0,"id_suffix": "user_has_sa_user_role","items": [],"level": "warning","path": "iam.projects.id.bindings.id","rationale": "Granting the iam.serviceAccountUser role to a user for a project gives the user access to all service accounts in the project, including service accounts that may be created in the future. This can result into elevation of privileges by using service accounts and corresponding Compute Engine instances.","references": ["https://cloud.google.com/iam/docs/service-accounts#google-managed","https://cloud.google.com/iam/docs/understanding-roles","https://cloud.google.com/iam/docs/using-iam-securely"],"remediation": null,"service": "IAM"}},"groups_count": 0,"projects": {},"service_accounts_count": 0,"users_count": 0},"kms": {"filters": {},"findings": {},"keyrings_count": 0,"projects": {}},"kubernetesengine": {"clusters_count": 0,"filters": {},"findings": {"kubernetesengine-basic-authentication-enabled": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "7.10","version": "1.0.0"},{"name": "CIS GKE Benchmark","reference": "6.8.1","version": "1.0.0"}],"dashboard_name": "Clusters","description": "Basic Authentication Enabled","flagged_items": 0,"id_suffix": "basic_authentication_enabled","items": [],"level": "warning","path": "kubernetesengine.projects.id.zones.id.clusters.id","rationale": "Basic authentication allows a user to authenticate to the cluster with a username and password and it is stored in plain text without any encryption. Disabling Basic authentication will prevent attacks like brute force. Its recommended to use either client certificate or IAM for authentication.","references": ["https://www.cisecurity.org/benchmark/kubernetes/","https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_authn_methods","https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#evaluation_on"],"remediation": null,"service": "Kubernetes Engine"},"kubernetesengine-certificate-authentication-enabled": {"checked_items": 0,"compliance": [{"name": "CIS GKE Benchmark","reference": "6.8.2","version": "1.0.0"}],"dashboard_name": "Clusters","description": "Certificate Authentication Enabled","flagged_items": 0,"id_suffix": "client_certificate_enabled","items": [],"level": "warning","path": "kubernetesengine.projects.id.zones.id.clusters.id","rationale": "Unless applications use the client certificate authentication method, it should be disabled.","references": ["https://www.cisecurity.org/benchmark/kubernetes/","https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_authn_methods","https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#evaluation_on"],"remediation": null,"service": "Kubernetes Engine"},"kubernetesengine-cluster-alias-ip-disabled": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "7.13","version": "1.0.0"},{"name": "CIS GKE Benchmark","reference": "6.6.2","version": "1.0.0"}],"dashboard_name": "Clusters","description": "Alias IP Disabled","flagged_items": 0,"id_suffix": "alias_ip_disabled","items": [],"level": "warning","path": "kubernetesengine.projects.id.zones.id.clusters.id","rationale": "With Alias IPs ranges enabled, Kubernetes Engine clusters can allocate IP addresses from a CIDR block known to Google Cloud Platform. This makes your cluster more scalable and allows your cluster to better interact with other GCP products and entities.","references": ["https://www.cisecurity.org/benchmark/kubernetes/","https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_network_access_to_the_control_plane_and_nodes","https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on"],"remediation": null,"service": "Kubernetes Engine"},"kubernetesengine-cluster-has-no-labels": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "7.5","version": "1.0.0"}],"dashboard_name": "Clusters","description": "Clusters Lacking Labels","flagged_items": 0,"id_suffix": "has_no_labels","items": [],"level": "warning","path": "kubernetesengine.projects.id.zones.id.clusters.id","rationale": "Labels enable users to map their own organizational structures onto system objects in a loosely coupled fashion, without requiring clients to store these mappings. Labels can also be used to apply specific security settings and auto configure objects at creation.","references": ["https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#use_namespaces_and_rbac_to_restrict_access_to_cluster_resources"],"remediation": null,"service": "Kubernetes Engine"},"kubernetesengine-cluster-logging-disabled": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "7.1","version": "1.0.0"},{"name": "CIS GKE Benchmark","reference": "6.7.1","version": "1.0.0"}],"dashboard_name": "Clusters","description": "Cluster Logging Disabled","flagged_items": 0,"id_suffix": "logging_disabled","items": [],"level": "warning","path": "kubernetesengine.projects.id.zones.id.clusters.id","rationale": "You should enable cluster logging and use a logging service so your cluster can export logs about its activities.","references": ["https://www.cisecurity.org/benchmark/kubernetes/","https://kubernetes.io/docs/tasks/debug-application-cluster/audit/","https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#stackdriver_logging","https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on"],"remediation": null,"service": "Kubernetes Engine"},"kubernetesengine-cluster-master-authorized-networks-disabled": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "7.4","version": "1.0.0"},{"name": "CIS GKE Benchmark","reference": "6.6.3","version": "1.0.0"}],"dashboard_name": "Clusters","description": "Master Authorized Networks Disabled","flagged_items": 0,"id_suffix": "master_authorized_networks_disabled","items": [],"level": "warning","path": "kubernetesengine.projects.id.zones.id.clusters.id","rationale": "Master authorized networks blocks untrusted IP addresses from outside Google Cloud Platform. Addresses from inside GCP can still reach your master through HTTPS provided that they have the necessary Kubernetes credentials.","references": ["https://www.cisecurity.org/benchmark/kubernetes/","https://cloud.google.com/kubernetes-engine/docs/how-to/authorized-networks","https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_network_access_to_the_control_plane_and_nodes","https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on"],"remediation": null,"service": "Kubernetes Engine"},"kubernetesengine-cluster-monitoring-disabled": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "7.2","version": "1.0.0"},{"name": "CIS GKE Benchmark","reference": "6.7.1","version": "1.0.0"}],"dashboard_name": "Clusters","description": "Cluster Monitoring Disabled","flagged_items": 0,"id_suffix": "monitoring_disabled","items": [],"level": "warning","path": "kubernetesengine.projects.id.zones.id.clusters.id","rationale": "You should enable cluster monitoring and use a monitoring service so your cluster can export metrics about its activities.","references": ["https://www.cisecurity.org/benchmark/kubernetes/","https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#stackdriver_logging","https://cloud.google.com/monitoring/kubernetes-engine#about-skm","https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on"],"remediation": null,"service": "Kubernetes Engine"},"kubernetesengine-cluster-network-policy-disabled": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "7.11","version": "1.0.0"},{"name": "CIS GKE Benchmark","reference": "6.6.7","version": "1.0.0"}],"dashboard_name": "Clusters","description": "Network Policy Disabled","flagged_items": 0,"id_suffix": "network_policy_disabled","items": [],"level": "warning","path": "kubernetesengine.projects.id.zones.id.clusters.id","rationale": "By default, pods are non-isolated; they accept traffic from any source. Pods become isolated by having a NetworkPolicy that selects them. Once there is any NetworkPolicy in a namespace selecting a particular pod, that pod will reject any connections that are not allowed by any NetworkPolicy.","references": ["https://www.cisecurity.org/benchmark/kubernetes/","https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_with_network_policy","https://cloud.google.com/kubernetes-engine/docs/concepts/security-overview#network_security","https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on"],"remediation": null,"service": "Kubernetes Engine"},"kubernetesengine-cluster-pod-security-policy-config-disabled": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "7.14","version": "1.0.0"},{"name": "CIS GKE Benchmark","reference": "6.10.3","version": "1.0.0"}],"dashboard_name": "Clusters","description": "Pod Security Policy Disabled","flagged_items": 0,"id_suffix": "pod_security_policy_enabled","items": [],"level": "warning","path": "kubernetesengine.projects.id.zones.id.clusters.id","rationale": "A Pod Security Policy is a cluster-level resource that controls security sensitive aspects of the pod specification. The PodSecurityPolicy objects define a set of conditions that a pod must run with in order to be accepted into the system, as well as defaults for the related fields.","references": ["https://www.cisecurity.org/benchmark/kubernetes/","https://cloud.google.com/kubernetes-engine/docs/how-to/pod-security-policies","https://kubernetes.io/docs/concepts/policy/pod-security-policy","https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on"],"remediation": "Enable the Pod Security Policy. By default, Pod Security Policy is disabled when you create a new cluster.","service": "Kubernetes Engine"},"kubernetesengine-cluster-private-google-access-disabled": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "7.16","version": "1.0.0"}],"dashboard_name": "Clusters","description": "Private Google Access Disabled","flagged_items": 0,"id_suffix": "private_ip_google_access_disabled","items": [],"level": "warning","path": "kubernetesengine.projects.id.zones.id.clusters.id","rationale": "Enabling Private Google Access allows VMs on a subnetwork to use a private IP address to reach Google APIs rather than an external IP address.","references": ["https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_network_access_to_the_control_plane_and_nodes"],"remediation": null,"service": "Kubernetes Engine"},"kubernetesengine-dashboard-enabled": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "7.6","version": "1.0.0"},{"name": "CIS GKE Benchmark","reference": "6.10.1","version": "1.0.0"}],"dashboard_name": "Clusters","description": "The GKE Dashboard Enabled","flagged_items": 0,"id_suffix": "dashboard_status","items": [],"level": "warning","path": "kubernetesengine.projects.id.zones.id.clusters.id","rationale": "You should disable the Kubernetes Web UI (Dashboard) when running on Kubernetes Engine. The Kubernetes Web UI (Dashboard) is backed by a highly privileged Kubernetes Service Account.","references": ["https://www.cisecurity.org/benchmark/kubernetes/","https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#disable_kubernetes_dashboard","https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on"],"remediation": null,"service": "Kubernetes Engine"},"kubernetesengine-default-service-account-used": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "7.17","version": "1.0.0"},{"name": "CIS GKE Benchmark","reference": "6.2.1","version": "1.0.0"}],"dashboard_name": "Clusters","description": "Default Service Account in Use","flagged_items": 0,"id_suffix": "default_service_account_used","items": [],"level": "warning","path": "kubernetesengine.projects.id.zones.id.clusters.id","rationale": "You should create and use a minimally privileged service account to run your Kubernetes Engine cluster instead of using the Compute Engine default service account.","references": ["https://www.cisecurity.org/benchmark/kubernetes/","https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#use_least_privilege_sa","https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on"],"remediation": null,"service": "Kubernetes Engine"},"kubernetesengine-legacy-abac-enabled": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "7.3","version": "1.0.0"},{"name": "CIS GKE Benchmark","reference": "6.8.4","version": "1.0.0"}],"dashboard_name": "Clusters","description": "Legacy Authorization (ABAC) Enabled","flagged_items": 0,"id_suffix": "legacy_abac_enabled","items": [],"level": "warning","path": "kubernetesengine.projects.id.zones.id.clusters.id","rationale": "The legacy authorizer in Kubernetes Engine grants broad, statically defined permissions. To ensure that RBAC limits permissions correctly, you must disable the legacy authorizer. RBAC has significant security advantages, can help you ensure that users only have access to cluster resources within their own namespace and is now stable in Kubernetes.","references": ["https://www.cisecurity.org/benchmark/kubernetes/","https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#leave_abac_disabled_default_for_110","https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on"],"remediation": null,"service": "Kubernetes Engine"},"kubernetesengine-legacy-metadata-endpoints-enabled": {"checked_items": 0,"compliance": [{"name": "CIS GKE Benchmark","reference": "6.4.1","version": "1.0.0"}],"dashboard_name": "Clusters","description": "Legacy Metadata Endpoints Enabled","display_path": "kubernetesengine.projects.id.zones.id.clusters.id","flagged_items": 0,"id_suffix": "legacy_metadata_endpoints_enabled","items": [],"level": "warning","path": "kubernetesengine.projects.id.zones.id.clusters.id.node_pools.id","rationale": "Unless your app uses the legacy metadata endpoints, you should disable them.","references": ["https://www.cisecurity.org/benchmark/kubernetes/","https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#protect_node_metadata_default_for_112","https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on"],"remediation": null,"service": "Kubernetes Engine"},"kubernetesengine-node-auto-repair-disabled": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "7.7","version": "1.0.0"},{"name": "CIS GKE Benchmark","reference": "6.5.2","version": "1.0.0"}],"dashboard_name": "Clusters","description": "Nodes Auto-Repair Disabled","display_path": "kubernetesengine.projects.id.zones.id.clusters.id","flagged_items": 0,"id_suffix": "auto_repair_disabled","items": [],"level": "warning","path": "kubernetesengine.projects.id.zones.id.clusters.id.node_pools.id","rationale": "Auto-repair helps you keep the nodes in your cluster in a healthy, running state.","references": ["https://www.cisecurity.org/benchmark/kubernetes/","https://cloud.google.com/kubernetes-engine/docs/how-to/node-auto-repair","https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on"],"remediation": null,"service": "Kubernetes Engine"},"kubernetesengine-node-auto-upgrade-disabled": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "7.8","version": "1.0.0"},{"name": "CIS GKE Benchmark","reference": "6.5.3","version": "1.0.0"}],"dashboard_name": "Clusters","description": "Nodes Auto-Upgrade Disabled","display_path": "kubernetesengine.projects.id.zones.id.clusters.id","flagged_items": 0,"id_suffix": "auto_upgrade_disabled","items": [],"level": "warning","path": "kubernetesengine.projects.id.zones.id.clusters.id.node_pools.id","rationale": "Auto-upgrades automatically ensures that security updates are applied and kept up to date.","references": ["https://www.cisecurity.org/benchmark/kubernetes/","https://cloud.google.com/kubernetes-engine/docs/how-to/node-auto-upgrades","https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on"],"remediation": null,"service": "Kubernetes Engine"},"kubernetesengine-node-container-optimized-os-not-used": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "7.9","version": "1.0.0"},{"name": "CIS GKE Benchmark","reference": "6.5.1","version": "1.0.0"}],"dashboard_name": "Clusters","description": "Lack of Container-Optimized OS Node Images","flagged_items": 0,"id_suffix": "container_optimized_os_not_used","items": [],"level": "warning","path": "kubernetesengine.projects.id.zones.id.clusters.id","rationale": "The Container-Optimized OS image provides better support, security, and stability than previous images.","references": ["https://www.cisecurity.org/benchmark/kubernetes/","https://cloud.google.com/container-optimized-os/docs/concepts/features-and-benefits","https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on"],"remediation": null,"service": "Kubernetes Engine"},"kubernetesengine-private-cluster-disabled": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "7.15","version": "1.0.0"},{"name": "CIS GKE Benchmark","reference": "6.6.4","version": "1.0.0"},{"name": "CIS GKE Benchmark","reference": "6.6.5","version": "1.0.0"}],"dashboard_name": "Clusters","description": "Private Cluster Disabled","flagged_items": 0,"id_suffix": "private_cluster_disabled","items": [],"level": "warning","path": "kubernetesengine.projects.id.zones.id.clusters.id","rationale": "A private cluster is a cluster that makes your master inaccessible from the public internet. In a private cluster, nodes do not have public IP addresses, so your workloads run in an environment that is isolated from the internet. Nodes have addressed only in the private RFC 1918 address space. Nodes and masters communicate with each other privately using VPC peering.","references": ["https://www.cisecurity.org/benchmark/kubernetes/","https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_network_access_to_the_control_plane_and_nodes","https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on"],"remediation": null,"service": "Kubernetes Engine"},"kubernetesengine-scopes-not-limited": {"checked_items": 0,"compliance": [{"name": "CIS Google Cloud Platform Foundations","reference": "7.18","version": "1.0.0"}],"dashboard_name": "Clusters","description": "Lack of Access Scope Limitation","flagged_items": 0,"id_suffix": "scopes_not_limited","items": [],"level": "warning","path": "kubernetesengine.projects.id.zones.id.clusters.id","rationale": "If you are not creating a separate service account for your nodes, you should limit the scopes of the node service account to reduce the possibility of a privilege escalation in an attack. This ensures that your default service account does not have permissions beyond those necessary to run your cluster. While the default scopes are limited, they may include scopes beyond the minimally required scopes needed to run your cluster. If you are accessing private images in Google Container Registry, the minimally required scopes are only logging.write, monitoring, and devstorage.read_only.","references": ["https://cloud.google.com/kubernetes-engine/docs/how-to/access-scopes"],"remediation": null,"service": "Kubernetes Engine"}},"projects": {}},"stackdriverlogging": {"filters": {},"findings": {"stackdriverlogging-no-export-sinks": {"checked_items": 0,"compliance": null,"dashboard_name": "Logging Configurations","description": "Lack of Export Sinks","display_path": "stackdriverlogging.projects.id.sinks","flagged_items": 0,"items": [],"level": "warning","path": "stackdriverlogging.projects.id","rationale": "Export sinks for Stackdriver logging were not found. As a result, logs would be deleted after the configured retention period, and would not be backed up.","references": ["https://cloud.google.com/logging","https://cloud.google.com/logging/docs/export"],"remediation": null,"service": "Stackdriver Logging"}},"metrics_count": 0,"projects": {},"sinks_count": 0},"stackdrivermonitoring": {"alert_policies_count": 0,"filters": {},"findings": {},"projects": {},"uptime_checks_count": 0}}} +{ + "account_id": "project-id", + "all_projects": false, + "environment": "default", + "folder_id": null, + "last_run": { + "ruleset_about": "This ruleset consists of numerous rules that are considered standard by NCC Group. The rules enabled range from violations of well-known security best practices to gaps resulting from less-known security implications of provider-specific mechanisms. Additional rules exist, some of them requiring extra-parameters to be configured, and some of them being applicable to a limited number of users.", + "ruleset_name": "default", + "run_parameters": { + "excluded_regions": null, + "regions": null, + "services": [], + "skipped_services": [] + }, + "summary": { + "cloudsql": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 6 + }, + "cloudstorage": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 4 + }, + "computeengine": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 11 + }, + "iam": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 9 + }, + "kms": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 0 + }, + "kubernetesengine": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 19 + }, + "stackdriverlogging": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 1 + }, + "stackdrivermonitoring": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 0 + } + }, + "time": "2021-01-08 17:16:19+0100", + "version": "5.10.2" + }, + "metadata": { + "compute": { + "computeengine": { + "resources": { + "firewalls": { + "cols": 2, + "count": 0, + "full_path": "services.computeengine.projects.id.firewalls", + "path": "services.computeengine.projects.id.firewalls", + "script": "services.computeengine.projects.firewalls" + }, + "instances": { + "cols": 2, + "count": 0, + "full_path": "services.computeengine.projects.id.zones.id.instances", + "path": "services.computeengine.projects.id.zones.id.instances", + "script": "services.computeengine.projects.zones.instances" + }, + "networks": { + "cols": 2, + "count": 0, + "full_path": "services.computeengine.projects.id.networks", + "path": "services.computeengine.projects.id.networks", + "script": "services.computeengine.projects.networks" + }, + "snapshots": { + "cols": 2, + "count": 0, + "full_path": "services.computeengine.projects.id.snapshots", + "path": "services.computeengine.projects.id.snapshots", + "script": "services.computeengine.projects.snapshots" + }, + "subnetworks": { + "cols": 2, + "count": 0, + "full_path": "services.computeengine.projects.id.regions.id.subnetworks", + "path": "services.computeengine.projects.id.regions.id.subnetworks", + "script": "services.computeengine.projects.regions.subnetworks" + } + } + }, + "kubernetesengine": { + "resources": { + "clusters": { + "cols": 2, + "count": 0, + "full_path": "services.kubernetesengine.projects.id.zones.id.clusters", + "path": "services.kubernetesengine.projects.id.zones.id.clusters", + "script": "services.kubernetesengine.projects.zones.clusters" + } + } + } + }, + "database": { + "cloudsql": { + "resources": { + "instances": { + "cols": 2, + "count": 0, + "full_path": "services.cloudsql.projects.id.instances", + "path": "services.cloudsql.projects.id.instances", + "script": "services.cloudsql.projects.instances" + } + } + } + }, + "management": { + "stackdriverlogging": { + "resources": { + "metrics": { + "cols": 2, + "count": 0, + "full_path": "services.stackdriverlogging.projects.id.metrics", + "path": "services.stackdriverlogging.projects.id.metrics", + "script": "services.stackdriverlogging.projects.metrics" + }, + "sinks": { + "cols": 2, + "count": 0, + "full_path": "services.stackdriverlogging.projects.id.sinks", + "path": "services.stackdriverlogging.projects.id.sinks", + "script": "services.stackdriverlogging.projects.sinks" + } + } + }, + "stackdrivermonitoring": { + "resources": { + "alert_policies": { + "cols": 2, + "count": 0, + "full_path": "services.stackdrivermonitoring.projects.id.alert_policies", + "path": "services.stackdrivermonitoring.projects.id.alert_policies", + "script": "services.stackdrivermonitoring.projects.alert_policies" + }, + "uptime_checks": { + "cols": 2, + "count": 0, + "full_path": "services.stackdrivermonitoring.projects.id.uptime_checks", + "path": "services.stackdrivermonitoring.projects.id.uptime_checks", + "script": "services.stackdrivermonitoring.projects.uptime_checks" + } + } + } + }, + "security": { + "iam": { + "resources": { + "bindings": { + "cols": 2, + "count": 0, + "full_path": "services.iam.projects.id.bindings", + "path": "services.iam.projects.id.bindings", + "script": "services.iam.projects.bindings" + }, + "groups": { + "cols": 2, + "count": 0, + "full_path": "services.iam.projects.id.groups", + "path": "services.iam.projects.id.groups", + "script": "services.iam.projects.groups" + }, + "service_accounts": { + "cols": 2, + "count": 0, + "full_path": "services.iam.projects.id.service_accounts", + "path": "services.iam.projects.id.service_accounts", + "script": "services.iam.projects.service_accounts" + }, + "users": { + "cols": 2, + "count": 0, + "full_path": "services.iam.projects.id.users", + "path": "services.iam.projects.id.users", + "script": "services.iam.projects.users" + } + } + }, + "kms": { + "resources": { + "keyrings": { + "cols": 2, + "count": 0, + "full_path": "services.kms.projects.id.keyrings", + "path": "services.kms.projects.id.keyrings", + "script": "services.kms.projects.keyrings" + } + } + } + }, + "storage": { + "cloudstorage": { + "resources": { + "buckets": { + "cols": 2, + "count": 0, + "full_path": "services.cloudstorage.projects.id.buckets", + "path": "services.cloudstorage.projects.id.buckets", + "script": "services.cloudstorage.projects.buckets" + } + } + } + } + }, + "organization_id": null, + "project_id": "project-id", + "provider_code": "gcp", + "provider_name": "Google Cloud Platform", + "result_format": "json", + "service_list": [ + "cloudsql", + "cloudstorage", + "computeengine", + "iam", + "kms", + "stackdriverlogging", + "stackdrivermonitoring", + "kubernetesengine" + ], + "services": { + "cloudsql": { + "filters": {}, + "findings": { + "cloudsql-allows-root-login-from-any-host": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "6.4", + "version": "1.0.0" + } + ], + "dashboard_name": "Instances", + "description": "Instance Allows Root Login from Any Host", + "flagged_items": 0, + "id_suffix": "root_access_from_any_host", + "items": [], + "level": "warning", + "path": "cloudsql.projects.id.instances.id", + "rationale": "Root access to MySQL Database Instances should be allowed only through trusted IPs.", + "references": [ + "https://forsetisecurity.org/docs/latest/concepts/best-practices.html#cloud-sql", + "https://cloud.google.com/blog/products/gcp/best-practices-for-securing-your-google-cloud-databases" + ], + "remediation": null, + "service": "Cloud SQL" + }, + "cloudsql-instance-backups-disabled": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Instances", + "description": "Instance with Automatic Backups Disabled", + "flagged_items": 0, + "id_suffix": "automatic_backup_enabled", + "items": [], + "level": "warning", + "path": "cloudsql.projects.id.instances.id", + "rationale": "Automatic backups should be configured for Cloud SQL instances in order to ensure backups are created regularly.", + "references": [ + "https://cloud.google.com/sql/docs/mysql/backup-recovery/backups" + ], + "remediation": null, + "service": "Cloud SQL" + }, + "cloudsql-instance-is-open-to-the-world": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "6.2", + "version": "1.0.0" + } + ], + "dashboard_name": "Instances", + "description": "Instance Allowing All Incoming Connections", + "display_path": "cloudsql.projects.id.instances.id", + "flagged_items": 0, + "id_suffix": "open_to_the_world", + "items": [], + "level": "danger", + "path": "cloudsql.projects.id.instances.id.authorized_networks.id", + "rationale": "Database instances should accept connections from trusted IPs and networks only.", + "references": null, + "remediation": null, + "service": "Cloud SQL" + }, + "cloudsql-instance-no-binary-logging": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Instances", + "description": "Instance with Binary Logging Disabled", + "flagged_items": 0, + "id_suffix": "log_enabled", + "items": [], + "level": "warning", + "path": "cloudsql.projects.id.instances.id", + "rationale": "The benefits of enabling binary logs (replication, scalability, auditability, point-in-time data recovery, etc.) can improve the security posture of the Cloud SQL instance.", + "references": [ + "https://cloud.google.com/sql/docs/mysql/instance-settings", + "https://cloud.google.com/sql/docs/mysql/replication/tips" + ], + "remediation": null, + "service": "Cloud SQL" + }, + "cloudsql-instance-ssl-not-required": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "6.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Instances", + "description": "Instance Not Requiring SSL for Incoming Connections", + "flagged_items": 0, + "id_suffix": "ssl_required", + "items": [], + "level": "warning", + "path": "cloudsql.projects.id.instances.id", + "rationale": "All incoming connections to databases should require the use of SSL.", + "references": [ + "https://cloud.google.com/sql/docs/mysql/authorize-ssl" + ], + "remediation": null, + "service": "Cloud SQL" + }, + "cloudsql-instance-with-no-backups": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Instances", + "description": "Instance with No Backups", + "flagged_items": 0, + "id_suffix": "last_backup_timestamp", + "items": [], + "level": "warning", + "path": "cloudsql.projects.id.instances.id", + "rationale": "Weekly or monthly backups should be created of all databases holding sensitive information.", + "references": [ + "https://cloud.google.com/sql/docs/mysql/backup-recovery/backups" + ], + "remediation": null, + "service": "Cloud SQL" + } + }, + "instances_count": 0, + "projects": {} + }, + "cloudstorage": { + "buckets_count": 0, + "filters": {}, + "findings": { + "cloudstorage-bucket-allAuthenticatedUsers": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "5.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Buckets", + "description": "Bucket Accessible by \"allAuthenticatedUsers\"", + "display_path": "cloudstorage.projects.id.buckets.id", + "flagged_items": 0, + "id_suffix": "allAuthenticatedUsers", + "items": [], + "level": "danger", + "path": "cloudstorage.projects.id.buckets.id", + "rationale": "Allowing anonymous and/or public access grants permissions to anyone to access bucket content. Such access might not be desired if you are storing any sensitive data. Hence, ensure that anonymous and/or public access to a bucket is not allowed.", + "references": [ + "https://cloud.google.com/storage/docs/access-control/iam-reference", + "https://cloud.google.com/storage/docs/access-control/making-data-public" + ], + "remediation": "No role should contain \"allUsers\" and/or \"allAuthenticatedUsers\" as a member.", + "service": "Cloud Storage" + }, + "cloudstorage-bucket-allUsers": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "5.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Buckets", + "description": "Bucket Accessible by \"allUsers\"", + "display_path": "cloudstorage.projects.id.buckets.id", + "flagged_items": 0, + "id_suffix": "allUsers", + "items": [], + "level": "danger", + "path": "cloudstorage.projects.id.buckets.id", + "rationale": "Allowing anonymous and/or public access grants permissions to anyone to access bucket content. Such access might not be desired if you are storing any sensitive data. Hence, ensure that anonymous and/or public access to a bucket is not allowed.", + "references": [ + "https://cloud.google.com/storage/docs/access-control/iam-reference", + "https://cloud.google.com/storage/docs/access-control/making-data-public" + ], + "remediation": "No role should contain \"allUsers\" and/or \"allAuthenticatedUsers\" as a member.", + "service": "Cloud Storage" + }, + "cloudstorage-bucket-no-logging": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "5.3", + "version": "1.0.0" + } + ], + "dashboard_name": "Buckets", + "description": "Bucket with Logging Disabled", + "flagged_items": 0, + "id_suffix": "logging_enabled", + "items": [], + "level": "warning", + "path": "cloudstorage.projects.id.buckets.id", + "rationale": "Enable access and storage logs, in order to capture all events which may affect objects within target buckets.", + "references": [ + "https://cloud.google.com/storage/docs/access-logs" + ], + "remediation": null, + "service": "Cloud Storage" + }, + "cloudstorage-bucket-no-versioning": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Buckets", + "description": "Bucket with Versioning Disabled", + "flagged_items": 0, + "id_suffix": "versioning_enabled", + "items": [], + "level": "warning", + "path": "cloudstorage.projects.id.buckets.id", + "rationale": "Enable Object Versioning to protect Cloud Storage data from being overwritten or accidentally deleted.", + "references": [ + "https://cloud.google.com/storage/docs/using-object-versioning" + ], + "remediation": null, + "service": "Cloud Storage" + } + }, + "projects": {} + }, + "computeengine": { + "filters": {}, + "findings": { + "computeengine-firewall-default-rule-in-use": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Firewall Rule", + "description": "Default Firewall Rule in Use", + "flagged_items": 0, + "id_suffix": "name", + "items": [], + "level": "warning", + "path": "computeengine.projects.id.firewalls.id", + "rationale": "Some default firewall rules were in use. This could potentially expose sensitive services or protocols to other networks.", + "references": null, + "remediation": null, + "service": "Compute Engine" + }, + "computeengine-firewall-rule-allows-all-ports": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Firewall Rule Elements", + "description": "Firewall Rule Opens All Ports (0-65535)", + "display_path": "computeengine.projects.id.firewalls.id", + "flagged_items": 0, + "id_suffix": "permissive_ports", + "items": [], + "level": "warning", + "path": "computeengine.projects.id.firewalls.id.allowed_traffic.id.ports.id", + "rationale": "The firewall rule allows access to all ports. This widens the attack surface of the infrastructure and makes it easier for an attacker to reach potentially sensitive services over the network.", + "references": null, + "remediation": null, + "service": "Compute Engine" + }, + "computeengine-firewall-rule-allows-internal-traffic": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Firewall Rule Elements", + "description": "Firewall Rule Allows Internal Traffic", + "display_path": "computeengine.projects.id.firewalls.id", + "flagged_items": 0, + "id_suffix": "permissive_ports", + "items": [], + "level": "warning", + "path": "computeengine.projects.id.firewalls.id.allowed_traffic.id.ports.id", + "rationale": "Firewall rule allows ingress connections for all protocols and ports among instances in the network.", + "references": null, + "remediation": null, + "service": "Compute Engine" + }, + "computeengine-firewall-rule-allows-port-range": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Firewall Rule Elements", + "description": "Firewall Rule Allows Port Range(s)", + "display_path": "computeengine.projects.id.firewalls.id", + "flagged_items": 0, + "id_suffix": "permissive_ports", + "items": [], + "level": "warning", + "path": "computeengine.projects.id.firewalls.id.allowed_traffic.id.ports.id", + "rationale": "It was found that the firewall rule was using port ranges. Sometimes, ranges could include unintended ports that should not be exposed. As a result, when possible, explicit port lists should be used instead.", + "references": null, + "remediation": null, + "service": "Compute Engine" + }, + "computeengine-firewall-rule-allows-public-access": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Firewall Rules", + "description": "Firewall Rule Allows Public Access (0.0.0.0/0)", + "flagged_items": 0, + "id_suffix": "source_ranges", + "items": [], + "level": "warning", + "path": "computeengine.projects.id.firewalls.id", + "rationale": "The firewall rule was found to be exposing potentially open ports to all source addresses. Ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.", + "references": null, + "remediation": null, + "service": "Compute Engine" + }, + "computeengine-firewall-rule-opens-all-ports-to-all": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Firewall Rule Elements", + "description": "Firewall Rule Allows Public Access (0.0.0.0/0) to All Ports (0-65535)", + "display_path": "computeengine.projects.id.firewalls.id", + "flagged_items": 0, + "id_suffix": "permissive_ports", + "items": [], + "level": "warning", + "path": "computeengine.projects.id.firewalls.id.allowed_traffic.id.ports.id", + "rationale": "The firewall rule was found to be exposing all ports to all source addresses. Ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.", + "references": null, + "remediation": null, + "service": "Compute Engine" + }, + "computeengine-firewall-rule-opens-sensitive-port-to-all": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Firewall Rule Elements", + "description": "Firewall INGRESS Rule Allows Public Access (0.0.0.0/0) to a Sensitive Port", + "display_path": "computeengine.projects.id.firewalls.id", + "flagged_items": 0, + "id_suffix": "permissive_ports", + "items": [], + "level": "warning", + "path": "computeengine.projects.id.firewalls.id.allowed_traffic.id.ports.id", + "rationale": "The firewall rule was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.", + "references": null, + "remediation": null, + "service": "Compute Engine" + }, + "computeengine-instance-disk-with-no-snapshot": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Instances", + "description": "Instance Disk without Snapshots", + "display_path": "computeengine.projects.id.zones.id.instances.id", + "flagged_items": 0, + "id_suffix": "latest_snapshot", + "items": [], + "level": "warning", + "path": "computeengine.projects.id.zones.id.instances.id.disks.id", + "rationale": "You should have snapshots of your in-use or available disks taken on a regular basis to enable disaster recovery efforts.", + "references": [ + "https://cloud.google.com/compute/docs/disks/create-snapshots", + "https://cloud.google.com/compute/docs/disks/scheduled-snapshots", + "https://cloud.google.com/compute/docs/disks/snapshot-best-practices" + ], + "remediation": null, + "service": "Compute Engine" + }, + "computeengine-instance-with-deletion-protection-disabled": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Instances", + "description": "Instance without Deletion Protection", + "flagged_items": 0, + "id_suffix": "deletion_protection_enabled", + "items": [], + "level": "warning", + "path": "computeengine.projects.id.zones.id.instances.id", + "rationale": "It is good practice to enable this feature on production instances, to ensure that they may not be deleted by accident.", + "references": [ + "https://cloud.google.com/compute/docs/instances/preventing-accidental-vm-deletion" + ], + "remediation": null, + "service": "Compute Engine" + }, + "computeengine-network-with-no-instances": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Networks", + "description": "Network without Instances", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "computeengine.projects.id.networks.id", + "rationale": "Maintaining unused resources increases risks of misconfigurations and increases the difficulty of audits.", + "references": null, + "remediation": null, + "service": "Compute Engine" + }, + "computeengine-old-disk-snapshot": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Snapshots", + "description": "Old Instance Disk Snapshot", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "computeengine.projects.id.snapshots.id", + "rationale": "Disk snapshots that are over 90 days are likely to be outdated.", + "references": [ + "https://cloud.google.com/compute/docs/disks/create-snapshots", + "https://cloud.google.com/compute/docs/disks/scheduled-snapshots", + "https://cloud.google.com/compute/docs/disks/snapshot-best-practices" + ], + "remediation": null, + "service": "Compute Engine" + } + }, + "firewalls_count": 0, + "instances_count": 0, + "networks_count": 0, + "projects": {}, + "snapshots_count": 0, + "subnetworks_count": 0 + }, + "iam": { + "bindings_count": 0, + "filters": {}, + "findings": { + "iam-gmail-accounts-used": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "1.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Users", + "description": "Gmail Account in Use", + "flagged_items": 0, + "id_suffix": "name", + "items": [], + "level": "warning", + "path": "iam.projects.id.users.id", + "rationale": "Gmail accounts are personally created and controllable accounts. Organizations seldom have any control over them. Thus, it is recommended that you use fully managed corporate Google accounts for increased visibility, auditing, and control over access to Cloud Platform resources.", + "references": null, + "remediation": null, + "service": "IAM" + }, + "iam-lack-of-service-account-key-rotation": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "1.6", + "version": "1.0.0" + } + ], + "dashboard_name": "Service Accounts", + "description": "Lack of Service Account Key Rotation", + "display_path": "iam.projects.id.service_accounts.id", + "flagged_items": 0, + "id_suffix": "valid_after", + "items": [], + "level": "warning", + "path": "iam.projects.id.service_accounts.id.keys.id", + "rationale": "Rotating Service Account keys will reduce the window of opportunity for an access key that is associated with a compromised or terminated account to be used. Service Account keys should be rotated to ensure that data cannot be accessed with an old key which might have been lost, cracked, or stolen. It should be ensured that keys are rotated every 90 days.", + "references": [ + "https://cloud.google.com/iam/docs/creating-managing-service-account-keys" + ], + "remediation": null, + "service": "IAM" + }, + "iam-primitive-role-in-use": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "1.4", + "version": "1.0.0" + } + ], + "dashboard_name": "Bindings", + "description": "Primitive Role in Use", + "flagged_items": 0, + "id_suffix": "name", + "items": [], + "level": "warning", + "path": "iam.projects.id.bindings.id", + "rationale": "Primitive roles grant significant privileges. In most cases, usage of these roles is not recommended and does not follow security best practice.

Note: This rule may flag Google-Managed Service Accounts. Google services rely on these Service Accounts having access to the project, and recommends not removing or changing the Service Account's role (see https://cloud.google.com/iam/docs/service-accounts#google-managed).", + "references": [ + "https://cloud.google.com/iam/docs/understanding-roles", + "https://cloud.google.com/iam/docs/using-iam-securely" + ], + "remediation": null, + "service": "IAM" + }, + "iam-role-assigned-to-user": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Bindings", + "description": "IAM Role Assigned to User", + "flagged_items": 0, + "id_suffix": "users", + "items": [], + "level": "warning", + "path": "iam.projects.id.bindings.id", + "rationale": "Best practices recommends granting roles to a Google Suite group instead of to individual users when possible. It is easier to add members to and remove members from a group instead of updating a Cloud IAM policy to add or remove users.", + "references": [ + "https://cloud.google.com/iam/docs/understanding-roles", + "https://cloud.google.com/iam/docs/using-iam-securely" + ], + "remediation": null, + "service": "IAM" + }, + "iam-sa-has-admin-privileges": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "1.4", + "version": "1.0.0" + } + ], + "dashboard_name": "Bindings", + "description": "Service Account with Admin Privileges", + "flagged_items": 0, + "id_suffix": "service_accounts", + "items": [], + "level": "warning", + "path": "iam.projects.id.bindings.id", + "rationale": "Service accounts represent service-level security of the Resources (application or a VM) which can be determined by the roles assigned to it. Enrolling Service Accounts with administrative privileges grants full access to assigned application or a VM, Service Account Access holder can user.

Note: This rule may flag Google-Managed Service Accounts. Google services rely on these Service Accounts having access to the project, and recommends not removing or changing the Service Account's role", + "references": [ + "https://cloud.google.com/iam/docs/service-accounts#google-managed", + "https://cloud.google.com/iam/docs/understanding-roles", + "https://cloud.google.com/iam/docs/using-iam-securely" + ], + "remediation": null, + "service": "IAM" + }, + "iam-service-account-user-allAuthenticatedUsers": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Service Accounts", + "description": "Service Account with 'allAuthenticatedUsers' Service Account User", + "display_path": "iam.projects.id.service_accounts.id", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "iam.projects.id.service_accounts.id.bindings.id", + "rationale": "Access to the Service Account User role (roles/iam.serviceAccountUser) should be restricted, as members granted this role on a service account can use it to indirectly access all the resources to which the service account has access. ", + "references": [ + "https://cloud.google.com/iam/docs/service-accounts#user-role" + ], + "remediation": null, + "service": "IAM" + }, + "iam-service-account-user-allUsers": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Service Accounts", + "description": "Service Account with 'allUsers' Service Account User", + "display_path": "iam.projects.id.service_accounts.id", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "iam.projects.id.service_accounts.id.bindings.id", + "rationale": "Access to the Service Account User role (roles/iam.serviceAccountUser) should be restricted, as members granted this role on a service account can use it to indirectly access all the resources to which the service account has access. ", + "references": [ + "https://cloud.google.com/iam/docs/service-accounts#user-role" + ], + "remediation": null, + "service": "IAM" + }, + "iam-service-account-with-user-managed-keys": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "1.3", + "version": "1.0.0" + } + ], + "dashboard_name": "Service Accounts", + "description": "User-Managed Service Account Keys", + "display_path": "iam.projects.id.service_accounts.id", + "flagged_items": 0, + "id_suffix": "key_type", + "items": [], + "level": "warning", + "path": "iam.projects.id.service_accounts.id.keys.id", + "rationale": "It is recommended to prevent use of user-managed service account keys, as anyone who has access to the keys will be able to access resources through the service account. Best practice recommends using GCP-managed keys, which are used by Cloud Platform services such as App Engine and Compute Engine. These keys cannot be downloaded. Google will keep the keys and automatically rotate them on an approximately weekly basis.", + "references": [ + "https://cloud.google.com/iam/docs/understanding-service-accounts#managing_service_account_keys" + ], + "remediation": null, + "service": "IAM" + }, + "iam-user-has-sa-user-role": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "1.5", + "version": "1.0.0" + } + ], + "dashboard_name": "Bindings", + "description": "User with \"Service Account User\" Role at the Project Level", + "flagged_items": 0, + "id_suffix": "user_has_sa_user_role", + "items": [], + "level": "warning", + "path": "iam.projects.id.bindings.id", + "rationale": "Granting the iam.serviceAccountUser role to a user for a project gives the user access to all service accounts in the project, including service accounts that may be created in the future. This can result into elevation of privileges by using service accounts and corresponding Compute Engine instances.", + "references": [ + "https://cloud.google.com/iam/docs/service-accounts#google-managed", + "https://cloud.google.com/iam/docs/understanding-roles", + "https://cloud.google.com/iam/docs/using-iam-securely" + ], + "remediation": null, + "service": "IAM" + } + }, + "groups_count": 0, + "projects": {}, + "service_accounts_count": 0, + "users_count": 0 + }, + "kms": { + "filters": {}, + "findings": {}, + "keyrings_count": 0, + "projects": {} + }, + "kubernetesengine": { + "clusters_count": 0, + "filters": {}, + "findings": { + "kubernetesengine-basic-authentication-enabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.10", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.8.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Basic Authentication Enabled", + "flagged_items": 0, + "id_suffix": "basic_authentication_enabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "Basic authentication allows a user to authenticate to the cluster with a username and password and it is stored in plain text without any encryption. Disabling Basic authentication will prevent attacks like brute force. Its recommended to use either client certificate or IAM for authentication.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_authn_methods", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#evaluation_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-certificate-authentication-enabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS GKE Benchmark", + "reference": "6.8.2", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Certificate Authentication Enabled", + "flagged_items": 0, + "id_suffix": "client_certificate_enabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "Unless applications use the client certificate authentication method, it should be disabled.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_authn_methods", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#evaluation_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-cluster-alias-ip-disabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.13", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.6.2", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Alias IP Disabled", + "flagged_items": 0, + "id_suffix": "alias_ip_disabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "With Alias IPs ranges enabled, Kubernetes Engine clusters can allocate IP addresses from a CIDR block known to Google Cloud Platform. This makes your cluster more scalable and allows your cluster to better interact with other GCP products and entities.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_network_access_to_the_control_plane_and_nodes", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-cluster-has-no-labels": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.5", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Clusters Lacking Labels", + "flagged_items": 0, + "id_suffix": "has_no_labels", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "Labels enable users to map their own organizational structures onto system objects in a loosely coupled fashion, without requiring clients to store these mappings. Labels can also be used to apply specific security settings and auto configure objects at creation.", + "references": [ + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#use_namespaces_and_rbac_to_restrict_access_to_cluster_resources" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-cluster-logging-disabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.1", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.7.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Cluster Logging Disabled", + "flagged_items": 0, + "id_suffix": "logging_disabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "You should enable cluster logging and use a logging service so your cluster can export logs about its activities.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://kubernetes.io/docs/tasks/debug-application-cluster/audit/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#stackdriver_logging", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-cluster-master-authorized-networks-disabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.4", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.6.3", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Master Authorized Networks Disabled", + "flagged_items": 0, + "id_suffix": "master_authorized_networks_disabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "Master authorized networks blocks untrusted IP addresses from outside Google Cloud Platform. Addresses from inside GCP can still reach your master through HTTPS provided that they have the necessary Kubernetes credentials.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/authorized-networks", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_network_access_to_the_control_plane_and_nodes", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-cluster-monitoring-disabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.2", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.7.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Cluster Monitoring Disabled", + "flagged_items": 0, + "id_suffix": "monitoring_disabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "You should enable cluster monitoring and use a monitoring service so your cluster can export metrics about its activities.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#stackdriver_logging", + "https://cloud.google.com/monitoring/kubernetes-engine#about-skm", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-cluster-network-policy-disabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.11", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.6.7", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Network Policy Disabled", + "flagged_items": 0, + "id_suffix": "network_policy_disabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "By default, pods are non-isolated; they accept traffic from any source. Pods become isolated by having a NetworkPolicy that selects them. Once there is any NetworkPolicy in a namespace selecting a particular pod, that pod will reject any connections that are not allowed by any NetworkPolicy.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_with_network_policy", + "https://cloud.google.com/kubernetes-engine/docs/concepts/security-overview#network_security", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-cluster-pod-security-policy-config-disabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.14", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.10.3", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Pod Security Policy Disabled", + "flagged_items": 0, + "id_suffix": "pod_security_policy_enabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "A Pod Security Policy is a cluster-level resource that controls security sensitive aspects of the pod specification. The PodSecurityPolicy objects define a set of conditions that a pod must run with in order to be accepted into the system, as well as defaults for the related fields.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/pod-security-policies", + "https://kubernetes.io/docs/concepts/policy/pod-security-policy", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": "Enable the Pod Security Policy. By default, Pod Security Policy is disabled when you create a new cluster.", + "service": "Kubernetes Engine" + }, + "kubernetesengine-cluster-private-google-access-disabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.16", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Private Google Access Disabled", + "flagged_items": 0, + "id_suffix": "private_ip_google_access_disabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "Enabling Private Google Access allows VMs on a subnetwork to use a private IP address to reach Google APIs rather than an external IP address.", + "references": [ + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_network_access_to_the_control_plane_and_nodes" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-dashboard-enabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.6", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.10.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "The GKE Dashboard Enabled", + "flagged_items": 0, + "id_suffix": "dashboard_status", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "You should disable the Kubernetes Web UI (Dashboard) when running on Kubernetes Engine. The Kubernetes Web UI (Dashboard) is backed by a highly privileged Kubernetes Service Account.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#disable_kubernetes_dashboard", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-default-service-account-used": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.17", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.2.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Default Service Account in Use", + "flagged_items": 0, + "id_suffix": "default_service_account_used", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "You should create and use a minimally privileged service account to run your Kubernetes Engine cluster instead of using the Compute Engine default service account.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#use_least_privilege_sa", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-legacy-abac-enabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.3", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.8.4", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Legacy Authorization (ABAC) Enabled", + "flagged_items": 0, + "id_suffix": "legacy_abac_enabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "The legacy authorizer in Kubernetes Engine grants broad, statically defined permissions. To ensure that RBAC limits permissions correctly, you must disable the legacy authorizer. RBAC has significant security advantages, can help you ensure that users only have access to cluster resources within their own namespace and is now stable in Kubernetes.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#leave_abac_disabled_default_for_110", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-legacy-metadata-endpoints-enabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS GKE Benchmark", + "reference": "6.4.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Legacy Metadata Endpoints Enabled", + "display_path": "kubernetesengine.projects.id.zones.id.clusters.id", + "flagged_items": 0, + "id_suffix": "legacy_metadata_endpoints_enabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id.node_pools.id", + "rationale": "Unless your app uses the legacy metadata endpoints, you should disable them.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#protect_node_metadata_default_for_112", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-node-auto-repair-disabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.7", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.5.2", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Nodes Auto-Repair Disabled", + "display_path": "kubernetesengine.projects.id.zones.id.clusters.id", + "flagged_items": 0, + "id_suffix": "auto_repair_disabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id.node_pools.id", + "rationale": "Auto-repair helps you keep the nodes in your cluster in a healthy, running state.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/node-auto-repair", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-node-auto-upgrade-disabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.8", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.5.3", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Nodes Auto-Upgrade Disabled", + "display_path": "kubernetesengine.projects.id.zones.id.clusters.id", + "flagged_items": 0, + "id_suffix": "auto_upgrade_disabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id.node_pools.id", + "rationale": "Auto-upgrades automatically ensures that security updates are applied and kept up to date.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/node-auto-upgrades", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-node-container-optimized-os-not-used": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.9", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.5.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Lack of Container-Optimized OS Node Images", + "flagged_items": 0, + "id_suffix": "container_optimized_os_not_used", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "The Container-Optimized OS image provides better support, security, and stability than previous images.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/container-optimized-os/docs/concepts/features-and-benefits", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-private-cluster-disabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.15", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.6.4", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.6.5", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Private Cluster Disabled", + "flagged_items": 0, + "id_suffix": "private_cluster_disabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "A private cluster is a cluster that makes your master inaccessible from the public internet. In a private cluster, nodes do not have public IP addresses, so your workloads run in an environment that is isolated from the internet. Nodes have addressed only in the private RFC 1918 address space. Nodes and masters communicate with each other privately using VPC peering.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_network_access_to_the_control_plane_and_nodes", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-scopes-not-limited": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.18", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Lack of Access Scope Limitation", + "flagged_items": 0, + "id_suffix": "scopes_not_limited", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "If you are not creating a separate service account for your nodes, you should limit the scopes of the node service account to reduce the possibility of a privilege escalation in an attack. This ensures that your default service account does not have permissions beyond those necessary to run your cluster. While the default scopes are limited, they may include scopes beyond the minimally required scopes needed to run your cluster. If you are accessing private images in Google Container Registry, the minimally required scopes are only logging.write, monitoring, and devstorage.read_only.", + "references": [ + "https://cloud.google.com/kubernetes-engine/docs/how-to/access-scopes" + ], + "remediation": null, + "service": "Kubernetes Engine" + } + }, + "projects": {} + }, + "stackdriverlogging": { + "filters": {}, + "findings": { + "stackdriverlogging-no-export-sinks": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Logging Configurations", + "description": "Lack of Export Sinks", + "display_path": "stackdriverlogging.projects.id.sinks", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "stackdriverlogging.projects.id", + "rationale": "Export sinks for Stackdriver logging were not found. As a result, logs would be deleted after the configured retention period, and would not be backed up.", + "references": [ + "https://cloud.google.com/logging", + "https://cloud.google.com/logging/docs/export" + ], + "remediation": null, + "service": "Stackdriver Logging" + } + }, + "metrics_count": 0, + "projects": {}, + "sinks_count": 0 + }, + "stackdrivermonitoring": { + "alert_policies_count": 0, + "filters": {}, + "findings": {}, + "projects": {}, + "uptime_checks_count": 0 + } + } +} \ No newline at end of file diff --git a/unittests/scans/scout_suite/two_findings.js b/unittests/scans/scout_suite/two_findings.js index b637c9afa5..75fb1211a8 100644 --- a/unittests/scans/scout_suite/two_findings.js +++ b/unittests/scans/scout_suite/two_findings.js @@ -1,2 +1,1599 @@ scoutsuite_results = -{ "account_id": "gcp-project-id", "all_projects": false, "environment": "default", "folder_id": null, "last_run": { "ruleset_about": "This ruleset consists of numerous rules that are considered standard by NCC Group. The rules enabled range from violations of well-known security best practices to gaps resulting from less-known security implications of provider-specific mechanisms. Additional rules exist, some of them requiring extra-parameters to be configured, and some of them being applicable to a limited number of users.", "ruleset_name": "default", "run_parameters": { "excluded_regions": null, "regions": null, "services": [], "skipped_services": [] }, "summary": { "cloudsql": { "checked_items": 0, "flagged_items": 0, "max_level": "warning", "resources_count": 0, "rules_count": 6 }, "cloudstorage": { "checked_items": 8, "flagged_items": 4, "max_level": "warning", "resources_count": 2, "rules_count": 4 }, "computeengine": { "checked_items": 0, "flagged_items": 0, "max_level": "warning", "resources_count": 0, "rules_count": 11 }, "iam": { "checked_items": 0, "flagged_items": 0, "max_level": "warning", "resources_count": 0, "rules_count": 9 }, "kms": { "checked_items": 0, "flagged_items": 0, "max_level": "warning", "resources_count": 0, "rules_count": 0 }, "kubernetesengine": { "checked_items": 0, "flagged_items": 0, "max_level": "warning", "resources_count": 0, "rules_count": 19 }, "stackdriverlogging": { "checked_items": 1, "flagged_items": 0, "max_level": "warning", "resources_count": 2, "rules_count": 1 }, "stackdrivermonitoring": { "checked_items": 0, "flagged_items": 0, "max_level": "warning", "resources_count": 0, "rules_count": 0 } }, "time": "2021-01-08 17:28:00+0100", "version": "5.10.2" }, "metadata": { "compute": { "computeengine": { "resources": { "firewalls": { "cols": 2, "count": 0, "full_path": "services.computeengine.projects.id.firewalls", "path": "services.computeengine.projects.id.firewalls", "script": "services.computeengine.projects.firewalls" }, "instances": { "cols": 2, "count": 0, "full_path": "services.computeengine.projects.id.zones.id.instances", "path": "services.computeengine.projects.id.zones.id.instances", "script": "services.computeengine.projects.zones.instances" }, "networks": { "cols": 2, "count": 0, "full_path": "services.computeengine.projects.id.networks", "path": "services.computeengine.projects.id.networks", "script": "services.computeengine.projects.networks" }, "snapshots": { "cols": 2, "count": 0, "full_path": "services.computeengine.projects.id.snapshots", "path": "services.computeengine.projects.id.snapshots", "script": "services.computeengine.projects.snapshots" }, "subnetworks": { "cols": 2, "count": 0, "full_path": "services.computeengine.projects.id.regions.id.subnetworks", "path": "services.computeengine.projects.id.regions.id.subnetworks", "script": "services.computeengine.projects.regions.subnetworks" } } }, "kubernetesengine": { "resources": { "clusters": { "cols": 2, "count": 0, "full_path": "services.kubernetesengine.projects.id.zones.id.clusters", "path": "services.kubernetesengine.projects.id.zones.id.clusters", "script": "services.kubernetesengine.projects.zones.clusters" } } } }, "database": { "cloudsql": { "resources": { "instances": { "cols": 2, "count": 0, "full_path": "services.cloudsql.projects.id.instances", "path": "services.cloudsql.projects.id.instances", "script": "services.cloudsql.projects.instances" } } } }, "management": { "stackdriverlogging": { "resources": { "metrics": { "cols": 2, "count": 0, "full_path": "services.stackdriverlogging.projects.id.metrics", "path": "services.stackdriverlogging.projects.id.metrics", "script": "services.stackdriverlogging.projects.metrics" }, "sinks": { "cols": 2, "count": 2, "full_path": "services.stackdriverlogging.projects.id.sinks", "path": "services.stackdriverlogging.projects.id.sinks", "script": "services.stackdriverlogging.projects.sinks" } } }, "stackdrivermonitoring": { "resources": { "alert_policies": { "cols": 2, "count": 0, "full_path": "services.stackdrivermonitoring.projects.id.alert_policies", "path": "services.stackdrivermonitoring.projects.id.alert_policies", "script": "services.stackdrivermonitoring.projects.alert_policies" }, "uptime_checks": { "cols": 2, "count": 0, "full_path": "services.stackdrivermonitoring.projects.id.uptime_checks", "path": "services.stackdrivermonitoring.projects.id.uptime_checks", "script": "services.stackdrivermonitoring.projects.uptime_checks" } } } }, "security": { "iam": { "resources": { "bindings": { "cols": 2, "count": 0, "full_path": "services.iam.projects.id.bindings", "path": "services.iam.projects.id.bindings", "script": "services.iam.projects.bindings" }, "groups": { "cols": 2, "count": 0, "full_path": "services.iam.projects.id.groups", "path": "services.iam.projects.id.groups", "script": "services.iam.projects.groups" }, "service_accounts": { "cols": 2, "count": 0, "full_path": "services.iam.projects.id.service_accounts", "path": "services.iam.projects.id.service_accounts", "script": "services.iam.projects.service_accounts" }, "users": { "cols": 2, "count": 0, "full_path": "services.iam.projects.id.users", "path": "services.iam.projects.id.users", "script": "services.iam.projects.users" } } }, "kms": { "resources": { "keyrings": { "cols": 2, "count": 0, "full_path": "services.kms.projects.id.keyrings", "path": "services.kms.projects.id.keyrings", "script": "services.kms.projects.keyrings" } } } }, "storage": { "cloudstorage": { "resources": { "buckets": { "cols": 2, "count": 2, "full_path": "services.cloudstorage.projects.id.buckets", "path": "services.cloudstorage.projects.id.buckets", "script": "services.cloudstorage.projects.buckets" } } } } }, "organization_id": null, "project_id": "gcp-project-id", "provider_code": "gcp", "provider_name": "Google Cloud Platform", "result_format": "json", "service_list": [ "cloudsql", "cloudstorage", "computeengine", "iam", "kms", "stackdriverlogging", "stackdrivermonitoring", "kubernetesengine" ], "services": { "cloudsql": { "filters": {}, "findings": { "cloudsql-allows-root-login-from-any-host": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "6.4", "version": "1.0.0" } ], "dashboard_name": "Instances", "description": "Instance Allows Root Login from Any Host", "flagged_items": 0, "id_suffix": "root_access_from_any_host", "items": [], "level": "warning", "path": "cloudsql.projects.id.instances.id", "rationale": "Root access to MySQL Database Instances should be allowed only through trusted IPs.", "references": [ "https://forsetisecurity.org/docs/latest/concepts/best-practices.html#cloud-sql", "https://cloud.google.com/blog/products/gcp/best-practices-for-securing-your-google-cloud-databases" ], "remediation": null, "service": "Cloud SQL" }, "cloudsql-instance-backups-disabled": { "checked_items": 0, "compliance": null, "dashboard_name": "Instances", "description": "Instance with Automatic Backups Disabled", "flagged_items": 0, "id_suffix": "automatic_backup_enabled", "items": [], "level": "warning", "path": "cloudsql.projects.id.instances.id", "rationale": "Automatic backups should be configured for Cloud SQL instances in order to ensure backups are created regularly.", "references": [ "https://cloud.google.com/sql/docs/mysql/backup-recovery/backups" ], "remediation": null, "service": "Cloud SQL" }, "cloudsql-instance-is-open-to-the-world": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "6.2", "version": "1.0.0" } ], "dashboard_name": "Instances", "description": "Instance Allowing All Incoming Connections", "display_path": "cloudsql.projects.id.instances.id", "flagged_items": 0, "id_suffix": "open_to_the_world", "items": [], "level": "danger", "path": "cloudsql.projects.id.instances.id.authorized_networks.id", "rationale": "Database instances should accept connections from trusted IPs and networks only.", "references": null, "remediation": null, "service": "Cloud SQL" }, "cloudsql-instance-no-binary-logging": { "checked_items": 0, "compliance": null, "dashboard_name": "Instances", "description": "Instance with Binary Logging Disabled", "flagged_items": 0, "id_suffix": "log_enabled", "items": [], "level": "warning", "path": "cloudsql.projects.id.instances.id", "rationale": "The benefits of enabling binary logs (replication, scalability, auditability, point-in-time data recovery, etc.) can improve the security posture of the Cloud SQL instance.", "references": [ "https://cloud.google.com/sql/docs/mysql/instance-settings", "https://cloud.google.com/sql/docs/mysql/replication/tips" ], "remediation": null, "service": "Cloud SQL" }, "cloudsql-instance-ssl-not-required": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "6.1", "version": "1.0.0" } ], "dashboard_name": "Instances", "description": "Instance Not Requiring SSL for Incoming Connections", "flagged_items": 0, "id_suffix": "ssl_required", "items": [], "level": "warning", "path": "cloudsql.projects.id.instances.id", "rationale": "All incoming connections to databases should require the use of SSL.", "references": [ "https://cloud.google.com/sql/docs/mysql/authorize-ssl" ], "remediation": null, "service": "Cloud SQL" }, "cloudsql-instance-with-no-backups": { "checked_items": 0, "compliance": null, "dashboard_name": "Instances", "description": "Instance with No Backups", "flagged_items": 0, "id_suffix": "last_backup_timestamp", "items": [], "level": "warning", "path": "cloudsql.projects.id.instances.id", "rationale": "Weekly or monthly backups should be created of all databases holding sensitive information.", "references": [ "https://cloud.google.com/sql/docs/mysql/backup-recovery/backups" ], "remediation": null, "service": "Cloud SQL" } }, "instances_count": 0, "projects": { "gcp-project-id": { "instances": {}, "instances_count": 0 } } }, "cloudstorage": { "buckets_count": 2, "filters": {}, "findings": { "cloudstorage-bucket-allAuthenticatedUsers": { "checked_items": 2, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "5.1", "version": "1.0.0" } ], "dashboard_name": "Buckets", "description": "Bucket Accessible by \"allAuthenticatedUsers\"", "display_path": "cloudstorage.projects.id.buckets.id", "flagged_items": 0, "id_suffix": "allAuthenticatedUsers", "items": [], "level": "danger", "path": "cloudstorage.projects.id.buckets.id", "rationale": "Allowing anonymous and/or public access grants permissions to anyone to access bucket content. Such access might not be desired if you are storing any sensitive data. Hence, ensure that anonymous and/or public access to a bucket is not allowed.", "references": [ "https://cloud.google.com/storage/docs/access-control/iam-reference", "https://cloud.google.com/storage/docs/access-control/making-data-public" ], "remediation": "No role should contain \"allUsers\" and/or \"allAuthenticatedUsers\" as a member.", "service": "Cloud Storage" }, "cloudstorage-bucket-allUsers": { "checked_items": 2, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "5.1", "version": "1.0.0" } ], "dashboard_name": "Buckets", "description": "Bucket Accessible by \"allUsers\"", "display_path": "cloudstorage.projects.id.buckets.id", "flagged_items": 0, "id_suffix": "allUsers", "items": [], "level": "danger", "path": "cloudstorage.projects.id.buckets.id", "rationale": "Allowing anonymous and/or public access grants permissions to anyone to access bucket content. Such access might not be desired if you are storing any sensitive data. Hence, ensure that anonymous and/or public access to a bucket is not allowed.", "references": [ "https://cloud.google.com/storage/docs/access-control/iam-reference", "https://cloud.google.com/storage/docs/access-control/making-data-public" ], "remediation": "No role should contain \"allUsers\" and/or \"allAuthenticatedUsers\" as a member.", "service": "Cloud Storage" }, "cloudstorage-bucket-no-logging": { "checked_items": 2, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "5.3", "version": "1.0.0" } ], "dashboard_name": "Buckets", "description": "Bucket with Logging Disabled", "flagged_items": 2, "id_suffix": "logging_enabled", "items": [ "cloudstorage.projects.gcp-project-id.buckets.52fc025e81845686d3c9fe5a5dc4f5e7ae740064.logging_enabled", "cloudstorage.projects.gcp-project-id.buckets.be0c682b7f6d9568fed2ec924eea5ebcfe083f3b.logging_enabled" ], "level": "warning", "path": "cloudstorage.projects.id.buckets.id", "rationale": "Enable access and storage logs, in order to capture all events which may affect objects within target buckets.", "references": [ "https://cloud.google.com/storage/docs/access-logs" ], "remediation": null, "service": "Cloud Storage" }, "cloudstorage-bucket-no-versioning": { "checked_items": 2, "compliance": null, "dashboard_name": "Buckets", "description": "Bucket with Versioning Disabled", "flagged_items": 2, "id_suffix": "versioning_enabled", "items": [ "cloudstorage.projects.gcp-project-id.buckets.52fc025e81845686d3c9fe5a5dc4f5e7ae740064.versioning_enabled", "cloudstorage.projects.gcp-project-id.buckets.be0c682b7f6d9568fed2ec924eea5ebcfe083f3b.versioning_enabled" ], "level": "warning", "path": "cloudstorage.projects.id.buckets.id", "rationale": "Enable Object Versioning to protect Cloud Storage data from being overwritten or accidentally deleted.", "references": [ "https://cloud.google.com/storage/docs/using-object-versioning" ], "remediation": null, "service": "Cloud Storage" } }, "projects": { "gcp-project-id": { "buckets": { "52fc025e81845686d3c9fe5a5dc4f5e7ae740064": { "acls": [ { "entity": "project-owners-1111111111", "role": "OWNER" }, { "entity": "project-editors-1111111111", "role": "OWNER" }, { "entity": "project-viewers-1111111111", "role": "READER" } ], "creation_date": "2019-01-24 09:35:13.157000+00:00", "default_object_acl": [ { "entity": "project-owners-1111111111", "role": "OWNER" }, { "entity": "project-editors-1111111111", "role": "OWNER" }, { "entity": "project-viewers-1111111111", "role": "READER" } ], "id": "52fc025e81845686d3c9fe5a5dc4f5e7ae740064", "location": "EU", "logging_enabled": false, "member_bindings": {}, "name": "gcp-project-id.appspot.com", "project_id": "gcp-project-id", "project_number": 1111111111, "storage_class": "standard", "uniform_bucket_level_access": false, "versioning_enabled": false }, "be0c682b7f6d9568fed2ec924eea5ebcfe083f3b": { "acls": [ { "entity": "project-owners-1111111111", "role": "OWNER" }, { "entity": "project-editors-1111111111", "role": "OWNER" }, { "entity": "project-viewers-1111111111", "role": "READER" } ], "creation_date": "2019-01-24 09:35:13.151000+00:00", "default_object_acl": [ { "entity": "project-owners-1111111111", "role": "OWNER" }, { "entity": "project-editors-1111111111", "role": "OWNER" }, { "entity": "project-viewers-1111111111", "role": "READER" } ], "id": "be0c682b7f6d9568fed2ec924eea5ebcfe083f3b", "location": "EU", "logging_enabled": false, "member_bindings": {}, "name": "staging.gcp-project-id.appspot.com", "project_id": "gcp-project-id", "project_number": 1111111111, "storage_class": "standard", "uniform_bucket_level_access": false, "versioning_enabled": false } }, "buckets_count": 2 } } }, "computeengine": { "filters": {}, "findings": { "computeengine-firewall-default-rule-in-use": { "checked_items": 0, "compliance": null, "dashboard_name": "Firewall Rule", "description": "Default Firewall Rule in Use", "flagged_items": 0, "id_suffix": "name", "items": [], "level": "warning", "path": "computeengine.projects.id.firewalls.id", "rationale": "Some default firewall rules were in use. This could potentially expose sensitive services or protocols to other networks.", "references": null, "remediation": null, "service": "Compute Engine" }, "computeengine-firewall-rule-allows-all-ports": { "checked_items": 0, "compliance": null, "dashboard_name": "Firewall Rule Elements", "description": "Firewall Rule Opens All Ports (0-65535)", "display_path": "computeengine.projects.id.firewalls.id", "flagged_items": 0, "id_suffix": "permissive_ports", "items": [], "level": "warning", "path": "computeengine.projects.id.firewalls.id.allowed_traffic.id.ports.id", "rationale": "The firewall rule allows access to all ports. This widens the attack surface of the infrastructure and makes it easier for an attacker to reach potentially sensitive services over the network.", "references": null, "remediation": null, "service": "Compute Engine" }, "computeengine-firewall-rule-allows-internal-traffic": { "checked_items": 0, "compliance": null, "dashboard_name": "Firewall Rule Elements", "description": "Firewall Rule Allows Internal Traffic", "display_path": "computeengine.projects.id.firewalls.id", "flagged_items": 0, "id_suffix": "permissive_ports", "items": [], "level": "warning", "path": "computeengine.projects.id.firewalls.id.allowed_traffic.id.ports.id", "rationale": "Firewall rule allows ingress connections for all protocols and ports among instances in the network.", "references": null, "remediation": null, "service": "Compute Engine" }, "computeengine-firewall-rule-allows-port-range": { "checked_items": 0, "compliance": null, "dashboard_name": "Firewall Rule Elements", "description": "Firewall Rule Allows Port Range(s)", "display_path": "computeengine.projects.id.firewalls.id", "flagged_items": 0, "id_suffix": "permissive_ports", "items": [], "level": "warning", "path": "computeengine.projects.id.firewalls.id.allowed_traffic.id.ports.id", "rationale": "It was found that the firewall rule was using port ranges. Sometimes, ranges could include unintended ports that should not be exposed. As a result, when possible, explicit port lists should be used instead.", "references": null, "remediation": null, "service": "Compute Engine" }, "computeengine-firewall-rule-allows-public-access": { "checked_items": 0, "compliance": null, "dashboard_name": "Firewall Rules", "description": "Firewall Rule Allows Public Access (0.0.0.0/0)", "flagged_items": 0, "id_suffix": "source_ranges", "items": [], "level": "warning", "path": "computeengine.projects.id.firewalls.id", "rationale": "The firewall rule was found to be exposing potentially open ports to all source addresses. Ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.", "references": null, "remediation": null, "service": "Compute Engine" }, "computeengine-firewall-rule-opens-all-ports-to-all": { "checked_items": 0, "compliance": null, "dashboard_name": "Firewall Rule Elements", "description": "Firewall Rule Allows Public Access (0.0.0.0/0) to All Ports (0-65535)", "display_path": "computeengine.projects.id.firewalls.id", "flagged_items": 0, "id_suffix": "permissive_ports", "items": [], "level": "warning", "path": "computeengine.projects.id.firewalls.id.allowed_traffic.id.ports.id", "rationale": "The firewall rule was found to be exposing all ports to all source addresses. Ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.", "references": null, "remediation": null, "service": "Compute Engine" }, "computeengine-firewall-rule-opens-sensitive-port-to-all": { "checked_items": 0, "compliance": null, "dashboard_name": "Firewall Rule Elements", "description": "Firewall INGRESS Rule Allows Public Access (0.0.0.0/0) to a Sensitive Port", "display_path": "computeengine.projects.id.firewalls.id", "flagged_items": 0, "id_suffix": "permissive_ports", "items": [], "level": "warning", "path": "computeengine.projects.id.firewalls.id.allowed_traffic.id.ports.id", "rationale": "The firewall rule was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.", "references": null, "remediation": null, "service": "Compute Engine" }, "computeengine-instance-disk-with-no-snapshot": { "checked_items": 0, "compliance": null, "dashboard_name": "Instances", "description": "Instance Disk without Snapshots", "display_path": "computeengine.projects.id.zones.id.instances.id", "flagged_items": 0, "id_suffix": "latest_snapshot", "items": [], "level": "warning", "path": "computeengine.projects.id.zones.id.instances.id.disks.id", "rationale": "You should have snapshots of your in-use or available disks taken on a regular basis to enable disaster recovery efforts.", "references": [ "https://cloud.google.com/compute/docs/disks/create-snapshots", "https://cloud.google.com/compute/docs/disks/scheduled-snapshots", "https://cloud.google.com/compute/docs/disks/snapshot-best-practices" ], "remediation": null, "service": "Compute Engine" }, "computeengine-instance-with-deletion-protection-disabled": { "checked_items": 0, "compliance": null, "dashboard_name": "Instances", "description": "Instance without Deletion Protection", "flagged_items": 0, "id_suffix": "deletion_protection_enabled", "items": [], "level": "warning", "path": "computeengine.projects.id.zones.id.instances.id", "rationale": "It is good practice to enable this feature on production instances, to ensure that they may not be deleted by accident.", "references": [ "https://cloud.google.com/compute/docs/instances/preventing-accidental-vm-deletion" ], "remediation": null, "service": "Compute Engine" }, "computeengine-network-with-no-instances": { "checked_items": 0, "compliance": null, "dashboard_name": "Networks", "description": "Network without Instances", "flagged_items": 0, "items": [], "level": "warning", "path": "computeengine.projects.id.networks.id", "rationale": "Maintaining unused resources increases risks of misconfigurations and increases the difficulty of audits.", "references": null, "remediation": null, "service": "Compute Engine" }, "computeengine-old-disk-snapshot": { "checked_items": 0, "compliance": null, "dashboard_name": "Snapshots", "description": "Old Instance Disk Snapshot", "flagged_items": 0, "items": [], "level": "warning", "path": "computeengine.projects.id.snapshots.id", "rationale": "Disk snapshots that are over 90 days are likely to be outdated.", "references": [ "https://cloud.google.com/compute/docs/disks/create-snapshots", "https://cloud.google.com/compute/docs/disks/scheduled-snapshots", "https://cloud.google.com/compute/docs/disks/snapshot-best-practices" ], "remediation": null, "service": "Compute Engine" } }, "firewalls_count": 0, "instances_count": 0, "networks_count": 0, "projects": {}, "snapshots_count": 0, "subnetworks_count": 0 }, "iam": { "bindings_count": 0, "filters": {}, "findings": { "iam-gmail-accounts-used": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "1.1", "version": "1.0.0" } ], "dashboard_name": "Users", "description": "Gmail Account in Use", "flagged_items": 0, "id_suffix": "name", "items": [], "level": "warning", "path": "iam.projects.id.users.id", "rationale": "Gmail accounts are personally created and controllable accounts. Organizations seldom have any control over them. Thus, it is recommended that you use fully managed corporate Google accounts for increased visibility, auditing, and control over access to Cloud Platform resources.", "references": null, "remediation": null, "service": "IAM" }, "iam-lack-of-service-account-key-rotation": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "1.6", "version": "1.0.0" } ], "dashboard_name": "Service Accounts", "description": "Lack of Service Account Key Rotation", "display_path": "iam.projects.id.service_accounts.id", "flagged_items": 0, "id_suffix": "valid_after", "items": [], "level": "warning", "path": "iam.projects.id.service_accounts.id.keys.id", "rationale": "Rotating Service Account keys will reduce the window of opportunity for an access key that is associated with a compromised or terminated account to be used. Service Account keys should be rotated to ensure that data cannot be accessed with an old key which might have been lost, cracked, or stolen. It should be ensured that keys are rotated every 90 days.", "references": [ "https://cloud.google.com/iam/docs/creating-managing-service-account-keys" ], "remediation": null, "service": "IAM" }, "iam-primitive-role-in-use": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "1.4", "version": "1.0.0" } ], "dashboard_name": "Bindings", "description": "Primitive Role in Use", "flagged_items": 0, "id_suffix": "name", "items": [], "level": "warning", "path": "iam.projects.id.bindings.id", "rationale": "Primitive roles grant significant privileges. In most cases, usage of these roles is not recommended and does not follow security best practice.

Note: This rule may flag Google-Managed Service Accounts. Google services rely on these Service Accounts having access to the project, and recommends not removing or changing the Service Account's role (see https://cloud.google.com/iam/docs/service-accounts#google-managed).", "references": [ "https://cloud.google.com/iam/docs/understanding-roles", "https://cloud.google.com/iam/docs/using-iam-securely" ], "remediation": null, "service": "IAM" }, "iam-role-assigned-to-user": { "checked_items": 0, "compliance": null, "dashboard_name": "Bindings", "description": "IAM Role Assigned to User", "flagged_items": 0, "id_suffix": "users", "items": [], "level": "warning", "path": "iam.projects.id.bindings.id", "rationale": "Best practices recommends granting roles to a Google Suite group instead of to individual users when possible. It is easier to add members to and remove members from a group instead of updating a Cloud IAM policy to add or remove users.", "references": [ "https://cloud.google.com/iam/docs/understanding-roles", "https://cloud.google.com/iam/docs/using-iam-securely" ], "remediation": null, "service": "IAM" }, "iam-sa-has-admin-privileges": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "1.4", "version": "1.0.0" } ], "dashboard_name": "Bindings", "description": "Service Account with Admin Privileges", "flagged_items": 0, "id_suffix": "service_accounts", "items": [], "level": "warning", "path": "iam.projects.id.bindings.id", "rationale": "Service accounts represent service-level security of the Resources (application or a VM) which can be determined by the roles assigned to it. Enrolling Service Accounts with administrative privileges grants full access to assigned application or a VM, Service Account Access holder can user.

Note: This rule may flag Google-Managed Service Accounts. Google services rely on these Service Accounts having access to the project, and recommends not removing or changing the Service Account's role", "references": [ "https://cloud.google.com/iam/docs/service-accounts#google-managed", "https://cloud.google.com/iam/docs/understanding-roles", "https://cloud.google.com/iam/docs/using-iam-securely" ], "remediation": null, "service": "IAM" }, "iam-service-account-user-allAuthenticatedUsers": { "checked_items": 0, "compliance": null, "dashboard_name": "Service Accounts", "description": "Service Account with 'allAuthenticatedUsers' Service Account User", "display_path": "iam.projects.id.service_accounts.id", "flagged_items": 0, "items": [], "level": "warning", "path": "iam.projects.id.service_accounts.id.bindings.id", "rationale": "Access to the Service Account User role (roles/iam.serviceAccountUser) should be restricted, as members granted this role on a service account can use it to indirectly access all the resources to which the service account has access. ", "references": [ "https://cloud.google.com/iam/docs/service-accounts#user-role" ], "remediation": null, "service": "IAM" }, "iam-service-account-user-allUsers": { "checked_items": 0, "compliance": null, "dashboard_name": "Service Accounts", "description": "Service Account with 'allUsers' Service Account User", "display_path": "iam.projects.id.service_accounts.id", "flagged_items": 0, "items": [], "level": "warning", "path": "iam.projects.id.service_accounts.id.bindings.id", "rationale": "Access to the Service Account User role (roles/iam.serviceAccountUser) should be restricted, as members granted this role on a service account can use it to indirectly access all the resources to which the service account has access. ", "references": [ "https://cloud.google.com/iam/docs/service-accounts#user-role" ], "remediation": null, "service": "IAM" }, "iam-service-account-with-user-managed-keys": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "1.3", "version": "1.0.0" } ], "dashboard_name": "Service Accounts", "description": "User-Managed Service Account Keys", "display_path": "iam.projects.id.service_accounts.id", "flagged_items": 0, "id_suffix": "key_type", "items": [], "level": "warning", "path": "iam.projects.id.service_accounts.id.keys.id", "rationale": "It is recommended to prevent use of user-managed service account keys, as anyone who has access to the keys will be able to access resources through the service account. Best practice recommends using GCP-managed keys, which are used by Cloud Platform services such as App Engine and Compute Engine. These keys cannot be downloaded. Google will keep the keys and automatically rotate them on an approximately weekly basis.", "references": [ "https://cloud.google.com/iam/docs/understanding-service-accounts#managing_service_account_keys" ], "remediation": null, "service": "IAM" }, "iam-user-has-sa-user-role": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "1.5", "version": "1.0.0" } ], "dashboard_name": "Bindings", "description": "User with \"Service Account User\" Role at the Project Level", "flagged_items": 0, "id_suffix": "user_has_sa_user_role", "items": [], "level": "warning", "path": "iam.projects.id.bindings.id", "rationale": "Granting the iam.serviceAccountUser role to a user for a project gives the user access to all service accounts in the project, including service accounts that may be created in the future. This can result into elevation of privileges by using service accounts and corresponding Compute Engine instances.", "references": [ "https://cloud.google.com/iam/docs/service-accounts#google-managed", "https://cloud.google.com/iam/docs/understanding-roles", "https://cloud.google.com/iam/docs/using-iam-securely" ], "remediation": null, "service": "IAM" } }, "groups_count": 0, "projects": {}, "service_accounts_count": 0, "users_count": 0 }, "kms": { "filters": {}, "findings": {}, "keyrings_count": 0, "projects": {} }, "kubernetesengine": { "clusters_count": 0, "filters": {}, "findings": { "kubernetesengine-basic-authentication-enabled": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "7.10", "version": "1.0.0" }, { "name": "CIS GKE Benchmark", "reference": "6.8.1", "version": "1.0.0" } ], "dashboard_name": "Clusters", "description": "Basic Authentication Enabled", "flagged_items": 0, "id_suffix": "basic_authentication_enabled", "items": [], "level": "warning", "path": "kubernetesengine.projects.id.zones.id.clusters.id", "rationale": "Basic authentication allows a user to authenticate to the cluster with a username and password and it is stored in plain text without any encryption. Disabling Basic authentication will prevent attacks like brute force. Its recommended to use either client certificate or IAM for authentication.", "references": [ "https://www.cisecurity.org/benchmark/kubernetes/", "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_authn_methods", "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#evaluation_on" ], "remediation": null, "service": "Kubernetes Engine" }, "kubernetesengine-certificate-authentication-enabled": { "checked_items": 0, "compliance": [ { "name": "CIS GKE Benchmark", "reference": "6.8.2", "version": "1.0.0" } ], "dashboard_name": "Clusters", "description": "Certificate Authentication Enabled", "flagged_items": 0, "id_suffix": "client_certificate_enabled", "items": [], "level": "warning", "path": "kubernetesengine.projects.id.zones.id.clusters.id", "rationale": "Unless applications use the client certificate authentication method, it should be disabled.", "references": [ "https://www.cisecurity.org/benchmark/kubernetes/", "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_authn_methods", "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#evaluation_on" ], "remediation": null, "service": "Kubernetes Engine" }, "kubernetesengine-cluster-alias-ip-disabled": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "7.13", "version": "1.0.0" }, { "name": "CIS GKE Benchmark", "reference": "6.6.2", "version": "1.0.0" } ], "dashboard_name": "Clusters", "description": "Alias IP Disabled", "flagged_items": 0, "id_suffix": "alias_ip_disabled", "items": [], "level": "warning", "path": "kubernetesengine.projects.id.zones.id.clusters.id", "rationale": "With Alias IPs ranges enabled, Kubernetes Engine clusters can allocate IP addresses from a CIDR block known to Google Cloud Platform. This makes your cluster more scalable and allows your cluster to better interact with other GCP products and entities.", "references": [ "https://www.cisecurity.org/benchmark/kubernetes/", "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_network_access_to_the_control_plane_and_nodes", "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" ], "remediation": null, "service": "Kubernetes Engine" }, "kubernetesengine-cluster-has-no-labels": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "7.5", "version": "1.0.0" } ], "dashboard_name": "Clusters", "description": "Clusters Lacking Labels", "flagged_items": 0, "id_suffix": "has_no_labels", "items": [], "level": "warning", "path": "kubernetesengine.projects.id.zones.id.clusters.id", "rationale": "Labels enable users to map their own organizational structures onto system objects in a loosely coupled fashion, without requiring clients to store these mappings. Labels can also be used to apply specific security settings and auto configure objects at creation.", "references": [ "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#use_namespaces_and_rbac_to_restrict_access_to_cluster_resources" ], "remediation": null, "service": "Kubernetes Engine" }, "kubernetesengine-cluster-logging-disabled": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "7.1", "version": "1.0.0" }, { "name": "CIS GKE Benchmark", "reference": "6.7.1", "version": "1.0.0" } ], "dashboard_name": "Clusters", "description": "Cluster Logging Disabled", "flagged_items": 0, "id_suffix": "logging_disabled", "items": [], "level": "warning", "path": "kubernetesengine.projects.id.zones.id.clusters.id", "rationale": "You should enable cluster logging and use a logging service so your cluster can export logs about its activities.", "references": [ "https://www.cisecurity.org/benchmark/kubernetes/", "https://kubernetes.io/docs/tasks/debug-application-cluster/audit/", "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#stackdriver_logging", "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" ], "remediation": null, "service": "Kubernetes Engine" }, "kubernetesengine-cluster-master-authorized-networks-disabled": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "7.4", "version": "1.0.0" }, { "name": "CIS GKE Benchmark", "reference": "6.6.3", "version": "1.0.0" } ], "dashboard_name": "Clusters", "description": "Master Authorized Networks Disabled", "flagged_items": 0, "id_suffix": "master_authorized_networks_disabled", "items": [], "level": "warning", "path": "kubernetesengine.projects.id.zones.id.clusters.id", "rationale": "Master authorized networks blocks untrusted IP addresses from outside Google Cloud Platform. Addresses from inside GCP can still reach your master through HTTPS provided that they have the necessary Kubernetes credentials.", "references": [ "https://www.cisecurity.org/benchmark/kubernetes/", "https://cloud.google.com/kubernetes-engine/docs/how-to/authorized-networks", "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_network_access_to_the_control_plane_and_nodes", "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" ], "remediation": null, "service": "Kubernetes Engine" }, "kubernetesengine-cluster-monitoring-disabled": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "7.2", "version": "1.0.0" }, { "name": "CIS GKE Benchmark", "reference": "6.7.1", "version": "1.0.0" } ], "dashboard_name": "Clusters", "description": "Cluster Monitoring Disabled", "flagged_items": 0, "id_suffix": "monitoring_disabled", "items": [], "level": "warning", "path": "kubernetesengine.projects.id.zones.id.clusters.id", "rationale": "You should enable cluster monitoring and use a monitoring service so your cluster can export metrics about its activities.", "references": [ "https://www.cisecurity.org/benchmark/kubernetes/", "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#stackdriver_logging", "https://cloud.google.com/monitoring/kubernetes-engine#about-skm", "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" ], "remediation": null, "service": "Kubernetes Engine" }, "kubernetesengine-cluster-network-policy-disabled": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "7.11", "version": "1.0.0" }, { "name": "CIS GKE Benchmark", "reference": "6.6.7", "version": "1.0.0" } ], "dashboard_name": "Clusters", "description": "Network Policy Disabled", "flagged_items": 0, "id_suffix": "network_policy_disabled", "items": [], "level": "warning", "path": "kubernetesengine.projects.id.zones.id.clusters.id", "rationale": "By default, pods are non-isolated; they accept traffic from any source. Pods become isolated by having a NetworkPolicy that selects them. Once there is any NetworkPolicy in a namespace selecting a particular pod, that pod will reject any connections that are not allowed by any NetworkPolicy.", "references": [ "https://www.cisecurity.org/benchmark/kubernetes/", "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_with_network_policy", "https://cloud.google.com/kubernetes-engine/docs/concepts/security-overview#network_security", "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" ], "remediation": null, "service": "Kubernetes Engine" }, "kubernetesengine-cluster-pod-security-policy-config-disabled": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "7.14", "version": "1.0.0" }, { "name": "CIS GKE Benchmark", "reference": "6.10.3", "version": "1.0.0" } ], "dashboard_name": "Clusters", "description": "Pod Security Policy Disabled", "flagged_items": 0, "id_suffix": "pod_security_policy_enabled", "items": [], "level": "warning", "path": "kubernetesengine.projects.id.zones.id.clusters.id", "rationale": "A Pod Security Policy is a cluster-level resource that controls security sensitive aspects of the pod specification. The PodSecurityPolicy objects define a set of conditions that a pod must run with in order to be accepted into the system, as well as defaults for the related fields.", "references": [ "https://www.cisecurity.org/benchmark/kubernetes/", "https://cloud.google.com/kubernetes-engine/docs/how-to/pod-security-policies", "https://kubernetes.io/docs/concepts/policy/pod-security-policy", "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" ], "remediation": "Enable the Pod Security Policy. By default, Pod Security Policy is disabled when you create a new cluster.", "service": "Kubernetes Engine" }, "kubernetesengine-cluster-private-google-access-disabled": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "7.16", "version": "1.0.0" } ], "dashboard_name": "Clusters", "description": "Private Google Access Disabled", "flagged_items": 0, "id_suffix": "private_ip_google_access_disabled", "items": [], "level": "warning", "path": "kubernetesengine.projects.id.zones.id.clusters.id", "rationale": "Enabling Private Google Access allows VMs on a subnetwork to use a private IP address to reach Google APIs rather than an external IP address.", "references": [ "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_network_access_to_the_control_plane_and_nodes" ], "remediation": null, "service": "Kubernetes Engine" }, "kubernetesengine-dashboard-enabled": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "7.6", "version": "1.0.0" }, { "name": "CIS GKE Benchmark", "reference": "6.10.1", "version": "1.0.0" } ], "dashboard_name": "Clusters", "description": "The GKE Dashboard Enabled", "flagged_items": 0, "id_suffix": "dashboard_status", "items": [], "level": "warning", "path": "kubernetesengine.projects.id.zones.id.clusters.id", "rationale": "You should disable the Kubernetes Web UI (Dashboard) when running on Kubernetes Engine. The Kubernetes Web UI (Dashboard) is backed by a highly privileged Kubernetes Service Account.", "references": [ "https://www.cisecurity.org/benchmark/kubernetes/", "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#disable_kubernetes_dashboard", "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" ], "remediation": null, "service": "Kubernetes Engine" }, "kubernetesengine-default-service-account-used": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "7.17", "version": "1.0.0" }, { "name": "CIS GKE Benchmark", "reference": "6.2.1", "version": "1.0.0" } ], "dashboard_name": "Clusters", "description": "Default Service Account in Use", "flagged_items": 0, "id_suffix": "default_service_account_used", "items": [], "level": "warning", "path": "kubernetesengine.projects.id.zones.id.clusters.id", "rationale": "You should create and use a minimally privileged service account to run your Kubernetes Engine cluster instead of using the Compute Engine default service account.", "references": [ "https://www.cisecurity.org/benchmark/kubernetes/", "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#use_least_privilege_sa", "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" ], "remediation": null, "service": "Kubernetes Engine" }, "kubernetesengine-legacy-abac-enabled": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "7.3", "version": "1.0.0" }, { "name": "CIS GKE Benchmark", "reference": "6.8.4", "version": "1.0.0" } ], "dashboard_name": "Clusters", "description": "Legacy Authorization (ABAC) Enabled", "flagged_items": 0, "id_suffix": "legacy_abac_enabled", "items": [], "level": "warning", "path": "kubernetesengine.projects.id.zones.id.clusters.id", "rationale": "The legacy authorizer in Kubernetes Engine grants broad, statically defined permissions. To ensure that RBAC limits permissions correctly, you must disable the legacy authorizer. RBAC has significant security advantages, can help you ensure that users only have access to cluster resources within their own namespace and is now stable in Kubernetes.", "references": [ "https://www.cisecurity.org/benchmark/kubernetes/", "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#leave_abac_disabled_default_for_110", "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" ], "remediation": null, "service": "Kubernetes Engine" }, "kubernetesengine-legacy-metadata-endpoints-enabled": { "checked_items": 0, "compliance": [ { "name": "CIS GKE Benchmark", "reference": "6.4.1", "version": "1.0.0" } ], "dashboard_name": "Clusters", "description": "Legacy Metadata Endpoints Enabled", "display_path": "kubernetesengine.projects.id.zones.id.clusters.id", "flagged_items": 0, "id_suffix": "legacy_metadata_endpoints_enabled", "items": [], "level": "warning", "path": "kubernetesengine.projects.id.zones.id.clusters.id.node_pools.id", "rationale": "Unless your app uses the legacy metadata endpoints, you should disable them.", "references": [ "https://www.cisecurity.org/benchmark/kubernetes/", "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#protect_node_metadata_default_for_112", "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" ], "remediation": null, "service": "Kubernetes Engine" }, "kubernetesengine-node-auto-repair-disabled": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "7.7", "version": "1.0.0" }, { "name": "CIS GKE Benchmark", "reference": "6.5.2", "version": "1.0.0" } ], "dashboard_name": "Clusters", "description": "Nodes Auto-Repair Disabled", "display_path": "kubernetesengine.projects.id.zones.id.clusters.id", "flagged_items": 0, "id_suffix": "auto_repair_disabled", "items": [], "level": "warning", "path": "kubernetesengine.projects.id.zones.id.clusters.id.node_pools.id", "rationale": "Auto-repair helps you keep the nodes in your cluster in a healthy, running state.", "references": [ "https://www.cisecurity.org/benchmark/kubernetes/", "https://cloud.google.com/kubernetes-engine/docs/how-to/node-auto-repair", "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" ], "remediation": null, "service": "Kubernetes Engine" }, "kubernetesengine-node-auto-upgrade-disabled": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "7.8", "version": "1.0.0" }, { "name": "CIS GKE Benchmark", "reference": "6.5.3", "version": "1.0.0" } ], "dashboard_name": "Clusters", "description": "Nodes Auto-Upgrade Disabled", "display_path": "kubernetesengine.projects.id.zones.id.clusters.id", "flagged_items": 0, "id_suffix": "auto_upgrade_disabled", "items": [], "level": "warning", "path": "kubernetesengine.projects.id.zones.id.clusters.id.node_pools.id", "rationale": "Auto-upgrades automatically ensures that security updates are applied and kept up to date.", "references": [ "https://www.cisecurity.org/benchmark/kubernetes/", "https://cloud.google.com/kubernetes-engine/docs/how-to/node-auto-upgrades", "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" ], "remediation": null, "service": "Kubernetes Engine" }, "kubernetesengine-node-container-optimized-os-not-used": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "7.9", "version": "1.0.0" }, { "name": "CIS GKE Benchmark", "reference": "6.5.1", "version": "1.0.0" } ], "dashboard_name": "Clusters", "description": "Lack of Container-Optimized OS Node Images", "flagged_items": 0, "id_suffix": "container_optimized_os_not_used", "items": [], "level": "warning", "path": "kubernetesengine.projects.id.zones.id.clusters.id", "rationale": "The Container-Optimized OS image provides better support, security, and stability than previous images.", "references": [ "https://www.cisecurity.org/benchmark/kubernetes/", "https://cloud.google.com/container-optimized-os/docs/concepts/features-and-benefits", "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" ], "remediation": null, "service": "Kubernetes Engine" }, "kubernetesengine-private-cluster-disabled": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "7.15", "version": "1.0.0" }, { "name": "CIS GKE Benchmark", "reference": "6.6.4", "version": "1.0.0" }, { "name": "CIS GKE Benchmark", "reference": "6.6.5", "version": "1.0.0" } ], "dashboard_name": "Clusters", "description": "Private Cluster Disabled", "flagged_items": 0, "id_suffix": "private_cluster_disabled", "items": [], "level": "warning", "path": "kubernetesengine.projects.id.zones.id.clusters.id", "rationale": "A private cluster is a cluster that makes your master inaccessible from the public internet. In a private cluster, nodes do not have public IP addresses, so your workloads run in an environment that is isolated from the internet. Nodes have addressed only in the private RFC 1918 address space. Nodes and masters communicate with each other privately using VPC peering.", "references": [ "https://www.cisecurity.org/benchmark/kubernetes/", "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_network_access_to_the_control_plane_and_nodes", "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" ], "remediation": null, "service": "Kubernetes Engine" }, "kubernetesengine-scopes-not-limited": { "checked_items": 0, "compliance": [ { "name": "CIS Google Cloud Platform Foundations", "reference": "7.18", "version": "1.0.0" } ], "dashboard_name": "Clusters", "description": "Lack of Access Scope Limitation", "flagged_items": 0, "id_suffix": "scopes_not_limited", "items": [], "level": "warning", "path": "kubernetesengine.projects.id.zones.id.clusters.id", "rationale": "If you are not creating a separate service account for your nodes, you should limit the scopes of the node service account to reduce the possibility of a privilege escalation in an attack. This ensures that your default service account does not have permissions beyond those necessary to run your cluster. While the default scopes are limited, they may include scopes beyond the minimally required scopes needed to run your cluster. If you are accessing private images in Google Container Registry, the minimally required scopes are only logging.write, monitoring, and devstorage.read_only.", "references": [ "https://cloud.google.com/kubernetes-engine/docs/how-to/access-scopes" ], "remediation": null, "service": "Kubernetes Engine" } }, "projects": {} }, "stackdriverlogging": { "filters": {}, "findings": { "stackdriverlogging-no-export-sinks": { "checked_items": 1, "compliance": null, "dashboard_name": "Logging Configurations", "description": "Lack of Export Sinks", "display_path": "stackdriverlogging.projects.id.sinks", "flagged_items": 0, "items": [], "level": "warning", "path": "stackdriverlogging.projects.id", "rationale": "Export sinks for Stackdriver logging were not found. As a result, logs would be deleted after the configured retention period, and would not be backed up.", "references": [ "https://cloud.google.com/logging", "https://cloud.google.com/logging/docs/export" ], "remediation": null, "service": "Stackdriver Logging" } }, "metrics_count": 0, "projects": { "gcp-project-id": { "metrics": {}, "metrics_count": 0, "sinks": { "_Default": { "destination": "logging.googleapis.com/projects/gcp-project-id/locations/global/buckets/_Default", "filter": "NOT LOG_ID(\"cloudaudit.googleapis.com/activity\") AND NOT LOG_ID(\"externalaudit.googleapis.com/activity\") AND NOT LOG_ID(\"cloudaudit.googleapis.com/system_event\") AND NOT LOG_ID(\"externalaudit.googleapis.com/system_event\") AND NOT LOG_ID(\"cloudaudit.googleapis.com/access_transparency\") AND NOT LOG_ID(\"externalaudit.googleapis.com/access_transparency\")", "name": "_Default" }, "_Required": { "destination": "logging.googleapis.com/projects/gcp-project-id/locations/global/buckets/_Required", "filter": "LOG_ID(\"cloudaudit.googleapis.com/activity\") OR LOG_ID(\"externalaudit.googleapis.com/activity\") OR LOG_ID(\"cloudaudit.googleapis.com/system_event\") OR LOG_ID(\"externalaudit.googleapis.com/system_event\") OR LOG_ID(\"cloudaudit.googleapis.com/access_transparency\") OR LOG_ID(\"externalaudit.googleapis.com/access_transparency\")", "name": "_Required" } }, "sinks_count": 2 } }, "sinks_count": 2 }, "stackdrivermonitoring": { "alert_policies_count": 0, "filters": {}, "findings": {}, "projects": { "gcp-project-id": { "alert_policies": {}, "alert_policies_count": 0, "uptime_checks": {}, "uptime_checks_count": 0 } }, "uptime_checks_count": 0 } }} +{ + "account_id": "gcp-project-id", + "all_projects": false, + "environment": "default", + "folder_id": null, + "last_run": { + "ruleset_about": "This ruleset consists of numerous rules that are considered standard by NCC Group. The rules enabled range from violations of well-known security best practices to gaps resulting from less-known security implications of provider-specific mechanisms. Additional rules exist, some of them requiring extra-parameters to be configured, and some of them being applicable to a limited number of users.", + "ruleset_name": "default", + "run_parameters": { + "excluded_regions": null, + "regions": null, + "services": [], + "skipped_services": [] + }, + "summary": { + "cloudsql": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 6 + }, + "cloudstorage": { + "checked_items": 8, + "flagged_items": 4, + "max_level": "warning", + "resources_count": 2, + "rules_count": 4 + }, + "computeengine": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 11 + }, + "iam": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 9 + }, + "kms": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 0 + }, + "kubernetesengine": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 19 + }, + "stackdriverlogging": { + "checked_items": 1, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 2, + "rules_count": 1 + }, + "stackdrivermonitoring": { + "checked_items": 0, + "flagged_items": 0, + "max_level": "warning", + "resources_count": 0, + "rules_count": 0 + } + }, + "time": "2021-01-08 17:28:00+0100", + "version": "5.10.2" + }, + "metadata": { + "compute": { + "computeengine": { + "resources": { + "firewalls": { + "cols": 2, + "count": 0, + "full_path": "services.computeengine.projects.id.firewalls", + "path": "services.computeengine.projects.id.firewalls", + "script": "services.computeengine.projects.firewalls" + }, + "instances": { + "cols": 2, + "count": 0, + "full_path": "services.computeengine.projects.id.zones.id.instances", + "path": "services.computeengine.projects.id.zones.id.instances", + "script": "services.computeengine.projects.zones.instances" + }, + "networks": { + "cols": 2, + "count": 0, + "full_path": "services.computeengine.projects.id.networks", + "path": "services.computeengine.projects.id.networks", + "script": "services.computeengine.projects.networks" + }, + "snapshots": { + "cols": 2, + "count": 0, + "full_path": "services.computeengine.projects.id.snapshots", + "path": "services.computeengine.projects.id.snapshots", + "script": "services.computeengine.projects.snapshots" + }, + "subnetworks": { + "cols": 2, + "count": 0, + "full_path": "services.computeengine.projects.id.regions.id.subnetworks", + "path": "services.computeengine.projects.id.regions.id.subnetworks", + "script": "services.computeengine.projects.regions.subnetworks" + } + } + }, + "kubernetesengine": { + "resources": { + "clusters": { + "cols": 2, + "count": 0, + "full_path": "services.kubernetesengine.projects.id.zones.id.clusters", + "path": "services.kubernetesengine.projects.id.zones.id.clusters", + "script": "services.kubernetesengine.projects.zones.clusters" + } + } + } + }, + "database": { + "cloudsql": { + "resources": { + "instances": { + "cols": 2, + "count": 0, + "full_path": "services.cloudsql.projects.id.instances", + "path": "services.cloudsql.projects.id.instances", + "script": "services.cloudsql.projects.instances" + } + } + } + }, + "management": { + "stackdriverlogging": { + "resources": { + "metrics": { + "cols": 2, + "count": 0, + "full_path": "services.stackdriverlogging.projects.id.metrics", + "path": "services.stackdriverlogging.projects.id.metrics", + "script": "services.stackdriverlogging.projects.metrics" + }, + "sinks": { + "cols": 2, + "count": 2, + "full_path": "services.stackdriverlogging.projects.id.sinks", + "path": "services.stackdriverlogging.projects.id.sinks", + "script": "services.stackdriverlogging.projects.sinks" + } + } + }, + "stackdrivermonitoring": { + "resources": { + "alert_policies": { + "cols": 2, + "count": 0, + "full_path": "services.stackdrivermonitoring.projects.id.alert_policies", + "path": "services.stackdrivermonitoring.projects.id.alert_policies", + "script": "services.stackdrivermonitoring.projects.alert_policies" + }, + "uptime_checks": { + "cols": 2, + "count": 0, + "full_path": "services.stackdrivermonitoring.projects.id.uptime_checks", + "path": "services.stackdrivermonitoring.projects.id.uptime_checks", + "script": "services.stackdrivermonitoring.projects.uptime_checks" + } + } + } + }, + "security": { + "iam": { + "resources": { + "bindings": { + "cols": 2, + "count": 0, + "full_path": "services.iam.projects.id.bindings", + "path": "services.iam.projects.id.bindings", + "script": "services.iam.projects.bindings" + }, + "groups": { + "cols": 2, + "count": 0, + "full_path": "services.iam.projects.id.groups", + "path": "services.iam.projects.id.groups", + "script": "services.iam.projects.groups" + }, + "service_accounts": { + "cols": 2, + "count": 0, + "full_path": "services.iam.projects.id.service_accounts", + "path": "services.iam.projects.id.service_accounts", + "script": "services.iam.projects.service_accounts" + }, + "users": { + "cols": 2, + "count": 0, + "full_path": "services.iam.projects.id.users", + "path": "services.iam.projects.id.users", + "script": "services.iam.projects.users" + } + } + }, + "kms": { + "resources": { + "keyrings": { + "cols": 2, + "count": 0, + "full_path": "services.kms.projects.id.keyrings", + "path": "services.kms.projects.id.keyrings", + "script": "services.kms.projects.keyrings" + } + } + } + }, + "storage": { + "cloudstorage": { + "resources": { + "buckets": { + "cols": 2, + "count": 2, + "full_path": "services.cloudstorage.projects.id.buckets", + "path": "services.cloudstorage.projects.id.buckets", + "script": "services.cloudstorage.projects.buckets" + } + } + } + } + }, + "organization_id": null, + "project_id": "gcp-project-id", + "provider_code": "gcp", + "provider_name": "Google Cloud Platform", + "result_format": "json", + "service_list": [ + "cloudsql", + "cloudstorage", + "computeengine", + "iam", + "kms", + "stackdriverlogging", + "stackdrivermonitoring", + "kubernetesengine" + ], + "services": { + "cloudsql": { + "filters": {}, + "findings": { + "cloudsql-allows-root-login-from-any-host": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "6.4", + "version": "1.0.0" + } + ], + "dashboard_name": "Instances", + "description": "Instance Allows Root Login from Any Host", + "flagged_items": 0, + "id_suffix": "root_access_from_any_host", + "items": [], + "level": "warning", + "path": "cloudsql.projects.id.instances.id", + "rationale": "Root access to MySQL Database Instances should be allowed only through trusted IPs.", + "references": [ + "https://forsetisecurity.org/docs/latest/concepts/best-practices.html#cloud-sql", + "https://cloud.google.com/blog/products/gcp/best-practices-for-securing-your-google-cloud-databases" + ], + "remediation": null, + "service": "Cloud SQL" + }, + "cloudsql-instance-backups-disabled": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Instances", + "description": "Instance with Automatic Backups Disabled", + "flagged_items": 0, + "id_suffix": "automatic_backup_enabled", + "items": [], + "level": "warning", + "path": "cloudsql.projects.id.instances.id", + "rationale": "Automatic backups should be configured for Cloud SQL instances in order to ensure backups are created regularly.", + "references": [ + "https://cloud.google.com/sql/docs/mysql/backup-recovery/backups" + ], + "remediation": null, + "service": "Cloud SQL" + }, + "cloudsql-instance-is-open-to-the-world": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "6.2", + "version": "1.0.0" + } + ], + "dashboard_name": "Instances", + "description": "Instance Allowing All Incoming Connections", + "display_path": "cloudsql.projects.id.instances.id", + "flagged_items": 0, + "id_suffix": "open_to_the_world", + "items": [], + "level": "danger", + "path": "cloudsql.projects.id.instances.id.authorized_networks.id", + "rationale": "Database instances should accept connections from trusted IPs and networks only.", + "references": null, + "remediation": null, + "service": "Cloud SQL" + }, + "cloudsql-instance-no-binary-logging": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Instances", + "description": "Instance with Binary Logging Disabled", + "flagged_items": 0, + "id_suffix": "log_enabled", + "items": [], + "level": "warning", + "path": "cloudsql.projects.id.instances.id", + "rationale": "The benefits of enabling binary logs (replication, scalability, auditability, point-in-time data recovery, etc.) can improve the security posture of the Cloud SQL instance.", + "references": [ + "https://cloud.google.com/sql/docs/mysql/instance-settings", + "https://cloud.google.com/sql/docs/mysql/replication/tips" + ], + "remediation": null, + "service": "Cloud SQL" + }, + "cloudsql-instance-ssl-not-required": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "6.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Instances", + "description": "Instance Not Requiring SSL for Incoming Connections", + "flagged_items": 0, + "id_suffix": "ssl_required", + "items": [], + "level": "warning", + "path": "cloudsql.projects.id.instances.id", + "rationale": "All incoming connections to databases should require the use of SSL.", + "references": [ + "https://cloud.google.com/sql/docs/mysql/authorize-ssl" + ], + "remediation": null, + "service": "Cloud SQL" + }, + "cloudsql-instance-with-no-backups": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Instances", + "description": "Instance with No Backups", + "flagged_items": 0, + "id_suffix": "last_backup_timestamp", + "items": [], + "level": "warning", + "path": "cloudsql.projects.id.instances.id", + "rationale": "Weekly or monthly backups should be created of all databases holding sensitive information.", + "references": [ + "https://cloud.google.com/sql/docs/mysql/backup-recovery/backups" + ], + "remediation": null, + "service": "Cloud SQL" + } + }, + "instances_count": 0, + "projects": { + "gcp-project-id": { + "instances": {}, + "instances_count": 0 + } + } + }, + "cloudstorage": { + "buckets_count": 2, + "filters": {}, + "findings": { + "cloudstorage-bucket-allAuthenticatedUsers": { + "checked_items": 2, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "5.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Buckets", + "description": "Bucket Accessible by \"allAuthenticatedUsers\"", + "display_path": "cloudstorage.projects.id.buckets.id", + "flagged_items": 0, + "id_suffix": "allAuthenticatedUsers", + "items": [], + "level": "danger", + "path": "cloudstorage.projects.id.buckets.id", + "rationale": "Allowing anonymous and/or public access grants permissions to anyone to access bucket content. Such access might not be desired if you are storing any sensitive data. Hence, ensure that anonymous and/or public access to a bucket is not allowed.", + "references": [ + "https://cloud.google.com/storage/docs/access-control/iam-reference", + "https://cloud.google.com/storage/docs/access-control/making-data-public" + ], + "remediation": "No role should contain \"allUsers\" and/or \"allAuthenticatedUsers\" as a member.", + "service": "Cloud Storage" + }, + "cloudstorage-bucket-allUsers": { + "checked_items": 2, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "5.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Buckets", + "description": "Bucket Accessible by \"allUsers\"", + "display_path": "cloudstorage.projects.id.buckets.id", + "flagged_items": 0, + "id_suffix": "allUsers", + "items": [], + "level": "danger", + "path": "cloudstorage.projects.id.buckets.id", + "rationale": "Allowing anonymous and/or public access grants permissions to anyone to access bucket content. Such access might not be desired if you are storing any sensitive data. Hence, ensure that anonymous and/or public access to a bucket is not allowed.", + "references": [ + "https://cloud.google.com/storage/docs/access-control/iam-reference", + "https://cloud.google.com/storage/docs/access-control/making-data-public" + ], + "remediation": "No role should contain \"allUsers\" and/or \"allAuthenticatedUsers\" as a member.", + "service": "Cloud Storage" + }, + "cloudstorage-bucket-no-logging": { + "checked_items": 2, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "5.3", + "version": "1.0.0" + } + ], + "dashboard_name": "Buckets", + "description": "Bucket with Logging Disabled", + "flagged_items": 2, + "id_suffix": "logging_enabled", + "items": [ + "cloudstorage.projects.gcp-project-id.buckets.52fc025e81845686d3c9fe5a5dc4f5e7ae740064.logging_enabled", + "cloudstorage.projects.gcp-project-id.buckets.be0c682b7f6d9568fed2ec924eea5ebcfe083f3b.logging_enabled" + ], + "level": "warning", + "path": "cloudstorage.projects.id.buckets.id", + "rationale": "Enable access and storage logs, in order to capture all events which may affect objects within target buckets.", + "references": [ + "https://cloud.google.com/storage/docs/access-logs" + ], + "remediation": null, + "service": "Cloud Storage" + }, + "cloudstorage-bucket-no-versioning": { + "checked_items": 2, + "compliance": null, + "dashboard_name": "Buckets", + "description": "Bucket with Versioning Disabled", + "flagged_items": 2, + "id_suffix": "versioning_enabled", + "items": [ + "cloudstorage.projects.gcp-project-id.buckets.52fc025e81845686d3c9fe5a5dc4f5e7ae740064.versioning_enabled", + "cloudstorage.projects.gcp-project-id.buckets.be0c682b7f6d9568fed2ec924eea5ebcfe083f3b.versioning_enabled" + ], + "level": "warning", + "path": "cloudstorage.projects.id.buckets.id", + "rationale": "Enable Object Versioning to protect Cloud Storage data from being overwritten or accidentally deleted.", + "references": [ + "https://cloud.google.com/storage/docs/using-object-versioning" + ], + "remediation": null, + "service": "Cloud Storage" + } + }, + "projects": { + "gcp-project-id": { + "buckets": { + "52fc025e81845686d3c9fe5a5dc4f5e7ae740064": { + "acls": [ + { + "entity": "project-owners-1111111111", + "role": "OWNER" + }, + { + "entity": "project-editors-1111111111", + "role": "OWNER" + }, + { + "entity": "project-viewers-1111111111", + "role": "READER" + } + ], + "creation_date": "2019-01-24 09:35:13.157000+00:00", + "default_object_acl": [ + { + "entity": "project-owners-1111111111", + "role": "OWNER" + }, + { + "entity": "project-editors-1111111111", + "role": "OWNER" + }, + { + "entity": "project-viewers-1111111111", + "role": "READER" + } + ], + "id": "52fc025e81845686d3c9fe5a5dc4f5e7ae740064", + "location": "EU", + "logging_enabled": false, + "member_bindings": {}, + "name": "gcp-project-id.appspot.com", + "project_id": "gcp-project-id", + "project_number": 1111111111, + "storage_class": "standard", + "uniform_bucket_level_access": false, + "versioning_enabled": false + }, + "be0c682b7f6d9568fed2ec924eea5ebcfe083f3b": { + "acls": [ + { + "entity": "project-owners-1111111111", + "role": "OWNER" + }, + { + "entity": "project-editors-1111111111", + "role": "OWNER" + }, + { + "entity": "project-viewers-1111111111", + "role": "READER" + } + ], + "creation_date": "2019-01-24 09:35:13.151000+00:00", + "default_object_acl": [ + { + "entity": "project-owners-1111111111", + "role": "OWNER" + }, + { + "entity": "project-editors-1111111111", + "role": "OWNER" + }, + { + "entity": "project-viewers-1111111111", + "role": "READER" + } + ], + "id": "be0c682b7f6d9568fed2ec924eea5ebcfe083f3b", + "location": "EU", + "logging_enabled": false, + "member_bindings": {}, + "name": "staging.gcp-project-id.appspot.com", + "project_id": "gcp-project-id", + "project_number": 1111111111, + "storage_class": "standard", + "uniform_bucket_level_access": false, + "versioning_enabled": false + } + }, + "buckets_count": 2 + } + } + }, + "computeengine": { + "filters": {}, + "findings": { + "computeengine-firewall-default-rule-in-use": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Firewall Rule", + "description": "Default Firewall Rule in Use", + "flagged_items": 0, + "id_suffix": "name", + "items": [], + "level": "warning", + "path": "computeengine.projects.id.firewalls.id", + "rationale": "Some default firewall rules were in use. This could potentially expose sensitive services or protocols to other networks.", + "references": null, + "remediation": null, + "service": "Compute Engine" + }, + "computeengine-firewall-rule-allows-all-ports": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Firewall Rule Elements", + "description": "Firewall Rule Opens All Ports (0-65535)", + "display_path": "computeengine.projects.id.firewalls.id", + "flagged_items": 0, + "id_suffix": "permissive_ports", + "items": [], + "level": "warning", + "path": "computeengine.projects.id.firewalls.id.allowed_traffic.id.ports.id", + "rationale": "The firewall rule allows access to all ports. This widens the attack surface of the infrastructure and makes it easier for an attacker to reach potentially sensitive services over the network.", + "references": null, + "remediation": null, + "service": "Compute Engine" + }, + "computeengine-firewall-rule-allows-internal-traffic": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Firewall Rule Elements", + "description": "Firewall Rule Allows Internal Traffic", + "display_path": "computeengine.projects.id.firewalls.id", + "flagged_items": 0, + "id_suffix": "permissive_ports", + "items": [], + "level": "warning", + "path": "computeengine.projects.id.firewalls.id.allowed_traffic.id.ports.id", + "rationale": "Firewall rule allows ingress connections for all protocols and ports among instances in the network.", + "references": null, + "remediation": null, + "service": "Compute Engine" + }, + "computeengine-firewall-rule-allows-port-range": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Firewall Rule Elements", + "description": "Firewall Rule Allows Port Range(s)", + "display_path": "computeengine.projects.id.firewalls.id", + "flagged_items": 0, + "id_suffix": "permissive_ports", + "items": [], + "level": "warning", + "path": "computeengine.projects.id.firewalls.id.allowed_traffic.id.ports.id", + "rationale": "It was found that the firewall rule was using port ranges. Sometimes, ranges could include unintended ports that should not be exposed. As a result, when possible, explicit port lists should be used instead.", + "references": null, + "remediation": null, + "service": "Compute Engine" + }, + "computeengine-firewall-rule-allows-public-access": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Firewall Rules", + "description": "Firewall Rule Allows Public Access (0.0.0.0/0)", + "flagged_items": 0, + "id_suffix": "source_ranges", + "items": [], + "level": "warning", + "path": "computeengine.projects.id.firewalls.id", + "rationale": "The firewall rule was found to be exposing potentially open ports to all source addresses. Ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.", + "references": null, + "remediation": null, + "service": "Compute Engine" + }, + "computeengine-firewall-rule-opens-all-ports-to-all": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Firewall Rule Elements", + "description": "Firewall Rule Allows Public Access (0.0.0.0/0) to All Ports (0-65535)", + "display_path": "computeengine.projects.id.firewalls.id", + "flagged_items": 0, + "id_suffix": "permissive_ports", + "items": [], + "level": "warning", + "path": "computeengine.projects.id.firewalls.id.allowed_traffic.id.ports.id", + "rationale": "The firewall rule was found to be exposing all ports to all source addresses. Ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.", + "references": null, + "remediation": null, + "service": "Compute Engine" + }, + "computeengine-firewall-rule-opens-sensitive-port-to-all": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Firewall Rule Elements", + "description": "Firewall INGRESS Rule Allows Public Access (0.0.0.0/0) to a Sensitive Port", + "display_path": "computeengine.projects.id.firewalls.id", + "flagged_items": 0, + "id_suffix": "permissive_ports", + "items": [], + "level": "warning", + "path": "computeengine.projects.id.firewalls.id.allowed_traffic.id.ports.id", + "rationale": "The firewall rule was found to be exposing a well-known port to all source addresses. Well-known ports are commonly probed by automated scanning tools, and could be an indicator of sensitive services exposed to Internet. If such services need to be exposed, a restriction on the source address could help to reduce the attack surface of the infrastructure.", + "references": null, + "remediation": null, + "service": "Compute Engine" + }, + "computeengine-instance-disk-with-no-snapshot": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Instances", + "description": "Instance Disk without Snapshots", + "display_path": "computeengine.projects.id.zones.id.instances.id", + "flagged_items": 0, + "id_suffix": "latest_snapshot", + "items": [], + "level": "warning", + "path": "computeengine.projects.id.zones.id.instances.id.disks.id", + "rationale": "You should have snapshots of your in-use or available disks taken on a regular basis to enable disaster recovery efforts.", + "references": [ + "https://cloud.google.com/compute/docs/disks/create-snapshots", + "https://cloud.google.com/compute/docs/disks/scheduled-snapshots", + "https://cloud.google.com/compute/docs/disks/snapshot-best-practices" + ], + "remediation": null, + "service": "Compute Engine" + }, + "computeengine-instance-with-deletion-protection-disabled": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Instances", + "description": "Instance without Deletion Protection", + "flagged_items": 0, + "id_suffix": "deletion_protection_enabled", + "items": [], + "level": "warning", + "path": "computeengine.projects.id.zones.id.instances.id", + "rationale": "It is good practice to enable this feature on production instances, to ensure that they may not be deleted by accident.", + "references": [ + "https://cloud.google.com/compute/docs/instances/preventing-accidental-vm-deletion" + ], + "remediation": null, + "service": "Compute Engine" + }, + "computeengine-network-with-no-instances": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Networks", + "description": "Network without Instances", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "computeengine.projects.id.networks.id", + "rationale": "Maintaining unused resources increases risks of misconfigurations and increases the difficulty of audits.", + "references": null, + "remediation": null, + "service": "Compute Engine" + }, + "computeengine-old-disk-snapshot": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Snapshots", + "description": "Old Instance Disk Snapshot", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "computeengine.projects.id.snapshots.id", + "rationale": "Disk snapshots that are over 90 days are likely to be outdated.", + "references": [ + "https://cloud.google.com/compute/docs/disks/create-snapshots", + "https://cloud.google.com/compute/docs/disks/scheduled-snapshots", + "https://cloud.google.com/compute/docs/disks/snapshot-best-practices" + ], + "remediation": null, + "service": "Compute Engine" + } + }, + "firewalls_count": 0, + "instances_count": 0, + "networks_count": 0, + "projects": {}, + "snapshots_count": 0, + "subnetworks_count": 0 + }, + "iam": { + "bindings_count": 0, + "filters": {}, + "findings": { + "iam-gmail-accounts-used": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "1.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Users", + "description": "Gmail Account in Use", + "flagged_items": 0, + "id_suffix": "name", + "items": [], + "level": "warning", + "path": "iam.projects.id.users.id", + "rationale": "Gmail accounts are personally created and controllable accounts. Organizations seldom have any control over them. Thus, it is recommended that you use fully managed corporate Google accounts for increased visibility, auditing, and control over access to Cloud Platform resources.", + "references": null, + "remediation": null, + "service": "IAM" + }, + "iam-lack-of-service-account-key-rotation": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "1.6", + "version": "1.0.0" + } + ], + "dashboard_name": "Service Accounts", + "description": "Lack of Service Account Key Rotation", + "display_path": "iam.projects.id.service_accounts.id", + "flagged_items": 0, + "id_suffix": "valid_after", + "items": [], + "level": "warning", + "path": "iam.projects.id.service_accounts.id.keys.id", + "rationale": "Rotating Service Account keys will reduce the window of opportunity for an access key that is associated with a compromised or terminated account to be used. Service Account keys should be rotated to ensure that data cannot be accessed with an old key which might have been lost, cracked, or stolen. It should be ensured that keys are rotated every 90 days.", + "references": [ + "https://cloud.google.com/iam/docs/creating-managing-service-account-keys" + ], + "remediation": null, + "service": "IAM" + }, + "iam-primitive-role-in-use": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "1.4", + "version": "1.0.0" + } + ], + "dashboard_name": "Bindings", + "description": "Primitive Role in Use", + "flagged_items": 0, + "id_suffix": "name", + "items": [], + "level": "warning", + "path": "iam.projects.id.bindings.id", + "rationale": "Primitive roles grant significant privileges. In most cases, usage of these roles is not recommended and does not follow security best practice.

Note: This rule may flag Google-Managed Service Accounts. Google services rely on these Service Accounts having access to the project, and recommends not removing or changing the Service Account's role (see https://cloud.google.com/iam/docs/service-accounts#google-managed).", + "references": [ + "https://cloud.google.com/iam/docs/understanding-roles", + "https://cloud.google.com/iam/docs/using-iam-securely" + ], + "remediation": null, + "service": "IAM" + }, + "iam-role-assigned-to-user": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Bindings", + "description": "IAM Role Assigned to User", + "flagged_items": 0, + "id_suffix": "users", + "items": [], + "level": "warning", + "path": "iam.projects.id.bindings.id", + "rationale": "Best practices recommends granting roles to a Google Suite group instead of to individual users when possible. It is easier to add members to and remove members from a group instead of updating a Cloud IAM policy to add or remove users.", + "references": [ + "https://cloud.google.com/iam/docs/understanding-roles", + "https://cloud.google.com/iam/docs/using-iam-securely" + ], + "remediation": null, + "service": "IAM" + }, + "iam-sa-has-admin-privileges": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "1.4", + "version": "1.0.0" + } + ], + "dashboard_name": "Bindings", + "description": "Service Account with Admin Privileges", + "flagged_items": 0, + "id_suffix": "service_accounts", + "items": [], + "level": "warning", + "path": "iam.projects.id.bindings.id", + "rationale": "Service accounts represent service-level security of the Resources (application or a VM) which can be determined by the roles assigned to it. Enrolling Service Accounts with administrative privileges grants full access to assigned application or a VM, Service Account Access holder can user.

Note: This rule may flag Google-Managed Service Accounts. Google services rely on these Service Accounts having access to the project, and recommends not removing or changing the Service Account's role", + "references": [ + "https://cloud.google.com/iam/docs/service-accounts#google-managed", + "https://cloud.google.com/iam/docs/understanding-roles", + "https://cloud.google.com/iam/docs/using-iam-securely" + ], + "remediation": null, + "service": "IAM" + }, + "iam-service-account-user-allAuthenticatedUsers": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Service Accounts", + "description": "Service Account with 'allAuthenticatedUsers' Service Account User", + "display_path": "iam.projects.id.service_accounts.id", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "iam.projects.id.service_accounts.id.bindings.id", + "rationale": "Access to the Service Account User role (roles/iam.serviceAccountUser) should be restricted, as members granted this role on a service account can use it to indirectly access all the resources to which the service account has access. ", + "references": [ + "https://cloud.google.com/iam/docs/service-accounts#user-role" + ], + "remediation": null, + "service": "IAM" + }, + "iam-service-account-user-allUsers": { + "checked_items": 0, + "compliance": null, + "dashboard_name": "Service Accounts", + "description": "Service Account with 'allUsers' Service Account User", + "display_path": "iam.projects.id.service_accounts.id", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "iam.projects.id.service_accounts.id.bindings.id", + "rationale": "Access to the Service Account User role (roles/iam.serviceAccountUser) should be restricted, as members granted this role on a service account can use it to indirectly access all the resources to which the service account has access. ", + "references": [ + "https://cloud.google.com/iam/docs/service-accounts#user-role" + ], + "remediation": null, + "service": "IAM" + }, + "iam-service-account-with-user-managed-keys": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "1.3", + "version": "1.0.0" + } + ], + "dashboard_name": "Service Accounts", + "description": "User-Managed Service Account Keys", + "display_path": "iam.projects.id.service_accounts.id", + "flagged_items": 0, + "id_suffix": "key_type", + "items": [], + "level": "warning", + "path": "iam.projects.id.service_accounts.id.keys.id", + "rationale": "It is recommended to prevent use of user-managed service account keys, as anyone who has access to the keys will be able to access resources through the service account. Best practice recommends using GCP-managed keys, which are used by Cloud Platform services such as App Engine and Compute Engine. These keys cannot be downloaded. Google will keep the keys and automatically rotate them on an approximately weekly basis.", + "references": [ + "https://cloud.google.com/iam/docs/understanding-service-accounts#managing_service_account_keys" + ], + "remediation": null, + "service": "IAM" + }, + "iam-user-has-sa-user-role": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "1.5", + "version": "1.0.0" + } + ], + "dashboard_name": "Bindings", + "description": "User with \"Service Account User\" Role at the Project Level", + "flagged_items": 0, + "id_suffix": "user_has_sa_user_role", + "items": [], + "level": "warning", + "path": "iam.projects.id.bindings.id", + "rationale": "Granting the iam.serviceAccountUser role to a user for a project gives the user access to all service accounts in the project, including service accounts that may be created in the future. This can result into elevation of privileges by using service accounts and corresponding Compute Engine instances.", + "references": [ + "https://cloud.google.com/iam/docs/service-accounts#google-managed", + "https://cloud.google.com/iam/docs/understanding-roles", + "https://cloud.google.com/iam/docs/using-iam-securely" + ], + "remediation": null, + "service": "IAM" + } + }, + "groups_count": 0, + "projects": {}, + "service_accounts_count": 0, + "users_count": 0 + }, + "kms": { + "filters": {}, + "findings": {}, + "keyrings_count": 0, + "projects": {} + }, + "kubernetesengine": { + "clusters_count": 0, + "filters": {}, + "findings": { + "kubernetesengine-basic-authentication-enabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.10", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.8.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Basic Authentication Enabled", + "flagged_items": 0, + "id_suffix": "basic_authentication_enabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "Basic authentication allows a user to authenticate to the cluster with a username and password and it is stored in plain text without any encryption. Disabling Basic authentication will prevent attacks like brute force. Its recommended to use either client certificate or IAM for authentication.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_authn_methods", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#evaluation_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-certificate-authentication-enabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS GKE Benchmark", + "reference": "6.8.2", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Certificate Authentication Enabled", + "flagged_items": 0, + "id_suffix": "client_certificate_enabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "Unless applications use the client certificate authentication method, it should be disabled.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_authn_methods", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#evaluation_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-cluster-alias-ip-disabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.13", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.6.2", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Alias IP Disabled", + "flagged_items": 0, + "id_suffix": "alias_ip_disabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "With Alias IPs ranges enabled, Kubernetes Engine clusters can allocate IP addresses from a CIDR block known to Google Cloud Platform. This makes your cluster more scalable and allows your cluster to better interact with other GCP products and entities.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_network_access_to_the_control_plane_and_nodes", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-cluster-has-no-labels": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.5", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Clusters Lacking Labels", + "flagged_items": 0, + "id_suffix": "has_no_labels", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "Labels enable users to map their own organizational structures onto system objects in a loosely coupled fashion, without requiring clients to store these mappings. Labels can also be used to apply specific security settings and auto configure objects at creation.", + "references": [ + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#use_namespaces_and_rbac_to_restrict_access_to_cluster_resources" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-cluster-logging-disabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.1", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.7.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Cluster Logging Disabled", + "flagged_items": 0, + "id_suffix": "logging_disabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "You should enable cluster logging and use a logging service so your cluster can export logs about its activities.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://kubernetes.io/docs/tasks/debug-application-cluster/audit/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#stackdriver_logging", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-cluster-master-authorized-networks-disabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.4", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.6.3", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Master Authorized Networks Disabled", + "flagged_items": 0, + "id_suffix": "master_authorized_networks_disabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "Master authorized networks blocks untrusted IP addresses from outside Google Cloud Platform. Addresses from inside GCP can still reach your master through HTTPS provided that they have the necessary Kubernetes credentials.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/authorized-networks", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_network_access_to_the_control_plane_and_nodes", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-cluster-monitoring-disabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.2", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.7.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Cluster Monitoring Disabled", + "flagged_items": 0, + "id_suffix": "monitoring_disabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "You should enable cluster monitoring and use a monitoring service so your cluster can export metrics about its activities.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#stackdriver_logging", + "https://cloud.google.com/monitoring/kubernetes-engine#about-skm", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-cluster-network-policy-disabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.11", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.6.7", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Network Policy Disabled", + "flagged_items": 0, + "id_suffix": "network_policy_disabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "By default, pods are non-isolated; they accept traffic from any source. Pods become isolated by having a NetworkPolicy that selects them. Once there is any NetworkPolicy in a namespace selecting a particular pod, that pod will reject any connections that are not allowed by any NetworkPolicy.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_with_network_policy", + "https://cloud.google.com/kubernetes-engine/docs/concepts/security-overview#network_security", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-cluster-pod-security-policy-config-disabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.14", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.10.3", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Pod Security Policy Disabled", + "flagged_items": 0, + "id_suffix": "pod_security_policy_enabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "A Pod Security Policy is a cluster-level resource that controls security sensitive aspects of the pod specification. The PodSecurityPolicy objects define a set of conditions that a pod must run with in order to be accepted into the system, as well as defaults for the related fields.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/pod-security-policies", + "https://kubernetes.io/docs/concepts/policy/pod-security-policy", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": "Enable the Pod Security Policy. By default, Pod Security Policy is disabled when you create a new cluster.", + "service": "Kubernetes Engine" + }, + "kubernetesengine-cluster-private-google-access-disabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.16", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Private Google Access Disabled", + "flagged_items": 0, + "id_suffix": "private_ip_google_access_disabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "Enabling Private Google Access allows VMs on a subnetwork to use a private IP address to reach Google APIs rather than an external IP address.", + "references": [ + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_network_access_to_the_control_plane_and_nodes" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-dashboard-enabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.6", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.10.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "The GKE Dashboard Enabled", + "flagged_items": 0, + "id_suffix": "dashboard_status", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "You should disable the Kubernetes Web UI (Dashboard) when running on Kubernetes Engine. The Kubernetes Web UI (Dashboard) is backed by a highly privileged Kubernetes Service Account.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#disable_kubernetes_dashboard", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-default-service-account-used": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.17", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.2.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Default Service Account in Use", + "flagged_items": 0, + "id_suffix": "default_service_account_used", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "You should create and use a minimally privileged service account to run your Kubernetes Engine cluster instead of using the Compute Engine default service account.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#use_least_privilege_sa", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-legacy-abac-enabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.3", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.8.4", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Legacy Authorization (ABAC) Enabled", + "flagged_items": 0, + "id_suffix": "legacy_abac_enabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "The legacy authorizer in Kubernetes Engine grants broad, statically defined permissions. To ensure that RBAC limits permissions correctly, you must disable the legacy authorizer. RBAC has significant security advantages, can help you ensure that users only have access to cluster resources within their own namespace and is now stable in Kubernetes.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#leave_abac_disabled_default_for_110", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-legacy-metadata-endpoints-enabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS GKE Benchmark", + "reference": "6.4.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Legacy Metadata Endpoints Enabled", + "display_path": "kubernetesengine.projects.id.zones.id.clusters.id", + "flagged_items": 0, + "id_suffix": "legacy_metadata_endpoints_enabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id.node_pools.id", + "rationale": "Unless your app uses the legacy metadata endpoints, you should disable them.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#protect_node_metadata_default_for_112", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-node-auto-repair-disabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.7", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.5.2", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Nodes Auto-Repair Disabled", + "display_path": "kubernetesengine.projects.id.zones.id.clusters.id", + "flagged_items": 0, + "id_suffix": "auto_repair_disabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id.node_pools.id", + "rationale": "Auto-repair helps you keep the nodes in your cluster in a healthy, running state.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/node-auto-repair", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-node-auto-upgrade-disabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.8", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.5.3", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Nodes Auto-Upgrade Disabled", + "display_path": "kubernetesengine.projects.id.zones.id.clusters.id", + "flagged_items": 0, + "id_suffix": "auto_upgrade_disabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id.node_pools.id", + "rationale": "Auto-upgrades automatically ensures that security updates are applied and kept up to date.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/node-auto-upgrades", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-node-container-optimized-os-not-used": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.9", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.5.1", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Lack of Container-Optimized OS Node Images", + "flagged_items": 0, + "id_suffix": "container_optimized_os_not_used", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "The Container-Optimized OS image provides better support, security, and stability than previous images.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/container-optimized-os/docs/concepts/features-and-benefits", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-private-cluster-disabled": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.15", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.6.4", + "version": "1.0.0" + }, + { + "name": "CIS GKE Benchmark", + "reference": "6.6.5", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Private Cluster Disabled", + "flagged_items": 0, + "id_suffix": "private_cluster_disabled", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "A private cluster is a cluster that makes your master inaccessible from the public internet. In a private cluster, nodes do not have public IP addresses, so your workloads run in an environment that is isolated from the internet. Nodes have addressed only in the private RFC 1918 address space. Nodes and masters communicate with each other privately using VPC peering.", + "references": [ + "https://www.cisecurity.org/benchmark/kubernetes/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#restrict_network_access_to_the_control_plane_and_nodes", + "https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks#default_values_on" + ], + "remediation": null, + "service": "Kubernetes Engine" + }, + "kubernetesengine-scopes-not-limited": { + "checked_items": 0, + "compliance": [ + { + "name": "CIS Google Cloud Platform Foundations", + "reference": "7.18", + "version": "1.0.0" + } + ], + "dashboard_name": "Clusters", + "description": "Lack of Access Scope Limitation", + "flagged_items": 0, + "id_suffix": "scopes_not_limited", + "items": [], + "level": "warning", + "path": "kubernetesengine.projects.id.zones.id.clusters.id", + "rationale": "If you are not creating a separate service account for your nodes, you should limit the scopes of the node service account to reduce the possibility of a privilege escalation in an attack. This ensures that your default service account does not have permissions beyond those necessary to run your cluster. While the default scopes are limited, they may include scopes beyond the minimally required scopes needed to run your cluster. If you are accessing private images in Google Container Registry, the minimally required scopes are only logging.write, monitoring, and devstorage.read_only.", + "references": [ + "https://cloud.google.com/kubernetes-engine/docs/how-to/access-scopes" + ], + "remediation": null, + "service": "Kubernetes Engine" + } + }, + "projects": {} + }, + "stackdriverlogging": { + "filters": {}, + "findings": { + "stackdriverlogging-no-export-sinks": { + "checked_items": 1, + "compliance": null, + "dashboard_name": "Logging Configurations", + "description": "Lack of Export Sinks", + "display_path": "stackdriverlogging.projects.id.sinks", + "flagged_items": 0, + "items": [], + "level": "warning", + "path": "stackdriverlogging.projects.id", + "rationale": "Export sinks for Stackdriver logging were not found. As a result, logs would be deleted after the configured retention period, and would not be backed up.", + "references": [ + "https://cloud.google.com/logging", + "https://cloud.google.com/logging/docs/export" + ], + "remediation": null, + "service": "Stackdriver Logging" + } + }, + "metrics_count": 0, + "projects": { + "gcp-project-id": { + "metrics": {}, + "metrics_count": 0, + "sinks": { + "_Default": { + "destination": "logging.googleapis.com/projects/gcp-project-id/locations/global/buckets/_Default", + "filter": "NOT LOG_ID(\"cloudaudit.googleapis.com/activity\") AND NOT LOG_ID(\"externalaudit.googleapis.com/activity\") AND NOT LOG_ID(\"cloudaudit.googleapis.com/system_event\") AND NOT LOG_ID(\"externalaudit.googleapis.com/system_event\") AND NOT LOG_ID(\"cloudaudit.googleapis.com/access_transparency\") AND NOT LOG_ID(\"externalaudit.googleapis.com/access_transparency\")", + "name": "_Default" + }, + "_Required": { + "destination": "logging.googleapis.com/projects/gcp-project-id/locations/global/buckets/_Required", + "filter": "LOG_ID(\"cloudaudit.googleapis.com/activity\") OR LOG_ID(\"externalaudit.googleapis.com/activity\") OR LOG_ID(\"cloudaudit.googleapis.com/system_event\") OR LOG_ID(\"externalaudit.googleapis.com/system_event\") OR LOG_ID(\"cloudaudit.googleapis.com/access_transparency\") OR LOG_ID(\"externalaudit.googleapis.com/access_transparency\")", + "name": "_Required" + } + }, + "sinks_count": 2 + } + }, + "sinks_count": 2 + }, + "stackdrivermonitoring": { + "alert_policies_count": 0, + "filters": {}, + "findings": {}, + "projects": { + "gcp-project-id": { + "alert_policies": {}, + "alert_policies_count": 0, + "uptime_checks": {}, + "uptime_checks_count": 0 + } + }, + "uptime_checks_count": 0 + } + } +} \ No newline at end of file From b95d80cd7add86fac7e3a343580b57a77ebdc3eb Mon Sep 17 00:00:00 2001 From: kiblik Date: Tue, 9 Apr 2024 01:58:30 +0200 Subject: [PATCH 017/138] PreDjango 4.2 fixes (#9882) --- dojo/models.py | 6 +++--- dojo/settings/settings.dist.py | 3 --- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/dojo/models.py b/dojo/models.py index 53d9637e01..b4e8191591 100755 --- a/dojo/models.py +++ b/dojo/models.py @@ -1648,7 +1648,7 @@ def clean(self): action_string = 'Postgres does not accept NULL character. Attempting to replace with %00...' for remove_str in null_char_list: self.path = self.path.replace(remove_str, '%00') - errors.append(ValidationError(f'Path "{old_value}" has invalid format - It contains the NULL character. The following action was taken: {action_string}')) + logging.error(f'Path "{old_value}" has invalid format - It contains the NULL character. The following action was taken: {action_string}') if self.path == '': self.path = None @@ -1661,7 +1661,7 @@ def clean(self): action_string = 'Postgres does not accept NULL character. Attempting to replace with %00...' for remove_str in null_char_list: self.query = self.query.replace(remove_str, '%00') - errors.append(ValidationError(f'Query "{old_value}" has invalid format - It contains the NULL character. The following action was taken: {action_string}')) + logging.error(f'Query "{old_value}" has invalid format - It contains the NULL character. The following action was taken: {action_string}') if self.query == '': self.query = None @@ -1674,7 +1674,7 @@ def clean(self): action_string = 'Postgres does not accept NULL character. Attempting to replace with %00...' for remove_str in null_char_list: self.fragment = self.fragment.replace(remove_str, '%00') - errors.append(ValidationError(f'Fragment "{old_value}" has invalid format - It contains the NULL character. The following action was taken: {action_string}')) + logging.error(f'Fragment "{old_value}" has invalid format - It contains the NULL character. The following action was taken: {action_string}') if self.fragment == '': self.fragment = None diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index b1552bf456..f719edb83d 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -492,10 +492,7 @@ def generate_url(scheme, double_slashes, user, password, host, port, path, param 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher', 'django.contrib.auth.hashers.BCryptSHA256PasswordHasher', 'django.contrib.auth.hashers.BCryptPasswordHasher', - 'django.contrib.auth.hashers.SHA1PasswordHasher', 'django.contrib.auth.hashers.MD5PasswordHasher', - 'django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher', - 'django.contrib.auth.hashers.UnsaltedMD5PasswordHasher', ] SOCIAL_AUTH_PIPELINE = ( From a058e1b4da6af1f1ae7cb53478821e9e8bb4b28b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 23:40:48 -0500 Subject: [PATCH 018/138] Update Helm release redis from 19.0.2 to ~19.1.0 (helm/defectdojo/Chart.yaml) (#9890) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- helm/defectdojo/Chart.lock | 6 +++--- helm/defectdojo/Chart.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/helm/defectdojo/Chart.lock b/helm/defectdojo/Chart.lock index 55ee782665..6abe2731ef 100644 --- a/helm/defectdojo/Chart.lock +++ b/helm/defectdojo/Chart.lock @@ -13,6 +13,6 @@ dependencies: version: 11.16.2 - name: redis repository: https://charts.bitnami.com/bitnami - version: 19.0.2 -digest: sha256:9a6157ef79354795f47ebea124f48c044c5d816a9424dbb17d555828734bb014 -generated: "2024-04-08T18:06:18.688462714Z" + version: 19.1.0 +digest: sha256:ea928e8d4001717c3ee4ca198d0365cb2037913a34768f1b30d3dc5cae5f73a0 +generated: "2024-04-08T18:32:57.408678021Z" diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index 43c7a5afa3..5e86ffdc5e 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -27,6 +27,6 @@ dependencies: repository: "https://charts.bitnami.com/bitnami" condition: rabbitmq.enabled - name: redis - version: ~19.0.0 + version: ~19.1.0 repository: "https://charts.bitnami.com/bitnami" condition: redis.enabled From 1fa0b5934e3b46507a988e61b9f5cf7bbf808bea Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Wed, 10 Apr 2024 07:00:03 +0200 Subject: [PATCH 019/138] sonarqube: cve to vulnerability_ids (#9902) --- .../tools/sonarqube/sonarqube_restapi_json.py | 46 ++++++++++--------- unittests/tools/test_sonarqube_parser.py | 7 ++- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/dojo/tools/sonarqube/sonarqube_restapi_json.py b/dojo/tools/sonarqube/sonarqube_restapi_json.py index df947baeeb..8e8fb8c108 100644 --- a/dojo/tools/sonarqube/sonarqube_restapi_json.py +++ b/dojo/tools/sonarqube/sonarqube_restapi_json.py @@ -53,27 +53,6 @@ def get_json_items(self, json_content, test, mode): flows = str(issue.get("flows")) status = issue.get("status") message = issue.get("message") - cve = None - if "Reference: CVE" in message: - cve_pattern = r'Reference: CVE-\d{4}-\d{4,7}' - cves = re.findall(cve_pattern, message) - if cves: - cve = cves[0].split("Reference: ")[1] - elif "References: CVE" in message: - cve_pattern = r'References: CVE-\d{4}-\d{4,7}' - cves = re.findall(cve_pattern, message) - if cves: - cve = cves[0].split("References: ")[1] - elif "Reference: GHSA" in message and cve is None: - cve_pattern = r'Reference: GHSA-[23456789cfghjmpqrvwx]{4}-[23456789cfghjmpqrvwx]{4}-[23456789cfghjmpqrvwx]{4}' - cves = re.findall(cve_pattern, message) - if cves: - cve = cves[0].split("Reference: ")[1] - elif "References: GHSA" in message and cve is None: - cve_pattern = r'References: GHSA-[23456789cfghjmpqrvwx]{4}-[23456789cfghjmpqrvwx]{4}-[23456789cfghjmpqrvwx]{4}' - cves = re.findall(cve_pattern, message) - if cves: - cve = cves[0].split("References: ")[1] cwe = None if "Category: CWE-" in message: cwe_pattern = r'Category: CWE-\d{1,5}' @@ -124,11 +103,34 @@ def get_json_items(self, json_content, test, mode): dynamic_finding=False, component_name=component_name, component_version=component_version, - cve=cve, cwe=cwe, cvssv3_score=cvss, tags=["vulnerability"], ) + vulnids = list() + if "Reference: CVE" in message: + cve_pattern = r'Reference: CVE-\d{4}-\d{4,7}' + cves = re.findall(cve_pattern, message) + for cve in cves: + vulnids.append(cve.split("Reference: ")[1]) + if "References: CVE" in message: + cve_pattern = r'References: CVE-\d{4}-\d{4,7}' + cves = re.findall(cve_pattern, message) + for cve in cves: + vulnids.append(cve.split("References: ")[1]) + if "Reference: GHSA" in message: + cve_pattern = r'Reference: GHSA-[23456789cfghjmpqrvwx]{4}-[23456789cfghjmpqrvwx]{4}-[23456789cfghjmpqrvwx]{4}' + cves = re.findall(cve_pattern, message) + for cve in cves: + vulnids.append(cve.split("Reference: ")[1]) + if "References: GHSA" in message: + cve_pattern = r'References: GHSA-[23456789cfghjmpqrvwx]{4}-[23456789cfghjmpqrvwx]{4}-[23456789cfghjmpqrvwx]{4}' + cves = re.findall(cve_pattern, message) + for cve in cves: + vulnids.append(cve.split("References: ")[1]) + item.unsaved_vulnerability_ids = list() + for vulnid in vulnids: + item.unsaved_vulnerability_ids.append(vulnid) elif issue.get("type") == "CODE_SMELL": key = issue.get("key") rule = issue.get("rule") diff --git a/unittests/tools/test_sonarqube_parser.py b/unittests/tools/test_sonarqube_parser.py index 3172407f82..946407e144 100644 --- a/unittests/tools/test_sonarqube_parser.py +++ b/unittests/tools/test_sonarqube_parser.py @@ -559,7 +559,7 @@ def test_parse_json_file_from_api_with_multiple_findings_json(self): self.assertEqual(str, type(item.description)) self.assertEqual("OWASP:UsingComponentWithKnownVulnerability_fjioefjwoefijo", item.title) self.assertEqual("Medium", item.severity) - self.assertEqual("CVE-2024-2529", item.cve) + self.assertEqual("CVE-2024-2529", item.unsaved_vulnerability_ids[0]) self.assertEqual("120", item.cwe) self.assertEqual("6.4", item.cvssv3_score) self.assertEqual("package", item.component_name) @@ -567,16 +567,15 @@ def test_parse_json_file_from_api_with_multiple_findings_json(self): item = findings[1] self.assertEqual("Web:TableWithoutCaptionCheck_asdfwfewfwefewf", item.title) self.assertEqual("Low", item.severity) - self.assertIsNone(item.cve) self.assertEqual(0, item.cwe) self.assertIsNone(item.cvssv3_score) item = findings[2] self.assertEqual("typescript:S1533_fjoiewfjoweifjoihugu-", item.title) self.assertEqual("Low", item.severity) item = findings[3] - self.assertEqual("GHSA-frr2-c345-p7c2", item.cve) + self.assertEqual("GHSA-frr2-c345-p7c2", item.unsaved_vulnerability_ids[0]) item = findings[4] - self.assertEqual("CVE-2023-52428", item.cve) + self.assertEqual("CVE-2023-52428", item.unsaved_vulnerability_ids[0]) self.assertEqual("nimbus-jose-jwt-9.24.4.jar", item.component_name) self.assertIsNone(item.component_version) From 50f19f1563d8767753cf0dd2e92ff357309e12dd Mon Sep 17 00:00:00 2001 From: kiblik Date: Fri, 12 Apr 2024 02:07:03 +0200 Subject: [PATCH 020/138] Ruff: Fix UP (after couple of merges) (#9903) --- dojo/tools/intsights/csv_handler.py | 2 +- dojo/tools/intsights/json_handler.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dojo/tools/intsights/csv_handler.py b/dojo/tools/intsights/csv_handler.py index 3369d4f010..828cfaf802 100644 --- a/dojo/tools/intsights/csv_handler.py +++ b/dojo/tools/intsights/csv_handler.py @@ -3,7 +3,7 @@ import io -class IntSightsCSVParser(object): +class IntSightsCSVParser: def _parse_csv(self, csv_file) -> [dict]: """ diff --git a/dojo/tools/intsights/json_handler.py b/dojo/tools/intsights/json_handler.py index d3d2faae6d..3455548b09 100644 --- a/dojo/tools/intsights/json_handler.py +++ b/dojo/tools/intsights/json_handler.py @@ -1,7 +1,7 @@ import json -class IntSightsJSONParser(object): +class IntSightsJSONParser: def _parse_json(self, json_file) -> [dict]: """ Parses entries from the JSON object into a list of alerts From 5f66a2cfcd17a313105055f2acf1b3661225d768 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 12 Apr 2024 00:13:58 -0500 Subject: [PATCH 021/138] Update dependency ruff from 0.3.5 to v0.3.6 (requirements-lint.txt) (#9918) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- requirements-lint.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-lint.txt b/requirements-lint.txt index a35983113e..8143810d30 100644 --- a/requirements-lint.txt +++ b/requirements-lint.txt @@ -1 +1 @@ -ruff==0.3.5 \ No newline at end of file +ruff==0.3.6 \ No newline at end of file From 8b2f082d28ec29c1386a543d4f37ccdae737930c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 13 Apr 2024 14:55:22 -0500 Subject: [PATCH 022/138] chore(deps): update stefanzweifel/git-auto-commit-action action from v5.0.0 to v5.0.1 (.github/workflows/release-3-master-into-dev.yml) (#9920) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/plantuml.yml | 2 +- .github/workflows/release-1-create-pr.yml | 2 +- .github/workflows/release-3-master-into-dev.yml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/plantuml.yml b/.github/workflows/plantuml.yml index c6016c0398..5fa308ffb4 100644 --- a/.github/workflows/plantuml.yml +++ b/.github/workflows/plantuml.yml @@ -33,7 +33,7 @@ jobs: with: args: -v -tpng ${{ steps.getfile.outputs.files }} - name: Push Local Changes - uses: stefanzweifel/git-auto-commit-action@v5.0.0 + uses: stefanzweifel/git-auto-commit-action@v5.0.1 with: commit_user_name: "PlantUML_bot" commit_user_email: "noreply@defectdojo.org" diff --git a/.github/workflows/release-1-create-pr.yml b/.github/workflows/release-1-create-pr.yml index ec73f6a49f..0b7bf2c92c 100644 --- a/.github/workflows/release-1-create-pr.yml +++ b/.github/workflows/release-1-create-pr.yml @@ -75,7 +75,7 @@ jobs: grep -H version helm/defectdojo/Chart.yaml - name: Push version changes - uses: stefanzweifel/git-auto-commit-action@v5.0.0 + uses: stefanzweifel/git-auto-commit-action@v5.0.1 with: commit_user_name: "${{ env.GIT_USERNAME }}" commit_user_email: "${{ env.GIT_EMAIL }}" diff --git a/.github/workflows/release-3-master-into-dev.yml b/.github/workflows/release-3-master-into-dev.yml index 241fdbdfa9..2da1dc0dd9 100644 --- a/.github/workflows/release-3-master-into-dev.yml +++ b/.github/workflows/release-3-master-into-dev.yml @@ -73,7 +73,7 @@ jobs: if: endsWith(github.event.inputs.release_number_new, '.0') && endsWith(github.event.inputs.release_number_dev, '.0-dev') - name: Push version changes - uses: stefanzweifel/git-auto-commit-action@v5.0.0 + uses: stefanzweifel/git-auto-commit-action@v5.0.1 with: commit_user_name: "${{ env.GIT_USERNAME }}" commit_user_email: "${{ env.GIT_EMAIL }}" @@ -139,7 +139,7 @@ jobs: grep version components/package.json - name: Push version changes - uses: stefanzweifel/git-auto-commit-action@v5.0.0 + uses: stefanzweifel/git-auto-commit-action@v5.0.1 with: commit_user_name: "${{ env.GIT_USERNAME }}" commit_user_email: "${{ env.GIT_EMAIL }}" From 49cea219813fe01f105306ba5f48036dafbca851 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 13 Apr 2024 15:13:50 -0500 Subject: [PATCH 023/138] Update dependency ruff from 0.3.6 to v0.3.7 (requirements-lint.txt) (#9919) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- requirements-lint.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-lint.txt b/requirements-lint.txt index 8143810d30..bbd63c00ea 100644 --- a/requirements-lint.txt +++ b/requirements-lint.txt @@ -1 +1 @@ -ruff==0.3.6 \ No newline at end of file +ruff==0.3.7 \ No newline at end of file From 2dfc00539278d34b70aa5a48d1225245331dc859 Mon Sep 17 00:00:00 2001 From: DefectDojo release bot Date: Mon, 15 Apr 2024 18:41:25 +0000 Subject: [PATCH 024/138] Update versions in application files --- components/package.json | 2 +- dojo/__init__.py | 2 +- helm/defectdojo/Chart.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/package.json b/components/package.json index 414b261866..41e9d22009 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "defectdojo", - "version": "2.33.2", + "version": "2.34.0-dev", "license" : "BSD-3-Clause", "private": true, "dependencies": { diff --git a/dojo/__init__.py b/dojo/__init__.py index d97cb16476..4758913441 100644 --- a/dojo/__init__.py +++ b/dojo/__init__.py @@ -4,6 +4,6 @@ # Django starts so that shared_task will use this app. from .celery import app as celery_app # noqa: F401 -__version__ = '2.33.2' +__version__ = '2.34.0-dev' __url__ = 'https://github.com/DefectDojo/django-DefectDojo' __docs__ = 'https://documentation.defectdojo.com' diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index 0f892f8ccc..fbb5647928 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 -appVersion: "2.33.2" +appVersion: "2.34.0-dev" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.120 +version: 1.6.121-dev icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap From 28c031a5cc4b6c9376dc71394ab4903779247e1c Mon Sep 17 00:00:00 2001 From: DefectDojo Date: Mon, 15 Apr 2024 18:49:51 +0000 Subject: [PATCH 025/138] Update helm lock file Signed-off-by: DefectDojo --- helm/defectdojo/Chart.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/helm/defectdojo/Chart.lock b/helm/defectdojo/Chart.lock index 6abe2731ef..dbd032c670 100644 --- a/helm/defectdojo/Chart.lock +++ b/helm/defectdojo/Chart.lock @@ -4,7 +4,7 @@ dependencies: version: 9.19.1 - name: postgresql repository: https://charts.bitnami.com/bitnami - version: 15.2.4 + version: 15.2.5 - name: postgresql-ha repository: https://charts.bitnami.com/bitnami version: 9.4.11 @@ -14,5 +14,5 @@ dependencies: - name: redis repository: https://charts.bitnami.com/bitnami version: 19.1.0 -digest: sha256:ea928e8d4001717c3ee4ca198d0365cb2037913a34768f1b30d3dc5cae5f73a0 -generated: "2024-04-08T18:32:57.408678021Z" +digest: sha256:682c2bf2aa7e86d0207b2c20d05212aa262d37ba80309d8aefe14884326ae93c +generated: "2024-04-15T18:49:42.741358115Z" From bab52177e64b0c48c0f9439ad5e245194c3c79ad Mon Sep 17 00:00:00 2001 From: DefectDojo release bot Date: Tue, 16 Apr 2024 23:26:29 +0000 Subject: [PATCH 026/138] Update versions in application files --- components/package.json | 2 +- dojo/__init__.py | 2 +- helm/defectdojo/Chart.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/package.json b/components/package.json index 3725e238fe..41e9d22009 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "defectdojo", - "version": "2.33.3", + "version": "2.34.0-dev", "license" : "BSD-3-Clause", "private": true, "dependencies": { diff --git a/dojo/__init__.py b/dojo/__init__.py index 94ecbff71f..4758913441 100644 --- a/dojo/__init__.py +++ b/dojo/__init__.py @@ -4,6 +4,6 @@ # Django starts so that shared_task will use this app. from .celery import app as celery_app # noqa: F401 -__version__ = '2.33.3' +__version__ = '2.34.0-dev' __url__ = 'https://github.com/DefectDojo/django-DefectDojo' __docs__ = 'https://documentation.defectdojo.com' diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index 326e73b618..59ad62fa89 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 -appVersion: "2.33.3" +appVersion: "2.34.0-dev" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.121 +version: 1.6.122-dev icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap From 4edcfe583db171b89c0ef24d11d94a23db9a63fe Mon Sep 17 00:00:00 2001 From: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> Date: Tue, 16 Apr 2024 18:37:56 -0500 Subject: [PATCH 027/138] Sync with dev --- ruff.toml | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/ruff.toml b/ruff.toml index b9e647656c..031f505f50 100644 --- a/ruff.toml +++ b/ruff.toml @@ -31,13 +31,30 @@ exclude = [ # Enable the pycodestyle (`E`) and Pyflakes (`F`) rules by default. # Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or # McCabe complexity (`C901`) by default. -select = ["E", "F", "FLY", "TRY004", "TRY2"] +select = [ + "F", + "E", + "W", + "UP", + "YTT", + "ASYNC", + "TRIO", + "ICN", + "LOG", + "SLOT", + "PD", + "PGH", + "TRY004", + "TRY2", + "FLY", + "NPY", + "AIR", +] ignore = ["E501", "E722", "F821"] # Allow autofix for all enabled rules (when `--fix`) is provided. fixable = ["ALL"] unfixable = [] - preview = true -per-file-ignores = {} +per-file-ignores = {} \ No newline at end of file From da4c9a22c8b63bf7658f2ccd88e2a419af75380e Mon Sep 17 00:00:00 2001 From: DefectDojo release bot Date: Wed, 17 Apr 2024 20:28:56 +0000 Subject: [PATCH 028/138] Update versions in application files --- components/package.json | 2 +- dojo/__init__.py | 2 +- helm/defectdojo/Chart.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/package.json b/components/package.json index 4beb9ece64..41e9d22009 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "defectdojo", - "version": "2.33.4", + "version": "2.34.0-dev", "license" : "BSD-3-Clause", "private": true, "dependencies": { diff --git a/dojo/__init__.py b/dojo/__init__.py index 83a61e0936..4758913441 100644 --- a/dojo/__init__.py +++ b/dojo/__init__.py @@ -4,6 +4,6 @@ # Django starts so that shared_task will use this app. from .celery import app as celery_app # noqa: F401 -__version__ = '2.33.4' +__version__ = '2.34.0-dev' __url__ = 'https://github.com/DefectDojo/django-DefectDojo' __docs__ = 'https://documentation.defectdojo.com' diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index 54c0e5975a..0896140174 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 -appVersion: "2.33.4" +appVersion: "2.34.0-dev" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.122 +version: 1.6.123-dev icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap From 98a435d4ca5f5d51e0573379a0be260e7a0323a6 Mon Sep 17 00:00:00 2001 From: DefectDojo Date: Wed, 17 Apr 2024 20:30:42 +0000 Subject: [PATCH 029/138] Update helm lock file Signed-off-by: DefectDojo --- helm/defectdojo/Chart.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/helm/defectdojo/Chart.lock b/helm/defectdojo/Chart.lock index dbd032c670..d2ab89de70 100644 --- a/helm/defectdojo/Chart.lock +++ b/helm/defectdojo/Chart.lock @@ -13,6 +13,6 @@ dependencies: version: 11.16.2 - name: redis repository: https://charts.bitnami.com/bitnami - version: 19.1.0 -digest: sha256:682c2bf2aa7e86d0207b2c20d05212aa262d37ba80309d8aefe14884326ae93c -generated: "2024-04-15T18:49:42.741358115Z" + version: 19.1.1 +digest: sha256:c8b6e1a32ee3479aada4224cfe230e93c755688dd0be021cf82081e62617e11a +generated: "2024-04-17T20:30:33.619138998Z" From 0127e4074f0eb5adbea49430ce36d7e5e5d0f745 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 21:36:29 -0500 Subject: [PATCH 030/138] Update gcr.io/cloudsql-docker/gce-proxy Docker tag from 1.34.1 to v1.35.1 (helm/defectdojo/values.yaml) (#9933) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- helm/defectdojo/values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm/defectdojo/values.yaml b/helm/defectdojo/values.yaml index 0591e45ca1..84fbba4a55 100644 --- a/helm/defectdojo/values.yaml +++ b/helm/defectdojo/values.yaml @@ -457,7 +457,7 @@ cloudsql: image: # set repo and image tag of gce-proxy repository: gcr.io/cloudsql-docker/gce-proxy - tag: 1.34.1 + tag: 1.35.1 pullPolicy: IfNotPresent # set CloudSQL instance: 'project:zone:instancename' instance: "" From 0b2edab871f6d408983fcaf889b301be264dc759 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 21:41:57 -0500 Subject: [PATCH 031/138] chore(deps): update peaceiris/actions-gh-pages action from v3 to v4 (.github/workflows/gh-pages.yml) (#9897) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/gh-pages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index 84d7800bed..206c895717 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -58,7 +58,7 @@ jobs: - run: ls -l ./docs/public/* - name: Deploy - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@v4 with: # publishes to the `gh-pages` branch by default github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./docs/public From a5c77fc5256267bd9809fc67af87e671e7be8d65 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 21:42:32 -0500 Subject: [PATCH 032/138] Update peaceiris/actions-hugo action from v2 to v3 (.github/workflows/gh-pages.yml) (#9863) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/gh-pages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index 206c895717..e0ebabe2ec 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Setup Hugo - uses: peaceiris/actions-hugo@v2 + uses: peaceiris/actions-hugo@v3 with: hugo-version: '0.81.0' extended: true From 05c32059bbca58c806648e0b65745530644ac0a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 22:00:11 -0500 Subject: [PATCH 033/138] Bump coverage from 7.4.1 to 7.4.4 (#9943) Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.4.1 to 7.4.4. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.4.1...7.4.4) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 55397ddcaf..cc9d2024df 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ asteval==0.9.31 bleach==6.1.0 bleach[css] celery==5.3.6 -coverage==7.4.1 +coverage==7.4.4 defusedxml==0.7.1 django_celery_results==2.5.1 django-auditlog==2.3.0 From 7b23b643a53946f14e565db7a0ba28c1fc357cb5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 22:01:39 -0500 Subject: [PATCH 034/138] Bump redis from 5.0.1 to 5.0.3 (#9951) Bumps [redis](https://github.com/redis/redis-py) from 5.0.1 to 5.0.3. - [Release notes](https://github.com/redis/redis-py/releases) - [Changelog](https://github.com/redis/redis-py/blob/master/CHANGES) - [Commits](https://github.com/redis/redis-py/compare/v5.0.1...v5.0.3) --- updated-dependencies: - dependency-name: redis dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index cc9d2024df..97fcfb22ed 100644 --- a/requirements.txt +++ b/requirements.txt @@ -39,7 +39,7 @@ psycopg2-binary==2.9.9 cryptography==42.0.4 python-dateutil==2.8.2 pytz==2024.1 -redis==5.0.1 +redis==5.0.3 requests==2.31.0 sqlalchemy==2.0.25 # Required by Celery broker transport urllib3==1.26.18 From 040aef531b7175da798c1d95a4d086e3a2d577eb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 22:02:28 -0500 Subject: [PATCH 035/138] Bump pillow from 10.2.0 to 10.3.0 (#9950) Bumps [pillow](https://github.com/python-pillow/Pillow) from 10.2.0 to 10.3.0. - [Release notes](https://github.com/python-pillow/Pillow/releases) - [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst) - [Commits](https://github.com/python-pillow/Pillow/compare/10.2.0...10.3.0) --- updated-dependencies: - dependency-name: pillow dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 97fcfb22ed..0e4499d5ee 100644 --- a/requirements.txt +++ b/requirements.txt @@ -34,7 +34,7 @@ lxml==5.1.0 Markdown==3.5.2 mysqlclient==2.1.1 openpyxl==3.1.2 -Pillow==10.2.0 # required by django-imagekit +Pillow==10.3.0 # required by django-imagekit psycopg2-binary==2.9.9 cryptography==42.0.4 python-dateutil==2.8.2 From 1208cec40bcf1aeb7384d24550ae558958160092 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 22:03:16 -0500 Subject: [PATCH 036/138] Bump cvss from 3.0 to 3.1 (#9949) Bumps [cvss](https://github.com/RedHatProductSecurity/cvss) from 3.0 to 3.1. - [Release notes](https://github.com/RedHatProductSecurity/cvss/releases) - [Commits](https://github.com/RedHatProductSecurity/cvss/compare/v3.0...v3.1) --- updated-dependencies: - dependency-name: cvss dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 0e4499d5ee..91b916d46a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -64,7 +64,7 @@ vcrpy==6.0.1 vcrpy-unittest==0.1.7 django-tagulous==1.3.3 PyJWT==2.8.0 -cvss==3.0 +cvss==3.1 django-fieldsignals==0.7.0 hyperlink==21.0.0 django-test-migrations==1.3.0 From a447aec3fce334bc7ed011d7c6c6ce1a9f18c5bc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 22:08:42 -0500 Subject: [PATCH 037/138] Bump jira from 3.6.0 to 3.8.0 (#9947) Bumps [jira](https://github.com/pycontribs/jira) from 3.6.0 to 3.8.0. - [Release notes](https://github.com/pycontribs/jira/releases) - [Changelog](https://github.com/pycontribs/jira/blob/main/RELEASE.md) - [Commits](https://github.com/pycontribs/jira/compare/3.6.0...3.8.0) --- updated-dependencies: - dependency-name: jira dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 91b916d46a..99632512b8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -28,7 +28,7 @@ Django==4.1.13 djangorestframework==3.14.0 html2text==2020.1.16 humanize==4.9.0 -jira==3.6.0 +jira==3.8.0 PyGithub==1.58.2 lxml==5.1.0 Markdown==3.5.2 From 5c52dd7b64e58c2c47348f5ec713d2db8e4fe9be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 22:30:55 -0500 Subject: [PATCH 038/138] Bump json-log-formatter from 0.5.2 to 1.0 (#9959) Bumps [json-log-formatter](https://github.com/marselester/json-log-formatter) from 0.5.2 to 1.0. - [Release notes](https://github.com/marselester/json-log-formatter/releases) - [Commits](https://github.com/marselester/json-log-formatter/compare/v0.5.2...v1.0.0) --- updated-dependencies: - dependency-name: json-log-formatter dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 99632512b8..1e8fa9be67 100644 --- a/requirements.txt +++ b/requirements.txt @@ -56,7 +56,7 @@ python-gitlab==4.4.0 cpe==1.2.1 packageurl-python==0.13.4 django-crum==0.7.9 -JSON-log-formatter==0.5.2 +JSON-log-formatter==1.0 django-split-settings==1.2.0 django-debug-toolbar==4.3.0 django-debug-toolbar-request-history==0.1.4 From bf07981b39d0f47ed9505420c9c8649b2eca60c4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 22:33:32 -0500 Subject: [PATCH 039/138] Update rabbitmq:3.13.1-alpine Docker digest from 3.13.1 to 3.13.1-alpine (docker-compose.yml) (#9927) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 478a67fd83..b4c3886c9b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -148,7 +148,7 @@ services: volumes: - defectdojo_postgres:/var/lib/postgresql/data rabbitmq: - image: rabbitmq:3.13.1-alpine@sha256:cd1b0e16575fd9885a03f2ae3b7d0fb4ee77b215a1127cf086397f7a55e8912b + image: rabbitmq:3.13.1-alpine@sha256:4bcec9fde55c9baf6c73a6969bd9070fb109ced1a5daa9679eb90c8145940809 profiles: - mysql-rabbitmq - postgres-rabbitmq From 0f7b70c9948e7cd8fb1d6e3b1df4e89cd7a8938e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 22:37:32 -0500 Subject: [PATCH 040/138] Update azure/setup-helm action from v4.1.0 to v4.2.0 (.github/workflows/test-helm-chart.yml) (#9928) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/test-helm-chart.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-helm-chart.yml b/.github/workflows/test-helm-chart.yml index 5fcf845076..5bf2016932 100644 --- a/.github/workflows/test-helm-chart.yml +++ b/.github/workflows/test-helm-chart.yml @@ -20,7 +20,7 @@ jobs: fetch-depth: 0 - name: Set up Helm - uses: azure/setup-helm@v4.1.0 + uses: azure/setup-helm@v4.2.0 - uses: actions/setup-python@v5 with: From 627327507383d16bb59505684467b8ba41a1478e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 23:12:27 -0500 Subject: [PATCH 041/138] Bump lxml from 5.1.0 to 5.2.1 (#9946) Bumps [lxml](https://github.com/lxml/lxml) from 5.1.0 to 5.2.1. - [Release notes](https://github.com/lxml/lxml/releases) - [Changelog](https://github.com/lxml/lxml/blob/master/CHANGES.txt) - [Commits](https://github.com/lxml/lxml/compare/lxml-5.1.0...lxml-5.2.1) --- updated-dependencies: - dependency-name: lxml dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 1e8fa9be67..bc4f8bba3f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -30,7 +30,7 @@ html2text==2020.1.16 humanize==4.9.0 jira==3.8.0 PyGithub==1.58.2 -lxml==5.1.0 +lxml==5.2.1 Markdown==3.5.2 mysqlclient==2.1.1 openpyxl==3.1.2 From 2598f0e79cd7aa2258e2ec4f7f4ef1ef0f23bd00 Mon Sep 17 00:00:00 2001 From: dogboat Date: Sun, 21 Apr 2024 20:23:38 -0400 Subject: [PATCH 042/138] add-group-members-wording Changing the wording on group membership addition pages to remove the word "Some" to be more formal (#9965) --- dojo/templates/dojo/new_group_member.html | 2 +- dojo/templates/dojo/new_group_member_user.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dojo/templates/dojo/new_group_member.html b/dojo/templates/dojo/new_group_member.html index 405a7ebcd4..426b5f37b4 100644 --- a/dojo/templates/dojo/new_group_member.html +++ b/dojo/templates/dojo/new_group_member.html @@ -5,7 +5,7 @@ } {% endblock %} {% block content %} -

Add Some Group Members

+

Add Group Members

{% csrf_token %} {% include "dojo/form_fields.html" with form=form %}
diff --git a/dojo/templates/dojo/new_group_member_user.html b/dojo/templates/dojo/new_group_member_user.html index 339cbfcd94..d792881e66 100644 --- a/dojo/templates/dojo/new_group_member_user.html +++ b/dojo/templates/dojo/new_group_member_user.html @@ -6,7 +6,7 @@ } {% endblock %} {% block content %} -

{% trans "Add Some Group Members" %}

+

{% trans "Add Group Members" %}

{% csrf_token %} {% include "dojo/form_fields.html" with form=form %}
From f8beb8935d2495a62c806d130f59d030ec893990 Mon Sep 17 00:00:00 2001 From: dogboat Date: Sun, 21 Apr 2024 20:24:02 -0400 Subject: [PATCH 043/138] view-finding-footer-fix Close a div so footer displays properly (#9968) --- dojo/templates/dojo/view_finding.html | 1 + 1 file changed, 1 insertion(+) diff --git a/dojo/templates/dojo/view_finding.html b/dojo/templates/dojo/view_finding.html index 5b2a7cc081..5c0b4541be 100755 --- a/dojo/templates/dojo/view_finding.html +++ b/dojo/templates/dojo/view_finding.html @@ -1167,6 +1167,7 @@

Credential
ProTip! Type e to edit any finding, p and n to navigate to the previous or next finding.
+

{% endblock %} {% block postscript %} {{ block.super }} From 7be3690e48c5f8b4cea4924053dfd4f5c0716f5d Mon Sep 17 00:00:00 2001 From: dogboat Date: Sun, 21 Apr 2024 20:24:38 -0400 Subject: [PATCH 044/138] Update dojo_sort template tag to properly handle querystrings with keys with multiple values (#9969) * sorting-filtered-findings-severity Update dojo_sort template tag to use QueryDict.urlencode() rather than urllib.parse.urlencode() to properly handle querystrings that have instances of multiple values for a single key * scorting-filtered-findings-severity Fix comment --- dojo/templatetags/navigation_tags.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dojo/templatetags/navigation_tags.py b/dojo/templatetags/navigation_tags.py index e446dd842d..4014885bbd 100644 --- a/dojo/templatetags/navigation_tags.py +++ b/dojo/templatetags/navigation_tags.py @@ -1,7 +1,6 @@ from django import template from django.utils.safestring import mark_safe as safe from django.utils.html import escape -from urllib.parse import urlencode from django.utils.translation import gettext as _ from dojo.authorization.roles_permissions import Permissions @@ -65,7 +64,8 @@ def dojo_sort(request, display='Name', value='title', default=None): icon += ' dd-sort">' dict_ = request.GET.copy() dict_[field] = value - link = f'{_(display)} {icon}' + # QueryDict.urlencode() used here to properly handle cases when keys have multiple values + link = f'{_(display)} {icon}' return safe(link) From 5b277a5a21dc97e7afe33df6f04f720ab61c1b30 Mon Sep 17 00:00:00 2001 From: dogboat Date: Sun, 21 Apr 2024 20:25:07 -0400 Subject: [PATCH 045/138] test-findings-colvis Add noVis settings for bulk edit checkbox and action links columns to the Findings listing on the Test view so they don't appear in the column visibility options (#9971) --- dojo/templates/dojo/view_test.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dojo/templates/dojo/view_test.html b/dojo/templates/dojo/view_test.html index 11e75510b4..61015f2521 100644 --- a/dojo/templates/dojo/view_test.html +++ b/dojo/templates/dojo/view_test.html @@ -1681,6 +1681,10 @@

"orderable": false, "targets": [0] }, + { + targets: [0, 1], + className: 'noVis' + }, { targets: 'severity-sort', orderDataType: 'severity-asc' From 902fb2ffe256ffa0f3756688695a978c7e19e51b Mon Sep 17 00:00:00 2001 From: DefectDojo release bot Date: Mon, 22 Apr 2024 14:56:53 +0000 Subject: [PATCH 046/138] Update versions in application files --- components/package.json | 2 +- dojo/__init__.py | 2 +- helm/defectdojo/Chart.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/package.json b/components/package.json index 336f73dfe7..41e9d22009 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "defectdojo", - "version": "2.33.5", + "version": "2.34.0-dev", "license" : "BSD-3-Clause", "private": true, "dependencies": { diff --git a/dojo/__init__.py b/dojo/__init__.py index c2f8acb400..4758913441 100644 --- a/dojo/__init__.py +++ b/dojo/__init__.py @@ -4,6 +4,6 @@ # Django starts so that shared_task will use this app. from .celery import app as celery_app # noqa: F401 -__version__ = '2.33.5' +__version__ = '2.34.0-dev' __url__ = 'https://github.com/DefectDojo/django-DefectDojo' __docs__ = 'https://documentation.defectdojo.com' diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index 276ec6a4d5..f78f941d41 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 -appVersion: "2.33.5" +appVersion: "2.34.0-dev" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.123 +version: 1.6.124-dev icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap From 6c9e9311ad7e846837f5419d4c12df549bd24ba8 Mon Sep 17 00:00:00 2001 From: DefectDojo Date: Mon, 22 Apr 2024 15:02:32 +0000 Subject: [PATCH 047/138] Update helm lock file Signed-off-by: DefectDojo --- helm/defectdojo/Chart.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/helm/defectdojo/Chart.lock b/helm/defectdojo/Chart.lock index d2ab89de70..0cd1eabf96 100644 --- a/helm/defectdojo/Chart.lock +++ b/helm/defectdojo/Chart.lock @@ -13,6 +13,6 @@ dependencies: version: 11.16.2 - name: redis repository: https://charts.bitnami.com/bitnami - version: 19.1.1 -digest: sha256:c8b6e1a32ee3479aada4224cfe230e93c755688dd0be021cf82081e62617e11a -generated: "2024-04-17T20:30:33.619138998Z" + version: 19.1.2 +digest: sha256:175b6a0625ae97af141faf363d504b0bccbcbd06bb5c01d014e7e3c82b78a0c8 +generated: "2024-04-22T15:02:23.837536991Z" From babc97d3459944315b04b8783ec78c902c6a080c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 13:27:42 -0500 Subject: [PATCH 048/138] Update dependency ruff from 0.3.7 to v0.4.1 (requirements-lint.txt) (#9974) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- requirements-lint.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-lint.txt b/requirements-lint.txt index bbd63c00ea..d0bc2a530a 100644 --- a/requirements-lint.txt +++ b/requirements-lint.txt @@ -1 +1 @@ -ruff==0.3.7 \ No newline at end of file +ruff==0.4.1 \ No newline at end of file From b17b205ca20915e1f2a18bc744c59f4949858503 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 13:28:03 -0500 Subject: [PATCH 049/138] Update redis:7.2.4-alpine Docker digest from 7.2.4 to 7.2.4-alpine (docker-compose.yml) (#9973) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index b4c3886c9b..76df3c8541 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -155,7 +155,7 @@ services: volumes: - defectdojo_rabbitmq:/var/lib/rabbitmq redis: - image: redis:7.2.4-alpine@sha256:7635b0bfdd7dd8552b4b31d6541fef07b734614045b45a52fd5cc27c9dada9e2 + image: redis:7.2.4-alpine@sha256:a40e29800d387e3cf9431902e1e7a362e4d819233d68ae39380532c3310091ac profiles: - mysql-redis - postgres-redis From c0f06475c67644545752881cbfa7ec663ae63e96 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 13:28:33 -0500 Subject: [PATCH 050/138] Update postgres:16.2-alpine Docker digest from 16.2 to 16.2-alpine (docker-compose.yml) (#9972) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 76df3c8541..69319da2c2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -137,7 +137,7 @@ services: volumes: - defectdojo_data:/var/lib/mysql postgres: - image: postgres:16.2-alpine@sha256:1d74239810c19ed0dbb317acae40974e673865b2d565a0d369e206159d483957 + image: postgres:16.2-alpine@sha256:951bfda460300925caa3949eaa092ba022e9aec191bbea9056a39e2382260b27 profiles: - postgres-rabbitmq - postgres-redis From 729920a3fe74fa41e4cffc2174eba839ad091dae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 13:30:56 -0500 Subject: [PATCH 051/138] Bump nginx from 1.25.4-alpine to 1.25.5-alpine (#9984) Bumps nginx from 1.25.4-alpine to 1.25.5-alpine. --- updated-dependencies: - dependency-name: nginx dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Dockerfile.nginx-alpine | 2 +- Dockerfile.nginx-debian | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile.nginx-alpine b/Dockerfile.nginx-alpine index 872fdaee78..c2ba916d1e 100644 --- a/Dockerfile.nginx-alpine +++ b/Dockerfile.nginx-alpine @@ -140,7 +140,7 @@ COPY manage.py ./ COPY dojo/ ./dojo/ RUN env DD_SECRET_KEY='.' python3 manage.py collectstatic --noinput && true -FROM nginx:1.25.4-alpine@sha256:31bad00311cb5eeb8a6648beadcf67277a175da89989f14727420a80e2e76742 +FROM nginx:1.25.5-alpine@sha256:7bd88800d8c18d4f73feeee25e04fcdbeecfc5e0a2b7254a90f4816bb67beadd ARG uid=1001 ARG appuser=defectdojo COPY --from=collectstatic /app/static/ /usr/share/nginx/html/static/ diff --git a/Dockerfile.nginx-debian b/Dockerfile.nginx-debian index b11a68fd11..07379aa170 100644 --- a/Dockerfile.nginx-debian +++ b/Dockerfile.nginx-debian @@ -75,7 +75,7 @@ COPY dojo/ ./dojo/ RUN env DD_SECRET_KEY='.' python3 manage.py collectstatic --noinput && true -FROM nginx:1.25.4-alpine@sha256:31bad00311cb5eeb8a6648beadcf67277a175da89989f14727420a80e2e76742 +FROM nginx:1.25.5-alpine@sha256:7bd88800d8c18d4f73feeee25e04fcdbeecfc5e0a2b7254a90f4816bb67beadd ARG uid=1001 ARG appuser=defectdojo COPY --from=collectstatic /app/static/ /usr/share/nginx/html/static/ From c713d0d78f21d7eafe4a78e00fee55eaedddc9a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 13:31:27 -0500 Subject: [PATCH 052/138] Bump openapitools/openapi-generator-cli from v7.4.0 to v7.5.0 (#9983) Bumps openapitools/openapi-generator-cli from v7.4.0 to v7.5.0. --- updated-dependencies: - dependency-name: openapitools/openapi-generator-cli dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Dockerfile.integration-tests-debian | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile.integration-tests-debian b/Dockerfile.integration-tests-debian index 545e4e3ef7..f254ae9f99 100644 --- a/Dockerfile.integration-tests-debian +++ b/Dockerfile.integration-tests-debian @@ -1,7 +1,7 @@ # code: language=Dockerfile -FROM openapitools/openapi-generator-cli:v7.4.0@sha256:579832bed49ea6c275ce2fb5f2d515f5b03d2b6243f3c80fa8430e4f5a770e9a as openapitools +FROM openapitools/openapi-generator-cli:v7.5.0@sha256:cdf11948948de9c21c6035de47dd5fc73c1651c8ba2ea0a4b86a527608ef52a9 as openapitools FROM python:3.11.4-slim-bullseye@sha256:40319d0a897896e746edf877783ef39685d44e90e1e6de8d964d0382df0d4952 as build WORKDIR /app RUN \ From f82220b3e9c25b8e4e9a8126950d47b38ba69f57 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 13:33:03 -0500 Subject: [PATCH 053/138] Bump python-dateutil from 2.8.2 to 2.9.0.post0 (#9982) Bumps [python-dateutil](https://github.com/dateutil/dateutil) from 2.8.2 to 2.9.0.post0. - [Release notes](https://github.com/dateutil/dateutil/releases) - [Changelog](https://github.com/dateutil/dateutil/blob/master/NEWS) - [Commits](https://github.com/dateutil/dateutil/compare/2.8.2...2.9.0.post0) --- updated-dependencies: - dependency-name: python-dateutil dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index bc4f8bba3f..5ca5571b10 100644 --- a/requirements.txt +++ b/requirements.txt @@ -37,7 +37,7 @@ openpyxl==3.1.2 Pillow==10.3.0 # required by django-imagekit psycopg2-binary==2.9.9 cryptography==42.0.4 -python-dateutil==2.8.2 +python-dateutil==2.9.0.post0 pytz==2024.1 redis==5.0.3 requests==2.31.0 From 59390e64628008d6fd809ff1ecd56312484b0485 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 13:33:48 -0500 Subject: [PATCH 054/138] Bump vobject from 0.9.6.1 to 0.9.7 (#9978) Bumps [vobject](https://github.com/py-vobject/vobject) from 0.9.6.1 to 0.9.7. - [Release notes](https://github.com/py-vobject/vobject/releases) - [Commits](https://github.com/py-vobject/vobject/compare/0.9.6.1...v0.9.7) --- updated-dependencies: - dependency-name: vobject dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 5ca5571b10..6fde881124 100644 --- a/requirements.txt +++ b/requirements.txt @@ -44,7 +44,7 @@ requests==2.31.0 sqlalchemy==2.0.25 # Required by Celery broker transport urllib3==1.26.18 uWSGI==2.0.23 -vobject==0.9.6.1 +vobject==0.9.7 whitenoise==5.2.0 titlecase==2.4.1 social-auth-app-django==5.4.0 From f895d7b403bee9e4d4c830997735451686e696b7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 13:34:59 -0500 Subject: [PATCH 055/138] Bump drf-spectacular-sidecar from 2024.3.4 to 2024.4.1 (#9976) Bumps [drf-spectacular-sidecar](https://github.com/tfranzel/drf-spectacular-sidecar) from 2024.3.4 to 2024.4.1. - [Commits](https://github.com/tfranzel/drf-spectacular-sidecar/compare/2024.3.4...2024.4.1) --- updated-dependencies: - dependency-name: drf-spectacular-sidecar dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 6fde881124..3252d044ce 100644 --- a/requirements.txt +++ b/requirements.txt @@ -70,7 +70,7 @@ hyperlink==21.0.0 django-test-migrations==1.3.0 djangosaml2==1.9.1 drf-spectacular==0.27.1 -drf-spectacular-sidecar==2024.3.4 +drf-spectacular-sidecar==2024.4.1 django-ratelimit==4.1.0 argon2-cffi==23.1.0 blackduck==1.1.0 From 3a25a4428355ffbcb7cd3f68dacb36ae1729d93a Mon Sep 17 00:00:00 2001 From: kiblik Date: Mon, 22 Apr 2024 20:35:46 +0200 Subject: [PATCH 056/138] Helm postgresql: Upgrade image (#9966) --- helm/defectdojo/values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm/defectdojo/values.yaml b/helm/defectdojo/values.yaml index 84fbba4a55..055bea24ef 100644 --- a/helm/defectdojo/values.yaml +++ b/helm/defectdojo/values.yaml @@ -369,7 +369,7 @@ mysql: postgresql: enabled: true image: - tag: 11.16.0-debian-11-r9 + tag: 11.22.0-debian-11-r4 auth: username: defectdojo password: "" From 65bc290294cd1a1bb4074d04c9e804047aa5398f Mon Sep 17 00:00:00 2001 From: Harold Blankenship <36673698+hblankenship@users.noreply.github.com> Date: Mon, 22 Apr 2024 13:36:46 -0500 Subject: [PATCH 057/138] Make the number of request/response pairs returned by the API configurable (#9967) * limit req response via setting * add unittest * update running test documentation * also must do here * fix linting, add urls.py * trailing space in a comment... * switch back to finding - different test uses it * change test data to not break * reset data, use my own * Update dojo/settings/settings.dist.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> --------- Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> --- dojo/api_v2/serializers.py | 5 +- dojo/api_v2/views.py | 6 +- dojo/fixtures/unit_limit_reqresp.json | 376 +++++++++++ dojo/settings/settings.dist.py | 4 +- dojo/urls.py | 2 +- readme-docs/DOCKER.md | 14 +- unittests/scans/burp_api/many_reqresp.json | 734 +++++++++++++++++++++ unittests/test_apiv2_limit_reqresp.py | 42 ++ 8 files changed, 1177 insertions(+), 6 deletions(-) create mode 100644 dojo/fixtures/unit_limit_reqresp.json create mode 100644 unittests/scans/burp_api/many_reqresp.json create mode 100644 unittests/test_apiv2_limit_reqresp.py diff --git a/dojo/api_v2/serializers.py b/dojo/api_v2/serializers.py index 795a69eac4..d743b1c597 100644 --- a/dojo/api_v2/serializers.py +++ b/dojo/api_v2/serializers.py @@ -1806,8 +1806,11 @@ def build_relational_field(self, field_name, relation_info): @extend_schema_field(BurpRawRequestResponseSerializer) def get_request_response(self, obj): - # burp_req_resp = BurpRawRequestResponse.objects.filter(finding=obj) + # Not necessarily Burp scan specific - these are just any request/response pairs burp_req_resp = obj.burprawrequestresponse_set.all() + var = settings.MAX_REQRESP_FROM_API + if var > -1: + burp_req_resp = burp_req_resp[:var] burp_list = [] for burp in burp_req_resp: request = burp.get_request() diff --git a/dojo/api_v2/views.py b/dojo/api_v2/views.py index ff73d2f01f..c130a735f6 100644 --- a/dojo/api_v2/views.py +++ b/dojo/api_v2/views.py @@ -1004,8 +1004,12 @@ def request_response(self, request, pk=None): return Response( burps.errors, status=status.HTTP_400_BAD_REQUEST ) - + # Not necessarily Burp scan specific - these are just any request/response pairs burp_req_resp = BurpRawRequestResponse.objects.filter(finding=finding) + var = settings.MAX_REQRESP_FROM_API + if var > -1: + burp_req_resp = burp_req_resp[:var] + burp_list = [] for burp in burp_req_resp: request = burp.get_request() diff --git a/dojo/fixtures/unit_limit_reqresp.json b/dojo/fixtures/unit_limit_reqresp.json new file mode 100644 index 0000000000..360156f533 --- /dev/null +++ b/dojo/fixtures/unit_limit_reqresp.json @@ -0,0 +1,376 @@ +[ + { + "pk": 1, + "model": "dojo.development_environment", + "fields": { + "name": "Development" + } + }, + { + "pk": 1, + "model": "auth.user", + "fields": { + "username": "admin", + "first_name": "", + "last_name": "", + "is_active": true, + "is_superuser": true, + "is_staff": true, + "last_login": "2018-04-17T06:00:43.171Z", + "groups": [], + "user_permissions": [], + "password": "pbkdf2_sha256$36000$sT96yObJtsFk$F9YAJimsQqBXnff/QGLNTv100qhCNl/23hoBuNtSNZU=", + "email": "", + "date_joined": "2018-04-13T07:58:59.861Z" + } + }, + { + "pk": "548afd6fab3bea9794a41b31da0e9404f733e222", + "model": "authtoken.token", + "fields": { + "user": 1, + "created": "2018-04-16T06:54:35.937Z" + } + }, + { + "pk": 2, + "model": "auth.user", + "fields": { + "username": "user1", + "first_name": "", + "last_name": "", + "is_active": true, + "is_superuser": false, + "is_staff": false, + "last_login": null, + "groups": [], + "user_permissions": [], + "password": "pbkdf2_sha256$36000$pe8Ff8HrBPac$Lb3ee6/R9z/aL9nM+D2AXWTpIt9Pa9kcLueXxYNy1ZY=", + "email": "", + "date_joined": "2018-04-13T07:59:51.527Z" + } + }, + { + "pk": 2, + "model": "dojo.product_type", + "fields": { + "critical_product": true, + "name": "ebooks", + "key_product": false + } + }, + { + "pk": 2, + "model": "dojo.product", + "fields": { + "updated": null, + "prod_type": 2, + "name": "Security How-to", + "created": null, + "technical_contact": 2, + "product_manager": 2, + "team_manager": 2, + "tid": 0, + "description": "test product" + } + },{ + "pk": 5, + "model": "dojo.engagement", + "fields": { + "product": 2, + "pen_test": true, + "report_type": null, + "first_contacted": null, + "tmodel_path": "none", + "risk_acceptance": [], + "lead": 1, + "version": null, + "progress": "threat_model", + "threat_model": true, + "test_strategy": null, + "status": "Completed", + "updated": null, + "description": "test Engagement", + "reason": null, + "requester": null, + "active": true, + "done_testing": false, + "target_end": "2018-04-12", + "name": "April monthly engagement2", + "check_list": true, + "target_start": "2018-04-12", + "api_test": true, + "deduplication_on_engagement": true + } + }, +{ + "pk": 5, + "model": "dojo.test", + "fields": { + "lead": null, + "estimated_time": "00:00:00", + "test_type": 1, + "scan_type": "ZAP Scan", + "engagement": 5, + "environment": 1, + "target_start": "2017-12-01T00:00:00Z", + "notes": [], + "percent_complete": 100, + "actual_time": "00:00:00", + "target_end": "2017-12-10T00:00:00Z" + } + },{ + "pk": 8, + "model": "dojo.finding", + "fields": { + "last_reviewed_by": null, + "reviewers": [], + "static_finding": false, + "date": "2017-12-31", + "references": "", + "files": [], + "payload": null, + "under_defect_review": false, + "impact": "High", + "false_p": false, + "verified": false, + "severity": "High", + "title": "DUMMY FINDING WITH REQRESP", + "param": null, + "created": "2017-12-01T00:00:00Z", + "duplicate": false, + "mitigation": "MITIGATION", + "found_by": [ + 1 + ], + "numerical_severity": "S0", + "test": 5, + "out_of_scope": false, + "cwe": 1, + "file_path": "", + "duplicate_finding": null, + "description": "TEST finding", + "mitigated_by": null, + "reporter": 2, + "mitigated": null, + "active": false, + "line": 100, + "under_review": false, + "defect_review_requested_by": 2, + "review_requested_by": 2, + "thread_id": 1, + "url": "http://www.example.com", + "notes": [], + "dynamic_finding": false, + "hash_code": "c89d25e445b088ba339908f68e15e3177b78d22f3039d1bfea51c4be251bf4e0", + "last_reviewed": null + } + },{ + "pk": 8, + "model": "dojo.finding", + "fields": { + "last_reviewed_by": null, + "reviewers": [], + "static_finding": false, + "date": "2017-12-31", + "references": "", + "files": [], + "payload": null, + "under_defect_review": false, + "impact": "High", + "false_p": false, + "verified": false, + "severity": "High", + "title": "DUMMY FINDING WITH REQRESP", + "param": null, + "created": "2017-12-01T00:00:00Z", + "duplicate": false, + "mitigation": "MITIGATION", + "found_by": [ + 1 + ], + "numerical_severity": "S0", + "test": 5, + "out_of_scope": false, + "cwe": 1, + "file_path": "", + "duplicate_finding": null, + "description": "TEST finding", + "mitigated_by": null, + "reporter": 2, + "mitigated": null, + "active": false, + "line": 100, + "under_review": false, + "defect_review_requested_by": 2, + "review_requested_by": 2, + "thread_id": 1, + "url": "http://www.example.com", + "notes": [], + "dynamic_finding": false, + "hash_code": "c89d25e445b088ba339908f68e15e3177b78d22f3039d1bfea51c4be251bf4e0", + "last_reviewed": null + } + },{ + "pk": 123, + "model": "dojo.burprawrequestresponse", + "fields": { + "finding": 8, + "burpRequestBase64": "UjBWVUlDOWliMlJuWldsMEwyeHZaMmx1TG1wemNDQklWRlJRTHpFdU1RMEtTRzl6ZERvZ2JHOWpZV3hvYjNOME9qZzRPRGdOQ2xWelpYSXRRV2RsYm5RNklFMXZlbWxzYkdFdk5TNHdJQ2hOWVdOcGJuUnZjMmc3SUVsdWRHVnNJRTFoWXlCUFV5QllJREV3TGpFeE95Qnlkam8wTnk0d0tTQkhaV05yYnk4eU1ERXdNREV3TVNCR2FYSmxabTk0THpRM0xqQU5Da0ZqWTJWd2REb2dkR1Y0ZEM5b2RHMXNMR0Z3Y0d4cFkyRjBhVzl1TDNob2RHMXNLM2h0YkN4aGNIQnNhV05oZEdsdmJpOTRiV3c3Y1Qwd0xqa3NLaThxTzNFOU1DNDREUXBCWTJObGNIUXRUR0Z1WjNWaFoyVTZJR1Z1TFZWVExHVnVPM0U5TUM0MURRcEJZMk5sY0hRdFJXNWpiMlJwYm1jNklHZDZhWEFzSUdSbFpteGhkR1VOQ2xKbFptVnlaWEk2SUdoMGRIQTZMeTlzYjJOaGJHaHZjM1E2T0RnNE9DOWliMlJuWldsMEx3MEtRMjl2YTJsbE9pQktVMFZUVTBsUFRrbEVQVFpGT1RVM04wRXhOa0pCUXpZeE9URXpSRVU1TjBFNE9EZEJSRFl3TWpjMURRcERiMjV1WldOMGFXOXVPaUJqYkc5elpRMEtEUW89", + "burpResponseBase64": "U0ZSVVVDOHhMakVnTWpBd0lBMEtVMlZ5ZG1WeU9pQkJjR0ZqYUdVdFEyOTViM1JsTHpFdU1RMEtRMjl1ZEdWdWRDMVVlWEJsT2lCMFpYaDBMMmgwYld3N1kyaGhjbk5sZEQxSlUwOHRPRGcxT1MweERRcERiMjUwWlc1MExVeGxibWQwYURvZ01qUTJNZzBLUkdGMFpUb2dVMkYwTENBeU55QkJkV2NnTWpBeE5pQXdNam93T0RvMU55QkhUVlFOQ2tOdmJtNWxZM1JwYjI0NklHTnNiM05sRFFvTkNnMEtEUW9OQ2cwS0Nnb0tDandoUkU5RFZGbFFSU0JJVkUxTUlGQlZRa3hKUXlBaUxTOHZWek5ETHk5RVZFUWdTRlJOVENBekxqSXZMMFZPSWo0S1BHaDBiV3crQ2p4b1pXRmtQZ284ZEdsMGJHVStWR2hsSUVKdlpHZGxTWFFnVTNSdmNtVThMM1JwZEd4bFBnbzhiR2x1YXlCb2NtVm1QU0p6ZEhsc1pTNWpjM01pSUhKbGJEMGljM1I1YkdWemFHVmxkQ0lnZEhsd1pUMGlkR1Y0ZEM5amMzTWlJQzgrQ2p4elkzSnBjSFFnZEhsd1pUMGlkR1Y0ZEM5cVlYWmhjMk55YVhCMElpQnpjbU05SWk0dmFuTXZkWFJwYkM1cWN5SStQQzl6WTNKcGNIUStDand2YUdWaFpENEtQR0p2WkhrK0NnbzhZMlZ1ZEdWeVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpnd0pTSWdZMnhoYzNNOUltSnZjbVJsY2lJK0NqeDBjaUJDUjBOUFRFOVNQU05ETTBRNVJrWStDangwWkNCaGJHbG5iajBpWTJWdWRHVnlJaUJqYjJ4emNHRnVQU0kySWo0S1BFZ3hQbFJvWlNCQ2IyUm5aVWwwSUZOMGIzSmxQQzlJTVQ0S1BIUmhZbXhsSUhkcFpIUm9QU0l4TURBbElpQmpiR0Z6Y3oxY0ltNXZZbTl5WkdWeVhDSStDangwY2lCQ1IwTlBURTlTUFNORE0wUTVSa1krQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTXpBbElqNG1ibUp6Y0RzOEwzUmtQZ284ZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJalF3SlNJK1YyVWdZbTlrWjJVZ2FYUXNJSE52SUhsdmRTQmtiMjUwSUdoaGRtVWdkRzhoUEM5MFpENEtQSFJrSUdGc2FXZHVQU0pqWlc1MFpYSWlJSGRwWkhSb1BTSXpNQ1VpSUhOMGVXeGxQU0owWlhoMExXRnNhV2R1T2lCeWFXZG9kQ0lnUGdwSGRXVnpkQ0IxYzJWeUNnbzhMM1J5UGdvOEwzUmhZbXhsUGdvOEwzUmtQZ284TDNSeVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTVRZbElpQkNSME5QVEU5U1BTTkZSVVZGUlVVK1BHRWdhSEpsWmowaWFHOXRaUzVxYzNBaVBraHZiV1U4TDJFK1BDOTBaRDRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUhkcFpIUm9QU0l4TmlVaUlFSkhRMDlNVDFJOUkwVkZSVVZGUlQ0OFlTQm9jbVZtUFNKaFltOTFkQzVxYzNBaVBrRmliM1YwSUZWelBDOWhQand2ZEdRK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQanhoSUdoeVpXWTlJbU52Ym5SaFkzUXVhbk53SWo1RGIyNTBZV04wSUZWelBDOWhQand2ZEdRK0Nqd2hMUzBnZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJakUySlNJK1BHRWdhSEpsWmowaVlXUnRhVzR1YW5Od0lqNUJaRzFwYmp3dllUNDhMM1JrTFMwK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQZ29LQ1FrOFlTQm9jbVZtUFNKc2IyZHBiaTVxYzNBaVBreHZaMmx1UEM5aFBnb0tQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGlZbUZ6YTJWMExtcHpjQ0krV1c5MWNpQkNZWE5yWlhROEwyRStQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGljMlZoY21Ob0xtcHpjQ0krVTJWaGNtTm9QQzloUGp3dmRHUStDand2ZEhJK0NqeDBjajRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUdOdmJITndZVzQ5SWpZaVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpFd01DVWlJR05zWVhOelBTSmliM0prWlhJaVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaWJHVm1kQ0lnZG1Gc2FXZHVQU0owYjNBaUlIZHBaSFJvUFNJeU5TVWlQZ284WVNCb2NtVm1QU0p3Y205a2RXTjBMbXB6Y0Q5MGVYQmxhV1E5TmlJK1JHOXZaR0ZvY3p3dllUNDhZbkl2UGdvOFlTQm9jbVZtUFNKd2NtOWtkV04wTG1wemNEOTBlWEJsYVdROU5TSStSMmw2Ylc5elBDOWhQanhpY2k4K0NqeGhJR2h5WldZOUluQnliMlIxWTNRdWFuTndQM1I1Y0dWcFpEMHpJajVVYUdsdVoyRnRZV3BwWjNNOEwyRStQR0p5THo0S1BHRWdhSEpsWmowaWNISnZaSFZqZEM1cWMzQS9kSGx3Wldsa1BUSWlQbFJvYVc1bmFXVnpQQzloUGp4aWNpOCtDanhoSUdoeVpXWTlJbkJ5YjJSMVkzUXVhbk53UDNSNWNHVnBaRDAzSWo1WGFHRjBZMmhoYldGallXeHNhWFJ6UEM5aFBqeGljaTgrQ2p4aElHaHlaV1k5SW5CeWIyUjFZM1F1YW5Od1AzUjVjR1ZwWkQwMElqNVhhR0YwYzJsMGN6d3ZZVDQ4WW5JdlBnbzhZU0JvY21WbVBTSndjbTlrZFdOMExtcHpjRDkwZVhCbGFXUTlNU0krVjJsa1oyVjBjend2WVQ0OFluSXZQZ29LUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K1BHSnlMejQ4WW5JdlBqeGljaTgrUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K0Nqd3ZkR1ErQ2p4MFpDQjJZV3hwWjI0OUluUnZjQ0lnZDJsa2RHZzlJamN3SlNJK0NnMEtEUW84YURNK1RHOW5hVzQ4TDJnelBnMEtVR3hsWVhObElHVnVkR1Z5SUhsdmRYSWdZM0psWkdWdWRHbGhiSE02SUR4aWNpOCtQR0p5THo0TkNqeG1iM0p0SUcxbGRHaHZaRDBpVUU5VFZDSStEUW9KUEdObGJuUmxjajROQ2drOGRHRmliR1UrRFFvSlBIUnlQZzBLQ1FrOGRHUStWWE5sY201aGJXVTZQQzkwWkQ0TkNna0pQSFJrUGp4cGJuQjFkQ0JwWkQwaWRYTmxjbTVoYldVaUlHNWhiV1U5SW5WelpYSnVZVzFsSWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4ZEhJK0RRb0pDVHgwWkQ1UVlYTnpkMjl5WkRvOEwzUmtQZzBLQ1FrOGRHUStQR2x1Y0hWMElHbGtQU0p3WVhOemQyOXlaQ0lnYm1GdFpUMGljR0Z6YzNkdmNtUWlJSFI1Y0dVOUluQmhjM04zYjNKa0lqNDhMMmx1Y0hWMFBqd3ZkR1ErRFFvSlBDOTBjajROQ2drOGRISStEUW9KQ1R4MFpENDhMM1JrUGcwS0NRazhkR1ErUEdsdWNIVjBJR2xrUFNKemRXSnRhWFFpSUhSNWNHVTlJbk4xWW0xcGRDSWdkbUZzZFdVOUlreHZaMmx1SWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4TDNSaFlteGxQZzBLQ1R3dlkyVnVkR1Z5UGcwS1BDOW1iM0p0UGcwS1NXWWdlVzkxSUdSdmJuUWdhR0YyWlNCaGJpQmhZMk52ZFc1MElIZHBkR2dnZFhNZ2RHaGxiaUJ3YkdWaGMyVWdQR0VnYUhKbFpqMGljbVZuYVhOMFpYSXVhbk53SWo1U1pXZHBjM1JsY2p3dllUNGdibTkzSUdadmNpQmhJR1p5WldVZ1lXTmpiM1Z1ZEM0TkNqeGljaTgrUEdKeUx6NE5DZzBLUEM5MFpENEtQQzkwY2o0S1BDOTBZV0pzWlQ0S1BDOTBaRDRLUEM5MGNqNEtQQzkwWVdKc1pUNEtQQzlqWlc1MFpYSStDand2WW05a2VUNEtQQzlvZEcxc1Bnb05DZzBL" + } + }, + { + "pk": 124, + "model": "dojo.burprawrequestresponse", + "fields": { + "finding": 8, + "burpRequestBase64": "UjBWVUlDOWliMlJuWldsMEwyeHZaMmx1TG1wemNDQklWRlJRTHpFdU1RMEtTRzl6ZERvZ2JHOWpZV3hvYjNOME9qZzRPRGdOQ2xWelpYSXRRV2RsYm5RNklFMXZlbWxzYkdFdk5TNHdJQ2hOWVdOcGJuUnZjMmc3SUVsdWRHVnNJRTFoWXlCUFV5QllJREV3TGpFeE95Qnlkam8wTnk0d0tTQkhaV05yYnk4eU1ERXdNREV3TVNCR2FYSmxabTk0THpRM0xqQU5Da0ZqWTJWd2REb2dkR1Y0ZEM5b2RHMXNMR0Z3Y0d4cFkyRjBhVzl1TDNob2RHMXNLM2h0YkN4aGNIQnNhV05oZEdsdmJpOTRiV3c3Y1Qwd0xqa3NLaThxTzNFOU1DNDREUXBCWTJObGNIUXRUR0Z1WjNWaFoyVTZJR1Z1TFZWVExHVnVPM0U5TUM0MURRcEJZMk5sY0hRdFJXNWpiMlJwYm1jNklHZDZhWEFzSUdSbFpteGhkR1VOQ2xKbFptVnlaWEk2SUdoMGRIQTZMeTlzYjJOaGJHaHZjM1E2T0RnNE9DOWliMlJuWldsMEx3MEtRMjl2YTJsbE9pQktVMFZUVTBsUFRrbEVQVFpGT1RVM04wRXhOa0pCUXpZeE9URXpSRVU1TjBFNE9EZEJSRFl3TWpjMURRcERiMjV1WldOMGFXOXVPaUJqYkc5elpRMEtEUW89", + "burpResponseBase64": "U0ZSVVVDOHhMakVnTWpBd0lBMEtVMlZ5ZG1WeU9pQkJjR0ZqYUdVdFEyOTViM1JsTHpFdU1RMEtRMjl1ZEdWdWRDMVVlWEJsT2lCMFpYaDBMMmgwYld3N1kyaGhjbk5sZEQxSlUwOHRPRGcxT1MweERRcERiMjUwWlc1MExVeGxibWQwYURvZ01qUTJNZzBLUkdGMFpUb2dVMkYwTENBeU55QkJkV2NnTWpBeE5pQXdNam93T0RvMU55QkhUVlFOQ2tOdmJtNWxZM1JwYjI0NklHTnNiM05sRFFvTkNnMEtEUW9OQ2cwS0Nnb0tDandoUkU5RFZGbFFSU0JJVkUxTUlGQlZRa3hKUXlBaUxTOHZWek5ETHk5RVZFUWdTRlJOVENBekxqSXZMMFZPSWo0S1BHaDBiV3crQ2p4b1pXRmtQZ284ZEdsMGJHVStWR2hsSUVKdlpHZGxTWFFnVTNSdmNtVThMM1JwZEd4bFBnbzhiR2x1YXlCb2NtVm1QU0p6ZEhsc1pTNWpjM01pSUhKbGJEMGljM1I1YkdWemFHVmxkQ0lnZEhsd1pUMGlkR1Y0ZEM5amMzTWlJQzgrQ2p4elkzSnBjSFFnZEhsd1pUMGlkR1Y0ZEM5cVlYWmhjMk55YVhCMElpQnpjbU05SWk0dmFuTXZkWFJwYkM1cWN5SStQQzl6WTNKcGNIUStDand2YUdWaFpENEtQR0p2WkhrK0NnbzhZMlZ1ZEdWeVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpnd0pTSWdZMnhoYzNNOUltSnZjbVJsY2lJK0NqeDBjaUJDUjBOUFRFOVNQU05ETTBRNVJrWStDangwWkNCaGJHbG5iajBpWTJWdWRHVnlJaUJqYjJ4emNHRnVQU0kySWo0S1BFZ3hQbFJvWlNCQ2IyUm5aVWwwSUZOMGIzSmxQQzlJTVQ0S1BIUmhZbXhsSUhkcFpIUm9QU0l4TURBbElpQmpiR0Z6Y3oxY0ltNXZZbTl5WkdWeVhDSStDangwY2lCQ1IwTlBURTlTUFNORE0wUTVSa1krQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTXpBbElqNG1ibUp6Y0RzOEwzUmtQZ284ZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJalF3SlNJK1YyVWdZbTlrWjJVZ2FYUXNJSE52SUhsdmRTQmtiMjUwSUdoaGRtVWdkRzhoUEM5MFpENEtQSFJrSUdGc2FXZHVQU0pqWlc1MFpYSWlJSGRwWkhSb1BTSXpNQ1VpSUhOMGVXeGxQU0owWlhoMExXRnNhV2R1T2lCeWFXZG9kQ0lnUGdwSGRXVnpkQ0IxYzJWeUNnbzhMM1J5UGdvOEwzUmhZbXhsUGdvOEwzUmtQZ284TDNSeVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTVRZbElpQkNSME5QVEU5U1BTTkZSVVZGUlVVK1BHRWdhSEpsWmowaWFHOXRaUzVxYzNBaVBraHZiV1U4TDJFK1BDOTBaRDRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUhkcFpIUm9QU0l4TmlVaUlFSkhRMDlNVDFJOUkwVkZSVVZGUlQ0OFlTQm9jbVZtUFNKaFltOTFkQzVxYzNBaVBrRmliM1YwSUZWelBDOWhQand2ZEdRK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQanhoSUdoeVpXWTlJbU52Ym5SaFkzUXVhbk53SWo1RGIyNTBZV04wSUZWelBDOWhQand2ZEdRK0Nqd2hMUzBnZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJakUySlNJK1BHRWdhSEpsWmowaVlXUnRhVzR1YW5Od0lqNUJaRzFwYmp3dllUNDhMM1JrTFMwK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQZ29LQ1FrOFlTQm9jbVZtUFNKc2IyZHBiaTVxYzNBaVBreHZaMmx1UEM5aFBnb0tQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGlZbUZ6YTJWMExtcHpjQ0krV1c5MWNpQkNZWE5yWlhROEwyRStQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGljMlZoY21Ob0xtcHpjQ0krVTJWaGNtTm9QQzloUGp3dmRHUStDand2ZEhJK0NqeDBjajRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUdOdmJITndZVzQ5SWpZaVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpFd01DVWlJR05zWVhOelBTSmliM0prWlhJaVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaWJHVm1kQ0lnZG1Gc2FXZHVQU0owYjNBaUlIZHBaSFJvUFNJeU5TVWlQZ284WVNCb2NtVm1QU0p3Y205a2RXTjBMbXB6Y0Q5MGVYQmxhV1E5TmlJK1JHOXZaR0ZvY3p3dllUNDhZbkl2UGdvOFlTQm9jbVZtUFNKd2NtOWtkV04wTG1wemNEOTBlWEJsYVdROU5TSStSMmw2Ylc5elBDOWhQanhpY2k4K0NqeGhJR2h5WldZOUluQnliMlIxWTNRdWFuTndQM1I1Y0dWcFpEMHpJajVVYUdsdVoyRnRZV3BwWjNNOEwyRStQR0p5THo0S1BHRWdhSEpsWmowaWNISnZaSFZqZEM1cWMzQS9kSGx3Wldsa1BUSWlQbFJvYVc1bmFXVnpQQzloUGp4aWNpOCtDanhoSUdoeVpXWTlJbkJ5YjJSMVkzUXVhbk53UDNSNWNHVnBaRDAzSWo1WGFHRjBZMmhoYldGallXeHNhWFJ6UEM5aFBqeGljaTgrQ2p4aElHaHlaV1k5SW5CeWIyUjFZM1F1YW5Od1AzUjVjR1ZwWkQwMElqNVhhR0YwYzJsMGN6d3ZZVDQ4WW5JdlBnbzhZU0JvY21WbVBTSndjbTlrZFdOMExtcHpjRDkwZVhCbGFXUTlNU0krVjJsa1oyVjBjend2WVQ0OFluSXZQZ29LUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K1BHSnlMejQ4WW5JdlBqeGljaTgrUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K0Nqd3ZkR1ErQ2p4MFpDQjJZV3hwWjI0OUluUnZjQ0lnZDJsa2RHZzlJamN3SlNJK0NnMEtEUW84YURNK1RHOW5hVzQ4TDJnelBnMEtVR3hsWVhObElHVnVkR1Z5SUhsdmRYSWdZM0psWkdWdWRHbGhiSE02SUR4aWNpOCtQR0p5THo0TkNqeG1iM0p0SUcxbGRHaHZaRDBpVUU5VFZDSStEUW9KUEdObGJuUmxjajROQ2drOGRHRmliR1UrRFFvSlBIUnlQZzBLQ1FrOGRHUStWWE5sY201aGJXVTZQQzkwWkQ0TkNna0pQSFJrUGp4cGJuQjFkQ0JwWkQwaWRYTmxjbTVoYldVaUlHNWhiV1U5SW5WelpYSnVZVzFsSWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4ZEhJK0RRb0pDVHgwWkQ1UVlYTnpkMjl5WkRvOEwzUmtQZzBLQ1FrOGRHUStQR2x1Y0hWMElHbGtQU0p3WVhOemQyOXlaQ0lnYm1GdFpUMGljR0Z6YzNkdmNtUWlJSFI1Y0dVOUluQmhjM04zYjNKa0lqNDhMMmx1Y0hWMFBqd3ZkR1ErRFFvSlBDOTBjajROQ2drOGRISStEUW9KQ1R4MFpENDhMM1JrUGcwS0NRazhkR1ErUEdsdWNIVjBJR2xrUFNKemRXSnRhWFFpSUhSNWNHVTlJbk4xWW0xcGRDSWdkbUZzZFdVOUlreHZaMmx1SWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4TDNSaFlteGxQZzBLQ1R3dlkyVnVkR1Z5UGcwS1BDOW1iM0p0UGcwS1NXWWdlVzkxSUdSdmJuUWdhR0YyWlNCaGJpQmhZMk52ZFc1MElIZHBkR2dnZFhNZ2RHaGxiaUJ3YkdWaGMyVWdQR0VnYUhKbFpqMGljbVZuYVhOMFpYSXVhbk53SWo1U1pXZHBjM1JsY2p3dllUNGdibTkzSUdadmNpQmhJR1p5WldVZ1lXTmpiM1Z1ZEM0TkNqeGljaTgrUEdKeUx6NE5DZzBLUEM5MFpENEtQQzkwY2o0S1BDOTBZV0pzWlQ0S1BDOTBaRDRLUEM5MGNqNEtQQzkwWVdKc1pUNEtQQzlqWlc1MFpYSStDand2WW05a2VUNEtQQzlvZEcxc1Bnb05DZzBL" + } + }, + { + "pk": 125, + "model": "dojo.burprawrequestresponse", + "fields": { + "finding": 8, + "burpRequestBase64": "UjBWVUlDOWliMlJuWldsMEwyeHZaMmx1TG1wemNDQklWRlJRTHpFdU1RMEtTRzl6ZERvZ2JHOWpZV3hvYjNOME9qZzRPRGdOQ2xWelpYSXRRV2RsYm5RNklFMXZlbWxzYkdFdk5TNHdJQ2hOWVdOcGJuUnZjMmc3SUVsdWRHVnNJRTFoWXlCUFV5QllJREV3TGpFeE95Qnlkam8wTnk0d0tTQkhaV05yYnk4eU1ERXdNREV3TVNCR2FYSmxabTk0THpRM0xqQU5Da0ZqWTJWd2REb2dkR1Y0ZEM5b2RHMXNMR0Z3Y0d4cFkyRjBhVzl1TDNob2RHMXNLM2h0YkN4aGNIQnNhV05oZEdsdmJpOTRiV3c3Y1Qwd0xqa3NLaThxTzNFOU1DNDREUXBCWTJObGNIUXRUR0Z1WjNWaFoyVTZJR1Z1TFZWVExHVnVPM0U5TUM0MURRcEJZMk5sY0hRdFJXNWpiMlJwYm1jNklHZDZhWEFzSUdSbFpteGhkR1VOQ2xKbFptVnlaWEk2SUdoMGRIQTZMeTlzYjJOaGJHaHZjM1E2T0RnNE9DOWliMlJuWldsMEx3MEtRMjl2YTJsbE9pQktVMFZUVTBsUFRrbEVQVFpGT1RVM04wRXhOa0pCUXpZeE9URXpSRVU1TjBFNE9EZEJSRFl3TWpjMURRcERiMjV1WldOMGFXOXVPaUJqYkc5elpRMEtEUW89", + "burpResponseBase64": "U0ZSVVVDOHhMakVnTWpBd0lBMEtVMlZ5ZG1WeU9pQkJjR0ZqYUdVdFEyOTViM1JsTHpFdU1RMEtRMjl1ZEdWdWRDMVVlWEJsT2lCMFpYaDBMMmgwYld3N1kyaGhjbk5sZEQxSlUwOHRPRGcxT1MweERRcERiMjUwWlc1MExVeGxibWQwYURvZ01qUTJNZzBLUkdGMFpUb2dVMkYwTENBeU55QkJkV2NnTWpBeE5pQXdNam93T0RvMU55QkhUVlFOQ2tOdmJtNWxZM1JwYjI0NklHTnNiM05sRFFvTkNnMEtEUW9OQ2cwS0Nnb0tDandoUkU5RFZGbFFSU0JJVkUxTUlGQlZRa3hKUXlBaUxTOHZWek5ETHk5RVZFUWdTRlJOVENBekxqSXZMMFZPSWo0S1BHaDBiV3crQ2p4b1pXRmtQZ284ZEdsMGJHVStWR2hsSUVKdlpHZGxTWFFnVTNSdmNtVThMM1JwZEd4bFBnbzhiR2x1YXlCb2NtVm1QU0p6ZEhsc1pTNWpjM01pSUhKbGJEMGljM1I1YkdWemFHVmxkQ0lnZEhsd1pUMGlkR1Y0ZEM5amMzTWlJQzgrQ2p4elkzSnBjSFFnZEhsd1pUMGlkR1Y0ZEM5cVlYWmhjMk55YVhCMElpQnpjbU05SWk0dmFuTXZkWFJwYkM1cWN5SStQQzl6WTNKcGNIUStDand2YUdWaFpENEtQR0p2WkhrK0NnbzhZMlZ1ZEdWeVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpnd0pTSWdZMnhoYzNNOUltSnZjbVJsY2lJK0NqeDBjaUJDUjBOUFRFOVNQU05ETTBRNVJrWStDangwWkNCaGJHbG5iajBpWTJWdWRHVnlJaUJqYjJ4emNHRnVQU0kySWo0S1BFZ3hQbFJvWlNCQ2IyUm5aVWwwSUZOMGIzSmxQQzlJTVQ0S1BIUmhZbXhsSUhkcFpIUm9QU0l4TURBbElpQmpiR0Z6Y3oxY0ltNXZZbTl5WkdWeVhDSStDangwY2lCQ1IwTlBURTlTUFNORE0wUTVSa1krQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTXpBbElqNG1ibUp6Y0RzOEwzUmtQZ284ZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJalF3SlNJK1YyVWdZbTlrWjJVZ2FYUXNJSE52SUhsdmRTQmtiMjUwSUdoaGRtVWdkRzhoUEM5MFpENEtQSFJrSUdGc2FXZHVQU0pqWlc1MFpYSWlJSGRwWkhSb1BTSXpNQ1VpSUhOMGVXeGxQU0owWlhoMExXRnNhV2R1T2lCeWFXZG9kQ0lnUGdwSGRXVnpkQ0IxYzJWeUNnbzhMM1J5UGdvOEwzUmhZbXhsUGdvOEwzUmtQZ284TDNSeVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTVRZbElpQkNSME5QVEU5U1BTTkZSVVZGUlVVK1BHRWdhSEpsWmowaWFHOXRaUzVxYzNBaVBraHZiV1U4TDJFK1BDOTBaRDRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUhkcFpIUm9QU0l4TmlVaUlFSkhRMDlNVDFJOUkwVkZSVVZGUlQ0OFlTQm9jbVZtUFNKaFltOTFkQzVxYzNBaVBrRmliM1YwSUZWelBDOWhQand2ZEdRK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQanhoSUdoeVpXWTlJbU52Ym5SaFkzUXVhbk53SWo1RGIyNTBZV04wSUZWelBDOWhQand2ZEdRK0Nqd2hMUzBnZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJakUySlNJK1BHRWdhSEpsWmowaVlXUnRhVzR1YW5Od0lqNUJaRzFwYmp3dllUNDhMM1JrTFMwK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQZ29LQ1FrOFlTQm9jbVZtUFNKc2IyZHBiaTVxYzNBaVBreHZaMmx1UEM5aFBnb0tQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGlZbUZ6YTJWMExtcHpjQ0krV1c5MWNpQkNZWE5yWlhROEwyRStQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGljMlZoY21Ob0xtcHpjQ0krVTJWaGNtTm9QQzloUGp3dmRHUStDand2ZEhJK0NqeDBjajRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUdOdmJITndZVzQ5SWpZaVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpFd01DVWlJR05zWVhOelBTSmliM0prWlhJaVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaWJHVm1kQ0lnZG1Gc2FXZHVQU0owYjNBaUlIZHBaSFJvUFNJeU5TVWlQZ284WVNCb2NtVm1QU0p3Y205a2RXTjBMbXB6Y0Q5MGVYQmxhV1E5TmlJK1JHOXZaR0ZvY3p3dllUNDhZbkl2UGdvOFlTQm9jbVZtUFNKd2NtOWtkV04wTG1wemNEOTBlWEJsYVdROU5TSStSMmw2Ylc5elBDOWhQanhpY2k4K0NqeGhJR2h5WldZOUluQnliMlIxWTNRdWFuTndQM1I1Y0dWcFpEMHpJajVVYUdsdVoyRnRZV3BwWjNNOEwyRStQR0p5THo0S1BHRWdhSEpsWmowaWNISnZaSFZqZEM1cWMzQS9kSGx3Wldsa1BUSWlQbFJvYVc1bmFXVnpQQzloUGp4aWNpOCtDanhoSUdoeVpXWTlJbkJ5YjJSMVkzUXVhbk53UDNSNWNHVnBaRDAzSWo1WGFHRjBZMmhoYldGallXeHNhWFJ6UEM5aFBqeGljaTgrQ2p4aElHaHlaV1k5SW5CeWIyUjFZM1F1YW5Od1AzUjVjR1ZwWkQwMElqNVhhR0YwYzJsMGN6d3ZZVDQ4WW5JdlBnbzhZU0JvY21WbVBTSndjbTlrZFdOMExtcHpjRDkwZVhCbGFXUTlNU0krVjJsa1oyVjBjend2WVQ0OFluSXZQZ29LUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K1BHSnlMejQ4WW5JdlBqeGljaTgrUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K0Nqd3ZkR1ErQ2p4MFpDQjJZV3hwWjI0OUluUnZjQ0lnZDJsa2RHZzlJamN3SlNJK0NnMEtEUW84YURNK1RHOW5hVzQ4TDJnelBnMEtVR3hsWVhObElHVnVkR1Z5SUhsdmRYSWdZM0psWkdWdWRHbGhiSE02SUR4aWNpOCtQR0p5THo0TkNqeG1iM0p0SUcxbGRHaHZaRDBpVUU5VFZDSStEUW9KUEdObGJuUmxjajROQ2drOGRHRmliR1UrRFFvSlBIUnlQZzBLQ1FrOGRHUStWWE5sY201aGJXVTZQQzkwWkQ0TkNna0pQSFJrUGp4cGJuQjFkQ0JwWkQwaWRYTmxjbTVoYldVaUlHNWhiV1U5SW5WelpYSnVZVzFsSWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4ZEhJK0RRb0pDVHgwWkQ1UVlYTnpkMjl5WkRvOEwzUmtQZzBLQ1FrOGRHUStQR2x1Y0hWMElHbGtQU0p3WVhOemQyOXlaQ0lnYm1GdFpUMGljR0Z6YzNkdmNtUWlJSFI1Y0dVOUluQmhjM04zYjNKa0lqNDhMMmx1Y0hWMFBqd3ZkR1ErRFFvSlBDOTBjajROQ2drOGRISStEUW9KQ1R4MFpENDhMM1JrUGcwS0NRazhkR1ErUEdsdWNIVjBJR2xrUFNKemRXSnRhWFFpSUhSNWNHVTlJbk4xWW0xcGRDSWdkbUZzZFdVOUlreHZaMmx1SWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4TDNSaFlteGxQZzBLQ1R3dlkyVnVkR1Z5UGcwS1BDOW1iM0p0UGcwS1NXWWdlVzkxSUdSdmJuUWdhR0YyWlNCaGJpQmhZMk52ZFc1MElIZHBkR2dnZFhNZ2RHaGxiaUJ3YkdWaGMyVWdQR0VnYUhKbFpqMGljbVZuYVhOMFpYSXVhbk53SWo1U1pXZHBjM1JsY2p3dllUNGdibTkzSUdadmNpQmhJR1p5WldVZ1lXTmpiM1Z1ZEM0TkNqeGljaTgrUEdKeUx6NE5DZzBLUEM5MFpENEtQQzkwY2o0S1BDOTBZV0pzWlQ0S1BDOTBaRDRLUEM5MGNqNEtQQzkwWVdKc1pUNEtQQzlqWlc1MFpYSStDand2WW05a2VUNEtQQzlvZEcxc1Bnb05DZzBL" + } + }, + { + "pk": 126, + "model": "dojo.burprawrequestresponse", + "fields": { + "finding": 8, + "burpRequestBase64": "UjBWVUlDOWliMlJuWldsMEwyeHZaMmx1TG1wemNDQklWRlJRTHpFdU1RMEtTRzl6ZERvZ2JHOWpZV3hvYjNOME9qZzRPRGdOQ2xWelpYSXRRV2RsYm5RNklFMXZlbWxzYkdFdk5TNHdJQ2hOWVdOcGJuUnZjMmc3SUVsdWRHVnNJRTFoWXlCUFV5QllJREV3TGpFeE95Qnlkam8wTnk0d0tTQkhaV05yYnk4eU1ERXdNREV3TVNCR2FYSmxabTk0THpRM0xqQU5Da0ZqWTJWd2REb2dkR1Y0ZEM5b2RHMXNMR0Z3Y0d4cFkyRjBhVzl1TDNob2RHMXNLM2h0YkN4aGNIQnNhV05oZEdsdmJpOTRiV3c3Y1Qwd0xqa3NLaThxTzNFOU1DNDREUXBCWTJObGNIUXRUR0Z1WjNWaFoyVTZJR1Z1TFZWVExHVnVPM0U5TUM0MURRcEJZMk5sY0hRdFJXNWpiMlJwYm1jNklHZDZhWEFzSUdSbFpteGhkR1VOQ2xKbFptVnlaWEk2SUdoMGRIQTZMeTlzYjJOaGJHaHZjM1E2T0RnNE9DOWliMlJuWldsMEx3MEtRMjl2YTJsbE9pQktVMFZUVTBsUFRrbEVQVFpGT1RVM04wRXhOa0pCUXpZeE9URXpSRVU1TjBFNE9EZEJSRFl3TWpjMURRcERiMjV1WldOMGFXOXVPaUJqYkc5elpRMEtEUW89", + "burpResponseBase64": "U0ZSVVVDOHhMakVnTWpBd0lBMEtVMlZ5ZG1WeU9pQkJjR0ZqYUdVdFEyOTViM1JsTHpFdU1RMEtRMjl1ZEdWdWRDMVVlWEJsT2lCMFpYaDBMMmgwYld3N1kyaGhjbk5sZEQxSlUwOHRPRGcxT1MweERRcERiMjUwWlc1MExVeGxibWQwYURvZ01qUTJNZzBLUkdGMFpUb2dVMkYwTENBeU55QkJkV2NnTWpBeE5pQXdNam93T0RvMU55QkhUVlFOQ2tOdmJtNWxZM1JwYjI0NklHTnNiM05sRFFvTkNnMEtEUW9OQ2cwS0Nnb0tDandoUkU5RFZGbFFSU0JJVkUxTUlGQlZRa3hKUXlBaUxTOHZWek5ETHk5RVZFUWdTRlJOVENBekxqSXZMMFZPSWo0S1BHaDBiV3crQ2p4b1pXRmtQZ284ZEdsMGJHVStWR2hsSUVKdlpHZGxTWFFnVTNSdmNtVThMM1JwZEd4bFBnbzhiR2x1YXlCb2NtVm1QU0p6ZEhsc1pTNWpjM01pSUhKbGJEMGljM1I1YkdWemFHVmxkQ0lnZEhsd1pUMGlkR1Y0ZEM5amMzTWlJQzgrQ2p4elkzSnBjSFFnZEhsd1pUMGlkR1Y0ZEM5cVlYWmhjMk55YVhCMElpQnpjbU05SWk0dmFuTXZkWFJwYkM1cWN5SStQQzl6WTNKcGNIUStDand2YUdWaFpENEtQR0p2WkhrK0NnbzhZMlZ1ZEdWeVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpnd0pTSWdZMnhoYzNNOUltSnZjbVJsY2lJK0NqeDBjaUJDUjBOUFRFOVNQU05ETTBRNVJrWStDangwWkNCaGJHbG5iajBpWTJWdWRHVnlJaUJqYjJ4emNHRnVQU0kySWo0S1BFZ3hQbFJvWlNCQ2IyUm5aVWwwSUZOMGIzSmxQQzlJTVQ0S1BIUmhZbXhsSUhkcFpIUm9QU0l4TURBbElpQmpiR0Z6Y3oxY0ltNXZZbTl5WkdWeVhDSStDangwY2lCQ1IwTlBURTlTUFNORE0wUTVSa1krQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTXpBbElqNG1ibUp6Y0RzOEwzUmtQZ284ZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJalF3SlNJK1YyVWdZbTlrWjJVZ2FYUXNJSE52SUhsdmRTQmtiMjUwSUdoaGRtVWdkRzhoUEM5MFpENEtQSFJrSUdGc2FXZHVQU0pqWlc1MFpYSWlJSGRwWkhSb1BTSXpNQ1VpSUhOMGVXeGxQU0owWlhoMExXRnNhV2R1T2lCeWFXZG9kQ0lnUGdwSGRXVnpkQ0IxYzJWeUNnbzhMM1J5UGdvOEwzUmhZbXhsUGdvOEwzUmtQZ284TDNSeVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTVRZbElpQkNSME5QVEU5U1BTTkZSVVZGUlVVK1BHRWdhSEpsWmowaWFHOXRaUzVxYzNBaVBraHZiV1U4TDJFK1BDOTBaRDRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUhkcFpIUm9QU0l4TmlVaUlFSkhRMDlNVDFJOUkwVkZSVVZGUlQ0OFlTQm9jbVZtUFNKaFltOTFkQzVxYzNBaVBrRmliM1YwSUZWelBDOWhQand2ZEdRK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQanhoSUdoeVpXWTlJbU52Ym5SaFkzUXVhbk53SWo1RGIyNTBZV04wSUZWelBDOWhQand2ZEdRK0Nqd2hMUzBnZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJakUySlNJK1BHRWdhSEpsWmowaVlXUnRhVzR1YW5Od0lqNUJaRzFwYmp3dllUNDhMM1JrTFMwK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQZ29LQ1FrOFlTQm9jbVZtUFNKc2IyZHBiaTVxYzNBaVBreHZaMmx1UEM5aFBnb0tQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGlZbUZ6YTJWMExtcHpjQ0krV1c5MWNpQkNZWE5yWlhROEwyRStQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGljMlZoY21Ob0xtcHpjQ0krVTJWaGNtTm9QQzloUGp3dmRHUStDand2ZEhJK0NqeDBjajRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUdOdmJITndZVzQ5SWpZaVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpFd01DVWlJR05zWVhOelBTSmliM0prWlhJaVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaWJHVm1kQ0lnZG1Gc2FXZHVQU0owYjNBaUlIZHBaSFJvUFNJeU5TVWlQZ284WVNCb2NtVm1QU0p3Y205a2RXTjBMbXB6Y0Q5MGVYQmxhV1E5TmlJK1JHOXZaR0ZvY3p3dllUNDhZbkl2UGdvOFlTQm9jbVZtUFNKd2NtOWtkV04wTG1wemNEOTBlWEJsYVdROU5TSStSMmw2Ylc5elBDOWhQanhpY2k4K0NqeGhJR2h5WldZOUluQnliMlIxWTNRdWFuTndQM1I1Y0dWcFpEMHpJajVVYUdsdVoyRnRZV3BwWjNNOEwyRStQR0p5THo0S1BHRWdhSEpsWmowaWNISnZaSFZqZEM1cWMzQS9kSGx3Wldsa1BUSWlQbFJvYVc1bmFXVnpQQzloUGp4aWNpOCtDanhoSUdoeVpXWTlJbkJ5YjJSMVkzUXVhbk53UDNSNWNHVnBaRDAzSWo1WGFHRjBZMmhoYldGallXeHNhWFJ6UEM5aFBqeGljaTgrQ2p4aElHaHlaV1k5SW5CeWIyUjFZM1F1YW5Od1AzUjVjR1ZwWkQwMElqNVhhR0YwYzJsMGN6d3ZZVDQ4WW5JdlBnbzhZU0JvY21WbVBTSndjbTlrZFdOMExtcHpjRDkwZVhCbGFXUTlNU0krVjJsa1oyVjBjend2WVQ0OFluSXZQZ29LUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K1BHSnlMejQ4WW5JdlBqeGljaTgrUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K0Nqd3ZkR1ErQ2p4MFpDQjJZV3hwWjI0OUluUnZjQ0lnZDJsa2RHZzlJamN3SlNJK0NnMEtEUW84YURNK1RHOW5hVzQ4TDJnelBnMEtVR3hsWVhObElHVnVkR1Z5SUhsdmRYSWdZM0psWkdWdWRHbGhiSE02SUR4aWNpOCtQR0p5THo0TkNqeG1iM0p0SUcxbGRHaHZaRDBpVUU5VFZDSStEUW9KUEdObGJuUmxjajROQ2drOGRHRmliR1UrRFFvSlBIUnlQZzBLQ1FrOGRHUStWWE5sY201aGJXVTZQQzkwWkQ0TkNna0pQSFJrUGp4cGJuQjFkQ0JwWkQwaWRYTmxjbTVoYldVaUlHNWhiV1U5SW5WelpYSnVZVzFsSWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4ZEhJK0RRb0pDVHgwWkQ1UVlYTnpkMjl5WkRvOEwzUmtQZzBLQ1FrOGRHUStQR2x1Y0hWMElHbGtQU0p3WVhOemQyOXlaQ0lnYm1GdFpUMGljR0Z6YzNkdmNtUWlJSFI1Y0dVOUluQmhjM04zYjNKa0lqNDhMMmx1Y0hWMFBqd3ZkR1ErRFFvSlBDOTBjajROQ2drOGRISStEUW9KQ1R4MFpENDhMM1JrUGcwS0NRazhkR1ErUEdsdWNIVjBJR2xrUFNKemRXSnRhWFFpSUhSNWNHVTlJbk4xWW0xcGRDSWdkbUZzZFdVOUlreHZaMmx1SWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4TDNSaFlteGxQZzBLQ1R3dlkyVnVkR1Z5UGcwS1BDOW1iM0p0UGcwS1NXWWdlVzkxSUdSdmJuUWdhR0YyWlNCaGJpQmhZMk52ZFc1MElIZHBkR2dnZFhNZ2RHaGxiaUJ3YkdWaGMyVWdQR0VnYUhKbFpqMGljbVZuYVhOMFpYSXVhbk53SWo1U1pXZHBjM1JsY2p3dllUNGdibTkzSUdadmNpQmhJR1p5WldVZ1lXTmpiM1Z1ZEM0TkNqeGljaTgrUEdKeUx6NE5DZzBLUEM5MFpENEtQQzkwY2o0S1BDOTBZV0pzWlQ0S1BDOTBaRDRLUEM5MGNqNEtQQzkwWVdKc1pUNEtQQzlqWlc1MFpYSStDand2WW05a2VUNEtQQzlvZEcxc1Bnb05DZzBL" + } + }, + { + "pk": 127, + "model": "dojo.burprawrequestresponse", + "fields": { + "finding": 8, + "burpRequestBase64": "UjBWVUlDOWliMlJuWldsMEwyeHZaMmx1TG1wemNDQklWRlJRTHpFdU1RMEtTRzl6ZERvZ2JHOWpZV3hvYjNOME9qZzRPRGdOQ2xWelpYSXRRV2RsYm5RNklFMXZlbWxzYkdFdk5TNHdJQ2hOWVdOcGJuUnZjMmc3SUVsdWRHVnNJRTFoWXlCUFV5QllJREV3TGpFeE95Qnlkam8wTnk0d0tTQkhaV05yYnk4eU1ERXdNREV3TVNCR2FYSmxabTk0THpRM0xqQU5Da0ZqWTJWd2REb2dkR1Y0ZEM5b2RHMXNMR0Z3Y0d4cFkyRjBhVzl1TDNob2RHMXNLM2h0YkN4aGNIQnNhV05oZEdsdmJpOTRiV3c3Y1Qwd0xqa3NLaThxTzNFOU1DNDREUXBCWTJObGNIUXRUR0Z1WjNWaFoyVTZJR1Z1TFZWVExHVnVPM0U5TUM0MURRcEJZMk5sY0hRdFJXNWpiMlJwYm1jNklHZDZhWEFzSUdSbFpteGhkR1VOQ2xKbFptVnlaWEk2SUdoMGRIQTZMeTlzYjJOaGJHaHZjM1E2T0RnNE9DOWliMlJuWldsMEx3MEtRMjl2YTJsbE9pQktVMFZUVTBsUFRrbEVQVFpGT1RVM04wRXhOa0pCUXpZeE9URXpSRVU1TjBFNE9EZEJSRFl3TWpjMURRcERiMjV1WldOMGFXOXVPaUJqYkc5elpRMEtEUW89", + "burpResponseBase64": "U0ZSVVVDOHhMakVnTWpBd0lBMEtVMlZ5ZG1WeU9pQkJjR0ZqYUdVdFEyOTViM1JsTHpFdU1RMEtRMjl1ZEdWdWRDMVVlWEJsT2lCMFpYaDBMMmgwYld3N1kyaGhjbk5sZEQxSlUwOHRPRGcxT1MweERRcERiMjUwWlc1MExVeGxibWQwYURvZ01qUTJNZzBLUkdGMFpUb2dVMkYwTENBeU55QkJkV2NnTWpBeE5pQXdNam93T0RvMU55QkhUVlFOQ2tOdmJtNWxZM1JwYjI0NklHTnNiM05sRFFvTkNnMEtEUW9OQ2cwS0Nnb0tDandoUkU5RFZGbFFSU0JJVkUxTUlGQlZRa3hKUXlBaUxTOHZWek5ETHk5RVZFUWdTRlJOVENBekxqSXZMMFZPSWo0S1BHaDBiV3crQ2p4b1pXRmtQZ284ZEdsMGJHVStWR2hsSUVKdlpHZGxTWFFnVTNSdmNtVThMM1JwZEd4bFBnbzhiR2x1YXlCb2NtVm1QU0p6ZEhsc1pTNWpjM01pSUhKbGJEMGljM1I1YkdWemFHVmxkQ0lnZEhsd1pUMGlkR1Y0ZEM5amMzTWlJQzgrQ2p4elkzSnBjSFFnZEhsd1pUMGlkR1Y0ZEM5cVlYWmhjMk55YVhCMElpQnpjbU05SWk0dmFuTXZkWFJwYkM1cWN5SStQQzl6WTNKcGNIUStDand2YUdWaFpENEtQR0p2WkhrK0NnbzhZMlZ1ZEdWeVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpnd0pTSWdZMnhoYzNNOUltSnZjbVJsY2lJK0NqeDBjaUJDUjBOUFRFOVNQU05ETTBRNVJrWStDangwWkNCaGJHbG5iajBpWTJWdWRHVnlJaUJqYjJ4emNHRnVQU0kySWo0S1BFZ3hQbFJvWlNCQ2IyUm5aVWwwSUZOMGIzSmxQQzlJTVQ0S1BIUmhZbXhsSUhkcFpIUm9QU0l4TURBbElpQmpiR0Z6Y3oxY0ltNXZZbTl5WkdWeVhDSStDangwY2lCQ1IwTlBURTlTUFNORE0wUTVSa1krQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTXpBbElqNG1ibUp6Y0RzOEwzUmtQZ284ZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJalF3SlNJK1YyVWdZbTlrWjJVZ2FYUXNJSE52SUhsdmRTQmtiMjUwSUdoaGRtVWdkRzhoUEM5MFpENEtQSFJrSUdGc2FXZHVQU0pqWlc1MFpYSWlJSGRwWkhSb1BTSXpNQ1VpSUhOMGVXeGxQU0owWlhoMExXRnNhV2R1T2lCeWFXZG9kQ0lnUGdwSGRXVnpkQ0IxYzJWeUNnbzhMM1J5UGdvOEwzUmhZbXhsUGdvOEwzUmtQZ284TDNSeVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTVRZbElpQkNSME5QVEU5U1BTTkZSVVZGUlVVK1BHRWdhSEpsWmowaWFHOXRaUzVxYzNBaVBraHZiV1U4TDJFK1BDOTBaRDRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUhkcFpIUm9QU0l4TmlVaUlFSkhRMDlNVDFJOUkwVkZSVVZGUlQ0OFlTQm9jbVZtUFNKaFltOTFkQzVxYzNBaVBrRmliM1YwSUZWelBDOWhQand2ZEdRK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQanhoSUdoeVpXWTlJbU52Ym5SaFkzUXVhbk53SWo1RGIyNTBZV04wSUZWelBDOWhQand2ZEdRK0Nqd2hMUzBnZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJakUySlNJK1BHRWdhSEpsWmowaVlXUnRhVzR1YW5Od0lqNUJaRzFwYmp3dllUNDhMM1JrTFMwK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQZ29LQ1FrOFlTQm9jbVZtUFNKc2IyZHBiaTVxYzNBaVBreHZaMmx1UEM5aFBnb0tQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGlZbUZ6YTJWMExtcHpjQ0krV1c5MWNpQkNZWE5yWlhROEwyRStQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGljMlZoY21Ob0xtcHpjQ0krVTJWaGNtTm9QQzloUGp3dmRHUStDand2ZEhJK0NqeDBjajRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUdOdmJITndZVzQ5SWpZaVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpFd01DVWlJR05zWVhOelBTSmliM0prWlhJaVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaWJHVm1kQ0lnZG1Gc2FXZHVQU0owYjNBaUlIZHBaSFJvUFNJeU5TVWlQZ284WVNCb2NtVm1QU0p3Y205a2RXTjBMbXB6Y0Q5MGVYQmxhV1E5TmlJK1JHOXZaR0ZvY3p3dllUNDhZbkl2UGdvOFlTQm9jbVZtUFNKd2NtOWtkV04wTG1wemNEOTBlWEJsYVdROU5TSStSMmw2Ylc5elBDOWhQanhpY2k4K0NqeGhJR2h5WldZOUluQnliMlIxWTNRdWFuTndQM1I1Y0dWcFpEMHpJajVVYUdsdVoyRnRZV3BwWjNNOEwyRStQR0p5THo0S1BHRWdhSEpsWmowaWNISnZaSFZqZEM1cWMzQS9kSGx3Wldsa1BUSWlQbFJvYVc1bmFXVnpQQzloUGp4aWNpOCtDanhoSUdoeVpXWTlJbkJ5YjJSMVkzUXVhbk53UDNSNWNHVnBaRDAzSWo1WGFHRjBZMmhoYldGallXeHNhWFJ6UEM5aFBqeGljaTgrQ2p4aElHaHlaV1k5SW5CeWIyUjFZM1F1YW5Od1AzUjVjR1ZwWkQwMElqNVhhR0YwYzJsMGN6d3ZZVDQ4WW5JdlBnbzhZU0JvY21WbVBTSndjbTlrZFdOMExtcHpjRDkwZVhCbGFXUTlNU0krVjJsa1oyVjBjend2WVQ0OFluSXZQZ29LUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K1BHSnlMejQ4WW5JdlBqeGljaTgrUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K0Nqd3ZkR1ErQ2p4MFpDQjJZV3hwWjI0OUluUnZjQ0lnZDJsa2RHZzlJamN3SlNJK0NnMEtEUW84YURNK1RHOW5hVzQ4TDJnelBnMEtVR3hsWVhObElHVnVkR1Z5SUhsdmRYSWdZM0psWkdWdWRHbGhiSE02SUR4aWNpOCtQR0p5THo0TkNqeG1iM0p0SUcxbGRHaHZaRDBpVUU5VFZDSStEUW9KUEdObGJuUmxjajROQ2drOGRHRmliR1UrRFFvSlBIUnlQZzBLQ1FrOGRHUStWWE5sY201aGJXVTZQQzkwWkQ0TkNna0pQSFJrUGp4cGJuQjFkQ0JwWkQwaWRYTmxjbTVoYldVaUlHNWhiV1U5SW5WelpYSnVZVzFsSWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4ZEhJK0RRb0pDVHgwWkQ1UVlYTnpkMjl5WkRvOEwzUmtQZzBLQ1FrOGRHUStQR2x1Y0hWMElHbGtQU0p3WVhOemQyOXlaQ0lnYm1GdFpUMGljR0Z6YzNkdmNtUWlJSFI1Y0dVOUluQmhjM04zYjNKa0lqNDhMMmx1Y0hWMFBqd3ZkR1ErRFFvSlBDOTBjajROQ2drOGRISStEUW9KQ1R4MFpENDhMM1JrUGcwS0NRazhkR1ErUEdsdWNIVjBJR2xrUFNKemRXSnRhWFFpSUhSNWNHVTlJbk4xWW0xcGRDSWdkbUZzZFdVOUlreHZaMmx1SWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4TDNSaFlteGxQZzBLQ1R3dlkyVnVkR1Z5UGcwS1BDOW1iM0p0UGcwS1NXWWdlVzkxSUdSdmJuUWdhR0YyWlNCaGJpQmhZMk52ZFc1MElIZHBkR2dnZFhNZ2RHaGxiaUJ3YkdWaGMyVWdQR0VnYUhKbFpqMGljbVZuYVhOMFpYSXVhbk53SWo1U1pXZHBjM1JsY2p3dllUNGdibTkzSUdadmNpQmhJR1p5WldVZ1lXTmpiM1Z1ZEM0TkNqeGljaTgrUEdKeUx6NE5DZzBLUEM5MFpENEtQQzkwY2o0S1BDOTBZV0pzWlQ0S1BDOTBaRDRLUEM5MGNqNEtQQzkwWVdKc1pUNEtQQzlqWlc1MFpYSStDand2WW05a2VUNEtQQzlvZEcxc1Bnb05DZzBL" + } + }, + { + "pk": 128, + "model": "dojo.burprawrequestresponse", + "fields": { + "finding": 8, + "burpRequestBase64": "UjBWVUlDOWliMlJuWldsMEwyeHZaMmx1TG1wemNDQklWRlJRTHpFdU1RMEtTRzl6ZERvZ2JHOWpZV3hvYjNOME9qZzRPRGdOQ2xWelpYSXRRV2RsYm5RNklFMXZlbWxzYkdFdk5TNHdJQ2hOWVdOcGJuUnZjMmc3SUVsdWRHVnNJRTFoWXlCUFV5QllJREV3TGpFeE95Qnlkam8wTnk0d0tTQkhaV05yYnk4eU1ERXdNREV3TVNCR2FYSmxabTk0THpRM0xqQU5Da0ZqWTJWd2REb2dkR1Y0ZEM5b2RHMXNMR0Z3Y0d4cFkyRjBhVzl1TDNob2RHMXNLM2h0YkN4aGNIQnNhV05oZEdsdmJpOTRiV3c3Y1Qwd0xqa3NLaThxTzNFOU1DNDREUXBCWTJObGNIUXRUR0Z1WjNWaFoyVTZJR1Z1TFZWVExHVnVPM0U5TUM0MURRcEJZMk5sY0hRdFJXNWpiMlJwYm1jNklHZDZhWEFzSUdSbFpteGhkR1VOQ2xKbFptVnlaWEk2SUdoMGRIQTZMeTlzYjJOaGJHaHZjM1E2T0RnNE9DOWliMlJuWldsMEx3MEtRMjl2YTJsbE9pQktVMFZUVTBsUFRrbEVQVFpGT1RVM04wRXhOa0pCUXpZeE9URXpSRVU1TjBFNE9EZEJSRFl3TWpjMURRcERiMjV1WldOMGFXOXVPaUJqYkc5elpRMEtEUW89", + "burpResponseBase64": "U0ZSVVVDOHhMakVnTWpBd0lBMEtVMlZ5ZG1WeU9pQkJjR0ZqYUdVdFEyOTViM1JsTHpFdU1RMEtRMjl1ZEdWdWRDMVVlWEJsT2lCMFpYaDBMMmgwYld3N1kyaGhjbk5sZEQxSlUwOHRPRGcxT1MweERRcERiMjUwWlc1MExVeGxibWQwYURvZ01qUTJNZzBLUkdGMFpUb2dVMkYwTENBeU55QkJkV2NnTWpBeE5pQXdNam93T0RvMU55QkhUVlFOQ2tOdmJtNWxZM1JwYjI0NklHTnNiM05sRFFvTkNnMEtEUW9OQ2cwS0Nnb0tDandoUkU5RFZGbFFSU0JJVkUxTUlGQlZRa3hKUXlBaUxTOHZWek5ETHk5RVZFUWdTRlJOVENBekxqSXZMMFZPSWo0S1BHaDBiV3crQ2p4b1pXRmtQZ284ZEdsMGJHVStWR2hsSUVKdlpHZGxTWFFnVTNSdmNtVThMM1JwZEd4bFBnbzhiR2x1YXlCb2NtVm1QU0p6ZEhsc1pTNWpjM01pSUhKbGJEMGljM1I1YkdWemFHVmxkQ0lnZEhsd1pUMGlkR1Y0ZEM5amMzTWlJQzgrQ2p4elkzSnBjSFFnZEhsd1pUMGlkR1Y0ZEM5cVlYWmhjMk55YVhCMElpQnpjbU05SWk0dmFuTXZkWFJwYkM1cWN5SStQQzl6WTNKcGNIUStDand2YUdWaFpENEtQR0p2WkhrK0NnbzhZMlZ1ZEdWeVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpnd0pTSWdZMnhoYzNNOUltSnZjbVJsY2lJK0NqeDBjaUJDUjBOUFRFOVNQU05ETTBRNVJrWStDangwWkNCaGJHbG5iajBpWTJWdWRHVnlJaUJqYjJ4emNHRnVQU0kySWo0S1BFZ3hQbFJvWlNCQ2IyUm5aVWwwSUZOMGIzSmxQQzlJTVQ0S1BIUmhZbXhsSUhkcFpIUm9QU0l4TURBbElpQmpiR0Z6Y3oxY0ltNXZZbTl5WkdWeVhDSStDangwY2lCQ1IwTlBURTlTUFNORE0wUTVSa1krQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTXpBbElqNG1ibUp6Y0RzOEwzUmtQZ284ZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJalF3SlNJK1YyVWdZbTlrWjJVZ2FYUXNJSE52SUhsdmRTQmtiMjUwSUdoaGRtVWdkRzhoUEM5MFpENEtQSFJrSUdGc2FXZHVQU0pqWlc1MFpYSWlJSGRwWkhSb1BTSXpNQ1VpSUhOMGVXeGxQU0owWlhoMExXRnNhV2R1T2lCeWFXZG9kQ0lnUGdwSGRXVnpkQ0IxYzJWeUNnbzhMM1J5UGdvOEwzUmhZbXhsUGdvOEwzUmtQZ284TDNSeVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTVRZbElpQkNSME5QVEU5U1BTTkZSVVZGUlVVK1BHRWdhSEpsWmowaWFHOXRaUzVxYzNBaVBraHZiV1U4TDJFK1BDOTBaRDRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUhkcFpIUm9QU0l4TmlVaUlFSkhRMDlNVDFJOUkwVkZSVVZGUlQ0OFlTQm9jbVZtUFNKaFltOTFkQzVxYzNBaVBrRmliM1YwSUZWelBDOWhQand2ZEdRK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQanhoSUdoeVpXWTlJbU52Ym5SaFkzUXVhbk53SWo1RGIyNTBZV04wSUZWelBDOWhQand2ZEdRK0Nqd2hMUzBnZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJakUySlNJK1BHRWdhSEpsWmowaVlXUnRhVzR1YW5Od0lqNUJaRzFwYmp3dllUNDhMM1JrTFMwK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQZ29LQ1FrOFlTQm9jbVZtUFNKc2IyZHBiaTVxYzNBaVBreHZaMmx1UEM5aFBnb0tQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGlZbUZ6YTJWMExtcHpjQ0krV1c5MWNpQkNZWE5yWlhROEwyRStQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGljMlZoY21Ob0xtcHpjQ0krVTJWaGNtTm9QQzloUGp3dmRHUStDand2ZEhJK0NqeDBjajRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUdOdmJITndZVzQ5SWpZaVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpFd01DVWlJR05zWVhOelBTSmliM0prWlhJaVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaWJHVm1kQ0lnZG1Gc2FXZHVQU0owYjNBaUlIZHBaSFJvUFNJeU5TVWlQZ284WVNCb2NtVm1QU0p3Y205a2RXTjBMbXB6Y0Q5MGVYQmxhV1E5TmlJK1JHOXZaR0ZvY3p3dllUNDhZbkl2UGdvOFlTQm9jbVZtUFNKd2NtOWtkV04wTG1wemNEOTBlWEJsYVdROU5TSStSMmw2Ylc5elBDOWhQanhpY2k4K0NqeGhJR2h5WldZOUluQnliMlIxWTNRdWFuTndQM1I1Y0dWcFpEMHpJajVVYUdsdVoyRnRZV3BwWjNNOEwyRStQR0p5THo0S1BHRWdhSEpsWmowaWNISnZaSFZqZEM1cWMzQS9kSGx3Wldsa1BUSWlQbFJvYVc1bmFXVnpQQzloUGp4aWNpOCtDanhoSUdoeVpXWTlJbkJ5YjJSMVkzUXVhbk53UDNSNWNHVnBaRDAzSWo1WGFHRjBZMmhoYldGallXeHNhWFJ6UEM5aFBqeGljaTgrQ2p4aElHaHlaV1k5SW5CeWIyUjFZM1F1YW5Od1AzUjVjR1ZwWkQwMElqNVhhR0YwYzJsMGN6d3ZZVDQ4WW5JdlBnbzhZU0JvY21WbVBTSndjbTlrZFdOMExtcHpjRDkwZVhCbGFXUTlNU0krVjJsa1oyVjBjend2WVQ0OFluSXZQZ29LUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K1BHSnlMejQ4WW5JdlBqeGljaTgrUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K0Nqd3ZkR1ErQ2p4MFpDQjJZV3hwWjI0OUluUnZjQ0lnZDJsa2RHZzlJamN3SlNJK0NnMEtEUW84YURNK1RHOW5hVzQ4TDJnelBnMEtVR3hsWVhObElHVnVkR1Z5SUhsdmRYSWdZM0psWkdWdWRHbGhiSE02SUR4aWNpOCtQR0p5THo0TkNqeG1iM0p0SUcxbGRHaHZaRDBpVUU5VFZDSStEUW9KUEdObGJuUmxjajROQ2drOGRHRmliR1UrRFFvSlBIUnlQZzBLQ1FrOGRHUStWWE5sY201aGJXVTZQQzkwWkQ0TkNna0pQSFJrUGp4cGJuQjFkQ0JwWkQwaWRYTmxjbTVoYldVaUlHNWhiV1U5SW5WelpYSnVZVzFsSWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4ZEhJK0RRb0pDVHgwWkQ1UVlYTnpkMjl5WkRvOEwzUmtQZzBLQ1FrOGRHUStQR2x1Y0hWMElHbGtQU0p3WVhOemQyOXlaQ0lnYm1GdFpUMGljR0Z6YzNkdmNtUWlJSFI1Y0dVOUluQmhjM04zYjNKa0lqNDhMMmx1Y0hWMFBqd3ZkR1ErRFFvSlBDOTBjajROQ2drOGRISStEUW9KQ1R4MFpENDhMM1JrUGcwS0NRazhkR1ErUEdsdWNIVjBJR2xrUFNKemRXSnRhWFFpSUhSNWNHVTlJbk4xWW0xcGRDSWdkbUZzZFdVOUlreHZaMmx1SWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4TDNSaFlteGxQZzBLQ1R3dlkyVnVkR1Z5UGcwS1BDOW1iM0p0UGcwS1NXWWdlVzkxSUdSdmJuUWdhR0YyWlNCaGJpQmhZMk52ZFc1MElIZHBkR2dnZFhNZ2RHaGxiaUJ3YkdWaGMyVWdQR0VnYUhKbFpqMGljbVZuYVhOMFpYSXVhbk53SWo1U1pXZHBjM1JsY2p3dllUNGdibTkzSUdadmNpQmhJR1p5WldVZ1lXTmpiM1Z1ZEM0TkNqeGljaTgrUEdKeUx6NE5DZzBLUEM5MFpENEtQQzkwY2o0S1BDOTBZV0pzWlQ0S1BDOTBaRDRLUEM5MGNqNEtQQzkwWVdKc1pUNEtQQzlqWlc1MFpYSStDand2WW05a2VUNEtQQzlvZEcxc1Bnb05DZzBL" + } + }, + { + "pk": 129, + "model": "dojo.burprawrequestresponse", + "fields": { + "finding": 8, + "burpRequestBase64": "UjBWVUlDOWliMlJuWldsMEwyeHZaMmx1TG1wemNDQklWRlJRTHpFdU1RMEtTRzl6ZERvZ2JHOWpZV3hvYjNOME9qZzRPRGdOQ2xWelpYSXRRV2RsYm5RNklFMXZlbWxzYkdFdk5TNHdJQ2hOWVdOcGJuUnZjMmc3SUVsdWRHVnNJRTFoWXlCUFV5QllJREV3TGpFeE95Qnlkam8wTnk0d0tTQkhaV05yYnk4eU1ERXdNREV3TVNCR2FYSmxabTk0THpRM0xqQU5Da0ZqWTJWd2REb2dkR1Y0ZEM5b2RHMXNMR0Z3Y0d4cFkyRjBhVzl1TDNob2RHMXNLM2h0YkN4aGNIQnNhV05oZEdsdmJpOTRiV3c3Y1Qwd0xqa3NLaThxTzNFOU1DNDREUXBCWTJObGNIUXRUR0Z1WjNWaFoyVTZJR1Z1TFZWVExHVnVPM0U5TUM0MURRcEJZMk5sY0hRdFJXNWpiMlJwYm1jNklHZDZhWEFzSUdSbFpteGhkR1VOQ2xKbFptVnlaWEk2SUdoMGRIQTZMeTlzYjJOaGJHaHZjM1E2T0RnNE9DOWliMlJuWldsMEx3MEtRMjl2YTJsbE9pQktVMFZUVTBsUFRrbEVQVFpGT1RVM04wRXhOa0pCUXpZeE9URXpSRVU1TjBFNE9EZEJSRFl3TWpjMURRcERiMjV1WldOMGFXOXVPaUJqYkc5elpRMEtEUW89", + "burpResponseBase64": "U0ZSVVVDOHhMakVnTWpBd0lBMEtVMlZ5ZG1WeU9pQkJjR0ZqYUdVdFEyOTViM1JsTHpFdU1RMEtRMjl1ZEdWdWRDMVVlWEJsT2lCMFpYaDBMMmgwYld3N1kyaGhjbk5sZEQxSlUwOHRPRGcxT1MweERRcERiMjUwWlc1MExVeGxibWQwYURvZ01qUTJNZzBLUkdGMFpUb2dVMkYwTENBeU55QkJkV2NnTWpBeE5pQXdNam93T0RvMU55QkhUVlFOQ2tOdmJtNWxZM1JwYjI0NklHTnNiM05sRFFvTkNnMEtEUW9OQ2cwS0Nnb0tDandoUkU5RFZGbFFSU0JJVkUxTUlGQlZRa3hKUXlBaUxTOHZWek5ETHk5RVZFUWdTRlJOVENBekxqSXZMMFZPSWo0S1BHaDBiV3crQ2p4b1pXRmtQZ284ZEdsMGJHVStWR2hsSUVKdlpHZGxTWFFnVTNSdmNtVThMM1JwZEd4bFBnbzhiR2x1YXlCb2NtVm1QU0p6ZEhsc1pTNWpjM01pSUhKbGJEMGljM1I1YkdWemFHVmxkQ0lnZEhsd1pUMGlkR1Y0ZEM5amMzTWlJQzgrQ2p4elkzSnBjSFFnZEhsd1pUMGlkR1Y0ZEM5cVlYWmhjMk55YVhCMElpQnpjbU05SWk0dmFuTXZkWFJwYkM1cWN5SStQQzl6WTNKcGNIUStDand2YUdWaFpENEtQR0p2WkhrK0NnbzhZMlZ1ZEdWeVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpnd0pTSWdZMnhoYzNNOUltSnZjbVJsY2lJK0NqeDBjaUJDUjBOUFRFOVNQU05ETTBRNVJrWStDangwWkNCaGJHbG5iajBpWTJWdWRHVnlJaUJqYjJ4emNHRnVQU0kySWo0S1BFZ3hQbFJvWlNCQ2IyUm5aVWwwSUZOMGIzSmxQQzlJTVQ0S1BIUmhZbXhsSUhkcFpIUm9QU0l4TURBbElpQmpiR0Z6Y3oxY0ltNXZZbTl5WkdWeVhDSStDangwY2lCQ1IwTlBURTlTUFNORE0wUTVSa1krQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTXpBbElqNG1ibUp6Y0RzOEwzUmtQZ284ZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJalF3SlNJK1YyVWdZbTlrWjJVZ2FYUXNJSE52SUhsdmRTQmtiMjUwSUdoaGRtVWdkRzhoUEM5MFpENEtQSFJrSUdGc2FXZHVQU0pqWlc1MFpYSWlJSGRwWkhSb1BTSXpNQ1VpSUhOMGVXeGxQU0owWlhoMExXRnNhV2R1T2lCeWFXZG9kQ0lnUGdwSGRXVnpkQ0IxYzJWeUNnbzhMM1J5UGdvOEwzUmhZbXhsUGdvOEwzUmtQZ284TDNSeVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTVRZbElpQkNSME5QVEU5U1BTTkZSVVZGUlVVK1BHRWdhSEpsWmowaWFHOXRaUzVxYzNBaVBraHZiV1U4TDJFK1BDOTBaRDRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUhkcFpIUm9QU0l4TmlVaUlFSkhRMDlNVDFJOUkwVkZSVVZGUlQ0OFlTQm9jbVZtUFNKaFltOTFkQzVxYzNBaVBrRmliM1YwSUZWelBDOWhQand2ZEdRK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQanhoSUdoeVpXWTlJbU52Ym5SaFkzUXVhbk53SWo1RGIyNTBZV04wSUZWelBDOWhQand2ZEdRK0Nqd2hMUzBnZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJakUySlNJK1BHRWdhSEpsWmowaVlXUnRhVzR1YW5Od0lqNUJaRzFwYmp3dllUNDhMM1JrTFMwK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQZ29LQ1FrOFlTQm9jbVZtUFNKc2IyZHBiaTVxYzNBaVBreHZaMmx1UEM5aFBnb0tQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGlZbUZ6YTJWMExtcHpjQ0krV1c5MWNpQkNZWE5yWlhROEwyRStQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGljMlZoY21Ob0xtcHpjQ0krVTJWaGNtTm9QQzloUGp3dmRHUStDand2ZEhJK0NqeDBjajRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUdOdmJITndZVzQ5SWpZaVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpFd01DVWlJR05zWVhOelBTSmliM0prWlhJaVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaWJHVm1kQ0lnZG1Gc2FXZHVQU0owYjNBaUlIZHBaSFJvUFNJeU5TVWlQZ284WVNCb2NtVm1QU0p3Y205a2RXTjBMbXB6Y0Q5MGVYQmxhV1E5TmlJK1JHOXZaR0ZvY3p3dllUNDhZbkl2UGdvOFlTQm9jbVZtUFNKd2NtOWtkV04wTG1wemNEOTBlWEJsYVdROU5TSStSMmw2Ylc5elBDOWhQanhpY2k4K0NqeGhJR2h5WldZOUluQnliMlIxWTNRdWFuTndQM1I1Y0dWcFpEMHpJajVVYUdsdVoyRnRZV3BwWjNNOEwyRStQR0p5THo0S1BHRWdhSEpsWmowaWNISnZaSFZqZEM1cWMzQS9kSGx3Wldsa1BUSWlQbFJvYVc1bmFXVnpQQzloUGp4aWNpOCtDanhoSUdoeVpXWTlJbkJ5YjJSMVkzUXVhbk53UDNSNWNHVnBaRDAzSWo1WGFHRjBZMmhoYldGallXeHNhWFJ6UEM5aFBqeGljaTgrQ2p4aElHaHlaV1k5SW5CeWIyUjFZM1F1YW5Od1AzUjVjR1ZwWkQwMElqNVhhR0YwYzJsMGN6d3ZZVDQ4WW5JdlBnbzhZU0JvY21WbVBTSndjbTlrZFdOMExtcHpjRDkwZVhCbGFXUTlNU0krVjJsa1oyVjBjend2WVQ0OFluSXZQZ29LUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K1BHSnlMejQ4WW5JdlBqeGljaTgrUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K0Nqd3ZkR1ErQ2p4MFpDQjJZV3hwWjI0OUluUnZjQ0lnZDJsa2RHZzlJamN3SlNJK0NnMEtEUW84YURNK1RHOW5hVzQ4TDJnelBnMEtVR3hsWVhObElHVnVkR1Z5SUhsdmRYSWdZM0psWkdWdWRHbGhiSE02SUR4aWNpOCtQR0p5THo0TkNqeG1iM0p0SUcxbGRHaHZaRDBpVUU5VFZDSStEUW9KUEdObGJuUmxjajROQ2drOGRHRmliR1UrRFFvSlBIUnlQZzBLQ1FrOGRHUStWWE5sY201aGJXVTZQQzkwWkQ0TkNna0pQSFJrUGp4cGJuQjFkQ0JwWkQwaWRYTmxjbTVoYldVaUlHNWhiV1U5SW5WelpYSnVZVzFsSWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4ZEhJK0RRb0pDVHgwWkQ1UVlYTnpkMjl5WkRvOEwzUmtQZzBLQ1FrOGRHUStQR2x1Y0hWMElHbGtQU0p3WVhOemQyOXlaQ0lnYm1GdFpUMGljR0Z6YzNkdmNtUWlJSFI1Y0dVOUluQmhjM04zYjNKa0lqNDhMMmx1Y0hWMFBqd3ZkR1ErRFFvSlBDOTBjajROQ2drOGRISStEUW9KQ1R4MFpENDhMM1JrUGcwS0NRazhkR1ErUEdsdWNIVjBJR2xrUFNKemRXSnRhWFFpSUhSNWNHVTlJbk4xWW0xcGRDSWdkbUZzZFdVOUlreHZaMmx1SWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4TDNSaFlteGxQZzBLQ1R3dlkyVnVkR1Z5UGcwS1BDOW1iM0p0UGcwS1NXWWdlVzkxSUdSdmJuUWdhR0YyWlNCaGJpQmhZMk52ZFc1MElIZHBkR2dnZFhNZ2RHaGxiaUJ3YkdWaGMyVWdQR0VnYUhKbFpqMGljbVZuYVhOMFpYSXVhbk53SWo1U1pXZHBjM1JsY2p3dllUNGdibTkzSUdadmNpQmhJR1p5WldVZ1lXTmpiM1Z1ZEM0TkNqeGljaTgrUEdKeUx6NE5DZzBLUEM5MFpENEtQQzkwY2o0S1BDOTBZV0pzWlQ0S1BDOTBaRDRLUEM5MGNqNEtQQzkwWVdKc1pUNEtQQzlqWlc1MFpYSStDand2WW05a2VUNEtQQzlvZEcxc1Bnb05DZzBL" + } + }, + { + "pk": 130, + "model": "dojo.burprawrequestresponse", + "fields": { + "finding": 8, + "burpRequestBase64": "UjBWVUlDOWliMlJuWldsMEwyeHZaMmx1TG1wemNDQklWRlJRTHpFdU1RMEtTRzl6ZERvZ2JHOWpZV3hvYjNOME9qZzRPRGdOQ2xWelpYSXRRV2RsYm5RNklFMXZlbWxzYkdFdk5TNHdJQ2hOWVdOcGJuUnZjMmc3SUVsdWRHVnNJRTFoWXlCUFV5QllJREV3TGpFeE95Qnlkam8wTnk0d0tTQkhaV05yYnk4eU1ERXdNREV3TVNCR2FYSmxabTk0THpRM0xqQU5Da0ZqWTJWd2REb2dkR1Y0ZEM5b2RHMXNMR0Z3Y0d4cFkyRjBhVzl1TDNob2RHMXNLM2h0YkN4aGNIQnNhV05oZEdsdmJpOTRiV3c3Y1Qwd0xqa3NLaThxTzNFOU1DNDREUXBCWTJObGNIUXRUR0Z1WjNWaFoyVTZJR1Z1TFZWVExHVnVPM0U5TUM0MURRcEJZMk5sY0hRdFJXNWpiMlJwYm1jNklHZDZhWEFzSUdSbFpteGhkR1VOQ2xKbFptVnlaWEk2SUdoMGRIQTZMeTlzYjJOaGJHaHZjM1E2T0RnNE9DOWliMlJuWldsMEx3MEtRMjl2YTJsbE9pQktVMFZUVTBsUFRrbEVQVFpGT1RVM04wRXhOa0pCUXpZeE9URXpSRVU1TjBFNE9EZEJSRFl3TWpjMURRcERiMjV1WldOMGFXOXVPaUJqYkc5elpRMEtEUW89", + "burpResponseBase64": "U0ZSVVVDOHhMakVnTWpBd0lBMEtVMlZ5ZG1WeU9pQkJjR0ZqYUdVdFEyOTViM1JsTHpFdU1RMEtRMjl1ZEdWdWRDMVVlWEJsT2lCMFpYaDBMMmgwYld3N1kyaGhjbk5sZEQxSlUwOHRPRGcxT1MweERRcERiMjUwWlc1MExVeGxibWQwYURvZ01qUTJNZzBLUkdGMFpUb2dVMkYwTENBeU55QkJkV2NnTWpBeE5pQXdNam93T0RvMU55QkhUVlFOQ2tOdmJtNWxZM1JwYjI0NklHTnNiM05sRFFvTkNnMEtEUW9OQ2cwS0Nnb0tDandoUkU5RFZGbFFSU0JJVkUxTUlGQlZRa3hKUXlBaUxTOHZWek5ETHk5RVZFUWdTRlJOVENBekxqSXZMMFZPSWo0S1BHaDBiV3crQ2p4b1pXRmtQZ284ZEdsMGJHVStWR2hsSUVKdlpHZGxTWFFnVTNSdmNtVThMM1JwZEd4bFBnbzhiR2x1YXlCb2NtVm1QU0p6ZEhsc1pTNWpjM01pSUhKbGJEMGljM1I1YkdWemFHVmxkQ0lnZEhsd1pUMGlkR1Y0ZEM5amMzTWlJQzgrQ2p4elkzSnBjSFFnZEhsd1pUMGlkR1Y0ZEM5cVlYWmhjMk55YVhCMElpQnpjbU05SWk0dmFuTXZkWFJwYkM1cWN5SStQQzl6WTNKcGNIUStDand2YUdWaFpENEtQR0p2WkhrK0NnbzhZMlZ1ZEdWeVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpnd0pTSWdZMnhoYzNNOUltSnZjbVJsY2lJK0NqeDBjaUJDUjBOUFRFOVNQU05ETTBRNVJrWStDangwWkNCaGJHbG5iajBpWTJWdWRHVnlJaUJqYjJ4emNHRnVQU0kySWo0S1BFZ3hQbFJvWlNCQ2IyUm5aVWwwSUZOMGIzSmxQQzlJTVQ0S1BIUmhZbXhsSUhkcFpIUm9QU0l4TURBbElpQmpiR0Z6Y3oxY0ltNXZZbTl5WkdWeVhDSStDangwY2lCQ1IwTlBURTlTUFNORE0wUTVSa1krQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTXpBbElqNG1ibUp6Y0RzOEwzUmtQZ284ZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJalF3SlNJK1YyVWdZbTlrWjJVZ2FYUXNJSE52SUhsdmRTQmtiMjUwSUdoaGRtVWdkRzhoUEM5MFpENEtQSFJrSUdGc2FXZHVQU0pqWlc1MFpYSWlJSGRwWkhSb1BTSXpNQ1VpSUhOMGVXeGxQU0owWlhoMExXRnNhV2R1T2lCeWFXZG9kQ0lnUGdwSGRXVnpkQ0IxYzJWeUNnbzhMM1J5UGdvOEwzUmhZbXhsUGdvOEwzUmtQZ284TDNSeVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTVRZbElpQkNSME5QVEU5U1BTTkZSVVZGUlVVK1BHRWdhSEpsWmowaWFHOXRaUzVxYzNBaVBraHZiV1U4TDJFK1BDOTBaRDRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUhkcFpIUm9QU0l4TmlVaUlFSkhRMDlNVDFJOUkwVkZSVVZGUlQ0OFlTQm9jbVZtUFNKaFltOTFkQzVxYzNBaVBrRmliM1YwSUZWelBDOWhQand2ZEdRK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQanhoSUdoeVpXWTlJbU52Ym5SaFkzUXVhbk53SWo1RGIyNTBZV04wSUZWelBDOWhQand2ZEdRK0Nqd2hMUzBnZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJakUySlNJK1BHRWdhSEpsWmowaVlXUnRhVzR1YW5Od0lqNUJaRzFwYmp3dllUNDhMM1JrTFMwK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQZ29LQ1FrOFlTQm9jbVZtUFNKc2IyZHBiaTVxYzNBaVBreHZaMmx1UEM5aFBnb0tQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGlZbUZ6YTJWMExtcHpjQ0krV1c5MWNpQkNZWE5yWlhROEwyRStQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGljMlZoY21Ob0xtcHpjQ0krVTJWaGNtTm9QQzloUGp3dmRHUStDand2ZEhJK0NqeDBjajRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUdOdmJITndZVzQ5SWpZaVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpFd01DVWlJR05zWVhOelBTSmliM0prWlhJaVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaWJHVm1kQ0lnZG1Gc2FXZHVQU0owYjNBaUlIZHBaSFJvUFNJeU5TVWlQZ284WVNCb2NtVm1QU0p3Y205a2RXTjBMbXB6Y0Q5MGVYQmxhV1E5TmlJK1JHOXZaR0ZvY3p3dllUNDhZbkl2UGdvOFlTQm9jbVZtUFNKd2NtOWtkV04wTG1wemNEOTBlWEJsYVdROU5TSStSMmw2Ylc5elBDOWhQanhpY2k4K0NqeGhJR2h5WldZOUluQnliMlIxWTNRdWFuTndQM1I1Y0dWcFpEMHpJajVVYUdsdVoyRnRZV3BwWjNNOEwyRStQR0p5THo0S1BHRWdhSEpsWmowaWNISnZaSFZqZEM1cWMzQS9kSGx3Wldsa1BUSWlQbFJvYVc1bmFXVnpQQzloUGp4aWNpOCtDanhoSUdoeVpXWTlJbkJ5YjJSMVkzUXVhbk53UDNSNWNHVnBaRDAzSWo1WGFHRjBZMmhoYldGallXeHNhWFJ6UEM5aFBqeGljaTgrQ2p4aElHaHlaV1k5SW5CeWIyUjFZM1F1YW5Od1AzUjVjR1ZwWkQwMElqNVhhR0YwYzJsMGN6d3ZZVDQ4WW5JdlBnbzhZU0JvY21WbVBTSndjbTlrZFdOMExtcHpjRDkwZVhCbGFXUTlNU0krVjJsa1oyVjBjend2WVQ0OFluSXZQZ29LUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K1BHSnlMejQ4WW5JdlBqeGljaTgrUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K0Nqd3ZkR1ErQ2p4MFpDQjJZV3hwWjI0OUluUnZjQ0lnZDJsa2RHZzlJamN3SlNJK0NnMEtEUW84YURNK1RHOW5hVzQ4TDJnelBnMEtVR3hsWVhObElHVnVkR1Z5SUhsdmRYSWdZM0psWkdWdWRHbGhiSE02SUR4aWNpOCtQR0p5THo0TkNqeG1iM0p0SUcxbGRHaHZaRDBpVUU5VFZDSStEUW9KUEdObGJuUmxjajROQ2drOGRHRmliR1UrRFFvSlBIUnlQZzBLQ1FrOGRHUStWWE5sY201aGJXVTZQQzkwWkQ0TkNna0pQSFJrUGp4cGJuQjFkQ0JwWkQwaWRYTmxjbTVoYldVaUlHNWhiV1U5SW5WelpYSnVZVzFsSWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4ZEhJK0RRb0pDVHgwWkQ1UVlYTnpkMjl5WkRvOEwzUmtQZzBLQ1FrOGRHUStQR2x1Y0hWMElHbGtQU0p3WVhOemQyOXlaQ0lnYm1GdFpUMGljR0Z6YzNkdmNtUWlJSFI1Y0dVOUluQmhjM04zYjNKa0lqNDhMMmx1Y0hWMFBqd3ZkR1ErRFFvSlBDOTBjajROQ2drOGRISStEUW9KQ1R4MFpENDhMM1JrUGcwS0NRazhkR1ErUEdsdWNIVjBJR2xrUFNKemRXSnRhWFFpSUhSNWNHVTlJbk4xWW0xcGRDSWdkbUZzZFdVOUlreHZaMmx1SWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4TDNSaFlteGxQZzBLQ1R3dlkyVnVkR1Z5UGcwS1BDOW1iM0p0UGcwS1NXWWdlVzkxSUdSdmJuUWdhR0YyWlNCaGJpQmhZMk52ZFc1MElIZHBkR2dnZFhNZ2RHaGxiaUJ3YkdWaGMyVWdQR0VnYUhKbFpqMGljbVZuYVhOMFpYSXVhbk53SWo1U1pXZHBjM1JsY2p3dllUNGdibTkzSUdadmNpQmhJR1p5WldVZ1lXTmpiM1Z1ZEM0TkNqeGljaTgrUEdKeUx6NE5DZzBLUEM5MFpENEtQQzkwY2o0S1BDOTBZV0pzWlQ0S1BDOTBaRDRLUEM5MGNqNEtQQzkwWVdKc1pUNEtQQzlqWlc1MFpYSStDand2WW05a2VUNEtQQzlvZEcxc1Bnb05DZzBL" + } + }, + { + "pk": 131, + "model": "dojo.burprawrequestresponse", + "fields": { + "finding": 8, + "burpRequestBase64": "UjBWVUlDOWliMlJuWldsMEwyeHZaMmx1TG1wemNDQklWRlJRTHpFdU1RMEtTRzl6ZERvZ2JHOWpZV3hvYjNOME9qZzRPRGdOQ2xWelpYSXRRV2RsYm5RNklFMXZlbWxzYkdFdk5TNHdJQ2hOWVdOcGJuUnZjMmc3SUVsdWRHVnNJRTFoWXlCUFV5QllJREV3TGpFeE95Qnlkam8wTnk0d0tTQkhaV05yYnk4eU1ERXdNREV3TVNCR2FYSmxabTk0THpRM0xqQU5Da0ZqWTJWd2REb2dkR1Y0ZEM5b2RHMXNMR0Z3Y0d4cFkyRjBhVzl1TDNob2RHMXNLM2h0YkN4aGNIQnNhV05oZEdsdmJpOTRiV3c3Y1Qwd0xqa3NLaThxTzNFOU1DNDREUXBCWTJObGNIUXRUR0Z1WjNWaFoyVTZJR1Z1TFZWVExHVnVPM0U5TUM0MURRcEJZMk5sY0hRdFJXNWpiMlJwYm1jNklHZDZhWEFzSUdSbFpteGhkR1VOQ2xKbFptVnlaWEk2SUdoMGRIQTZMeTlzYjJOaGJHaHZjM1E2T0RnNE9DOWliMlJuWldsMEx3MEtRMjl2YTJsbE9pQktVMFZUVTBsUFRrbEVQVFpGT1RVM04wRXhOa0pCUXpZeE9URXpSRVU1TjBFNE9EZEJSRFl3TWpjMURRcERiMjV1WldOMGFXOXVPaUJqYkc5elpRMEtEUW89", + "burpResponseBase64": "U0ZSVVVDOHhMakVnTWpBd0lBMEtVMlZ5ZG1WeU9pQkJjR0ZqYUdVdFEyOTViM1JsTHpFdU1RMEtRMjl1ZEdWdWRDMVVlWEJsT2lCMFpYaDBMMmgwYld3N1kyaGhjbk5sZEQxSlUwOHRPRGcxT1MweERRcERiMjUwWlc1MExVeGxibWQwYURvZ01qUTJNZzBLUkdGMFpUb2dVMkYwTENBeU55QkJkV2NnTWpBeE5pQXdNam93T0RvMU55QkhUVlFOQ2tOdmJtNWxZM1JwYjI0NklHTnNiM05sRFFvTkNnMEtEUW9OQ2cwS0Nnb0tDandoUkU5RFZGbFFSU0JJVkUxTUlGQlZRa3hKUXlBaUxTOHZWek5ETHk5RVZFUWdTRlJOVENBekxqSXZMMFZPSWo0S1BHaDBiV3crQ2p4b1pXRmtQZ284ZEdsMGJHVStWR2hsSUVKdlpHZGxTWFFnVTNSdmNtVThMM1JwZEd4bFBnbzhiR2x1YXlCb2NtVm1QU0p6ZEhsc1pTNWpjM01pSUhKbGJEMGljM1I1YkdWemFHVmxkQ0lnZEhsd1pUMGlkR1Y0ZEM5amMzTWlJQzgrQ2p4elkzSnBjSFFnZEhsd1pUMGlkR1Y0ZEM5cVlYWmhjMk55YVhCMElpQnpjbU05SWk0dmFuTXZkWFJwYkM1cWN5SStQQzl6WTNKcGNIUStDand2YUdWaFpENEtQR0p2WkhrK0NnbzhZMlZ1ZEdWeVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpnd0pTSWdZMnhoYzNNOUltSnZjbVJsY2lJK0NqeDBjaUJDUjBOUFRFOVNQU05ETTBRNVJrWStDangwWkNCaGJHbG5iajBpWTJWdWRHVnlJaUJqYjJ4emNHRnVQU0kySWo0S1BFZ3hQbFJvWlNCQ2IyUm5aVWwwSUZOMGIzSmxQQzlJTVQ0S1BIUmhZbXhsSUhkcFpIUm9QU0l4TURBbElpQmpiR0Z6Y3oxY0ltNXZZbTl5WkdWeVhDSStDangwY2lCQ1IwTlBURTlTUFNORE0wUTVSa1krQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTXpBbElqNG1ibUp6Y0RzOEwzUmtQZ284ZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJalF3SlNJK1YyVWdZbTlrWjJVZ2FYUXNJSE52SUhsdmRTQmtiMjUwSUdoaGRtVWdkRzhoUEM5MFpENEtQSFJrSUdGc2FXZHVQU0pqWlc1MFpYSWlJSGRwWkhSb1BTSXpNQ1VpSUhOMGVXeGxQU0owWlhoMExXRnNhV2R1T2lCeWFXZG9kQ0lnUGdwSGRXVnpkQ0IxYzJWeUNnbzhMM1J5UGdvOEwzUmhZbXhsUGdvOEwzUmtQZ284TDNSeVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTVRZbElpQkNSME5QVEU5U1BTTkZSVVZGUlVVK1BHRWdhSEpsWmowaWFHOXRaUzVxYzNBaVBraHZiV1U4TDJFK1BDOTBaRDRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUhkcFpIUm9QU0l4TmlVaUlFSkhRMDlNVDFJOUkwVkZSVVZGUlQ0OFlTQm9jbVZtUFNKaFltOTFkQzVxYzNBaVBrRmliM1YwSUZWelBDOWhQand2ZEdRK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQanhoSUdoeVpXWTlJbU52Ym5SaFkzUXVhbk53SWo1RGIyNTBZV04wSUZWelBDOWhQand2ZEdRK0Nqd2hMUzBnZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJakUySlNJK1BHRWdhSEpsWmowaVlXUnRhVzR1YW5Od0lqNUJaRzFwYmp3dllUNDhMM1JrTFMwK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQZ29LQ1FrOFlTQm9jbVZtUFNKc2IyZHBiaTVxYzNBaVBreHZaMmx1UEM5aFBnb0tQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGlZbUZ6YTJWMExtcHpjQ0krV1c5MWNpQkNZWE5yWlhROEwyRStQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGljMlZoY21Ob0xtcHpjQ0krVTJWaGNtTm9QQzloUGp3dmRHUStDand2ZEhJK0NqeDBjajRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUdOdmJITndZVzQ5SWpZaVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpFd01DVWlJR05zWVhOelBTSmliM0prWlhJaVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaWJHVm1kQ0lnZG1Gc2FXZHVQU0owYjNBaUlIZHBaSFJvUFNJeU5TVWlQZ284WVNCb2NtVm1QU0p3Y205a2RXTjBMbXB6Y0Q5MGVYQmxhV1E5TmlJK1JHOXZaR0ZvY3p3dllUNDhZbkl2UGdvOFlTQm9jbVZtUFNKd2NtOWtkV04wTG1wemNEOTBlWEJsYVdROU5TSStSMmw2Ylc5elBDOWhQanhpY2k4K0NqeGhJR2h5WldZOUluQnliMlIxWTNRdWFuTndQM1I1Y0dWcFpEMHpJajVVYUdsdVoyRnRZV3BwWjNNOEwyRStQR0p5THo0S1BHRWdhSEpsWmowaWNISnZaSFZqZEM1cWMzQS9kSGx3Wldsa1BUSWlQbFJvYVc1bmFXVnpQQzloUGp4aWNpOCtDanhoSUdoeVpXWTlJbkJ5YjJSMVkzUXVhbk53UDNSNWNHVnBaRDAzSWo1WGFHRjBZMmhoYldGallXeHNhWFJ6UEM5aFBqeGljaTgrQ2p4aElHaHlaV1k5SW5CeWIyUjFZM1F1YW5Od1AzUjVjR1ZwWkQwMElqNVhhR0YwYzJsMGN6d3ZZVDQ4WW5JdlBnbzhZU0JvY21WbVBTSndjbTlrZFdOMExtcHpjRDkwZVhCbGFXUTlNU0krVjJsa1oyVjBjend2WVQ0OFluSXZQZ29LUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K1BHSnlMejQ4WW5JdlBqeGljaTgrUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K0Nqd3ZkR1ErQ2p4MFpDQjJZV3hwWjI0OUluUnZjQ0lnZDJsa2RHZzlJamN3SlNJK0NnMEtEUW84YURNK1RHOW5hVzQ4TDJnelBnMEtVR3hsWVhObElHVnVkR1Z5SUhsdmRYSWdZM0psWkdWdWRHbGhiSE02SUR4aWNpOCtQR0p5THo0TkNqeG1iM0p0SUcxbGRHaHZaRDBpVUU5VFZDSStEUW9KUEdObGJuUmxjajROQ2drOGRHRmliR1UrRFFvSlBIUnlQZzBLQ1FrOGRHUStWWE5sY201aGJXVTZQQzkwWkQ0TkNna0pQSFJrUGp4cGJuQjFkQ0JwWkQwaWRYTmxjbTVoYldVaUlHNWhiV1U5SW5WelpYSnVZVzFsSWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4ZEhJK0RRb0pDVHgwWkQ1UVlYTnpkMjl5WkRvOEwzUmtQZzBLQ1FrOGRHUStQR2x1Y0hWMElHbGtQU0p3WVhOemQyOXlaQ0lnYm1GdFpUMGljR0Z6YzNkdmNtUWlJSFI1Y0dVOUluQmhjM04zYjNKa0lqNDhMMmx1Y0hWMFBqd3ZkR1ErRFFvSlBDOTBjajROQ2drOGRISStEUW9KQ1R4MFpENDhMM1JrUGcwS0NRazhkR1ErUEdsdWNIVjBJR2xrUFNKemRXSnRhWFFpSUhSNWNHVTlJbk4xWW0xcGRDSWdkbUZzZFdVOUlreHZaMmx1SWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4TDNSaFlteGxQZzBLQ1R3dlkyVnVkR1Z5UGcwS1BDOW1iM0p0UGcwS1NXWWdlVzkxSUdSdmJuUWdhR0YyWlNCaGJpQmhZMk52ZFc1MElIZHBkR2dnZFhNZ2RHaGxiaUJ3YkdWaGMyVWdQR0VnYUhKbFpqMGljbVZuYVhOMFpYSXVhbk53SWo1U1pXZHBjM1JsY2p3dllUNGdibTkzSUdadmNpQmhJR1p5WldVZ1lXTmpiM1Z1ZEM0TkNqeGljaTgrUEdKeUx6NE5DZzBLUEM5MFpENEtQQzkwY2o0S1BDOTBZV0pzWlQ0S1BDOTBaRDRLUEM5MGNqNEtQQzkwWVdKc1pUNEtQQzlqWlc1MFpYSStDand2WW05a2VUNEtQQzlvZEcxc1Bnb05DZzBL" + } + }, + { + "pk": 132, + "model": "dojo.burprawrequestresponse", + "fields": { + "finding": 8, + "burpRequestBase64": "UjBWVUlDOWliMlJuWldsMEwyeHZaMmx1TG1wemNDQklWRlJRTHpFdU1RMEtTRzl6ZERvZ2JHOWpZV3hvYjNOME9qZzRPRGdOQ2xWelpYSXRRV2RsYm5RNklFMXZlbWxzYkdFdk5TNHdJQ2hOWVdOcGJuUnZjMmc3SUVsdWRHVnNJRTFoWXlCUFV5QllJREV3TGpFeE95Qnlkam8wTnk0d0tTQkhaV05yYnk4eU1ERXdNREV3TVNCR2FYSmxabTk0THpRM0xqQU5Da0ZqWTJWd2REb2dkR1Y0ZEM5b2RHMXNMR0Z3Y0d4cFkyRjBhVzl1TDNob2RHMXNLM2h0YkN4aGNIQnNhV05oZEdsdmJpOTRiV3c3Y1Qwd0xqa3NLaThxTzNFOU1DNDREUXBCWTJObGNIUXRUR0Z1WjNWaFoyVTZJR1Z1TFZWVExHVnVPM0U5TUM0MURRcEJZMk5sY0hRdFJXNWpiMlJwYm1jNklHZDZhWEFzSUdSbFpteGhkR1VOQ2xKbFptVnlaWEk2SUdoMGRIQTZMeTlzYjJOaGJHaHZjM1E2T0RnNE9DOWliMlJuWldsMEx3MEtRMjl2YTJsbE9pQktVMFZUVTBsUFRrbEVQVFpGT1RVM04wRXhOa0pCUXpZeE9URXpSRVU1TjBFNE9EZEJSRFl3TWpjMURRcERiMjV1WldOMGFXOXVPaUJqYkc5elpRMEtEUW89", + "burpResponseBase64": "U0ZSVVVDOHhMakVnTWpBd0lBMEtVMlZ5ZG1WeU9pQkJjR0ZqYUdVdFEyOTViM1JsTHpFdU1RMEtRMjl1ZEdWdWRDMVVlWEJsT2lCMFpYaDBMMmgwYld3N1kyaGhjbk5sZEQxSlUwOHRPRGcxT1MweERRcERiMjUwWlc1MExVeGxibWQwYURvZ01qUTJNZzBLUkdGMFpUb2dVMkYwTENBeU55QkJkV2NnTWpBeE5pQXdNam93T0RvMU55QkhUVlFOQ2tOdmJtNWxZM1JwYjI0NklHTnNiM05sRFFvTkNnMEtEUW9OQ2cwS0Nnb0tDandoUkU5RFZGbFFSU0JJVkUxTUlGQlZRa3hKUXlBaUxTOHZWek5ETHk5RVZFUWdTRlJOVENBekxqSXZMMFZPSWo0S1BHaDBiV3crQ2p4b1pXRmtQZ284ZEdsMGJHVStWR2hsSUVKdlpHZGxTWFFnVTNSdmNtVThMM1JwZEd4bFBnbzhiR2x1YXlCb2NtVm1QU0p6ZEhsc1pTNWpjM01pSUhKbGJEMGljM1I1YkdWemFHVmxkQ0lnZEhsd1pUMGlkR1Y0ZEM5amMzTWlJQzgrQ2p4elkzSnBjSFFnZEhsd1pUMGlkR1Y0ZEM5cVlYWmhjMk55YVhCMElpQnpjbU05SWk0dmFuTXZkWFJwYkM1cWN5SStQQzl6WTNKcGNIUStDand2YUdWaFpENEtQR0p2WkhrK0NnbzhZMlZ1ZEdWeVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpnd0pTSWdZMnhoYzNNOUltSnZjbVJsY2lJK0NqeDBjaUJDUjBOUFRFOVNQU05ETTBRNVJrWStDangwWkNCaGJHbG5iajBpWTJWdWRHVnlJaUJqYjJ4emNHRnVQU0kySWo0S1BFZ3hQbFJvWlNCQ2IyUm5aVWwwSUZOMGIzSmxQQzlJTVQ0S1BIUmhZbXhsSUhkcFpIUm9QU0l4TURBbElpQmpiR0Z6Y3oxY0ltNXZZbTl5WkdWeVhDSStDangwY2lCQ1IwTlBURTlTUFNORE0wUTVSa1krQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTXpBbElqNG1ibUp6Y0RzOEwzUmtQZ284ZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJalF3SlNJK1YyVWdZbTlrWjJVZ2FYUXNJSE52SUhsdmRTQmtiMjUwSUdoaGRtVWdkRzhoUEM5MFpENEtQSFJrSUdGc2FXZHVQU0pqWlc1MFpYSWlJSGRwWkhSb1BTSXpNQ1VpSUhOMGVXeGxQU0owWlhoMExXRnNhV2R1T2lCeWFXZG9kQ0lnUGdwSGRXVnpkQ0IxYzJWeUNnbzhMM1J5UGdvOEwzUmhZbXhsUGdvOEwzUmtQZ284TDNSeVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTVRZbElpQkNSME5QVEU5U1BTTkZSVVZGUlVVK1BHRWdhSEpsWmowaWFHOXRaUzVxYzNBaVBraHZiV1U4TDJFK1BDOTBaRDRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUhkcFpIUm9QU0l4TmlVaUlFSkhRMDlNVDFJOUkwVkZSVVZGUlQ0OFlTQm9jbVZtUFNKaFltOTFkQzVxYzNBaVBrRmliM1YwSUZWelBDOWhQand2ZEdRK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQanhoSUdoeVpXWTlJbU52Ym5SaFkzUXVhbk53SWo1RGIyNTBZV04wSUZWelBDOWhQand2ZEdRK0Nqd2hMUzBnZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJakUySlNJK1BHRWdhSEpsWmowaVlXUnRhVzR1YW5Od0lqNUJaRzFwYmp3dllUNDhMM1JrTFMwK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQZ29LQ1FrOFlTQm9jbVZtUFNKc2IyZHBiaTVxYzNBaVBreHZaMmx1UEM5aFBnb0tQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGlZbUZ6YTJWMExtcHpjQ0krV1c5MWNpQkNZWE5yWlhROEwyRStQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGljMlZoY21Ob0xtcHpjQ0krVTJWaGNtTm9QQzloUGp3dmRHUStDand2ZEhJK0NqeDBjajRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUdOdmJITndZVzQ5SWpZaVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpFd01DVWlJR05zWVhOelBTSmliM0prWlhJaVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaWJHVm1kQ0lnZG1Gc2FXZHVQU0owYjNBaUlIZHBaSFJvUFNJeU5TVWlQZ284WVNCb2NtVm1QU0p3Y205a2RXTjBMbXB6Y0Q5MGVYQmxhV1E5TmlJK1JHOXZaR0ZvY3p3dllUNDhZbkl2UGdvOFlTQm9jbVZtUFNKd2NtOWtkV04wTG1wemNEOTBlWEJsYVdROU5TSStSMmw2Ylc5elBDOWhQanhpY2k4K0NqeGhJR2h5WldZOUluQnliMlIxWTNRdWFuTndQM1I1Y0dWcFpEMHpJajVVYUdsdVoyRnRZV3BwWjNNOEwyRStQR0p5THo0S1BHRWdhSEpsWmowaWNISnZaSFZqZEM1cWMzQS9kSGx3Wldsa1BUSWlQbFJvYVc1bmFXVnpQQzloUGp4aWNpOCtDanhoSUdoeVpXWTlJbkJ5YjJSMVkzUXVhbk53UDNSNWNHVnBaRDAzSWo1WGFHRjBZMmhoYldGallXeHNhWFJ6UEM5aFBqeGljaTgrQ2p4aElHaHlaV1k5SW5CeWIyUjFZM1F1YW5Od1AzUjVjR1ZwWkQwMElqNVhhR0YwYzJsMGN6d3ZZVDQ4WW5JdlBnbzhZU0JvY21WbVBTSndjbTlrZFdOMExtcHpjRDkwZVhCbGFXUTlNU0krVjJsa1oyVjBjend2WVQ0OFluSXZQZ29LUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K1BHSnlMejQ4WW5JdlBqeGljaTgrUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K0Nqd3ZkR1ErQ2p4MFpDQjJZV3hwWjI0OUluUnZjQ0lnZDJsa2RHZzlJamN3SlNJK0NnMEtEUW84YURNK1RHOW5hVzQ4TDJnelBnMEtVR3hsWVhObElHVnVkR1Z5SUhsdmRYSWdZM0psWkdWdWRHbGhiSE02SUR4aWNpOCtQR0p5THo0TkNqeG1iM0p0SUcxbGRHaHZaRDBpVUU5VFZDSStEUW9KUEdObGJuUmxjajROQ2drOGRHRmliR1UrRFFvSlBIUnlQZzBLQ1FrOGRHUStWWE5sY201aGJXVTZQQzkwWkQ0TkNna0pQSFJrUGp4cGJuQjFkQ0JwWkQwaWRYTmxjbTVoYldVaUlHNWhiV1U5SW5WelpYSnVZVzFsSWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4ZEhJK0RRb0pDVHgwWkQ1UVlYTnpkMjl5WkRvOEwzUmtQZzBLQ1FrOGRHUStQR2x1Y0hWMElHbGtQU0p3WVhOemQyOXlaQ0lnYm1GdFpUMGljR0Z6YzNkdmNtUWlJSFI1Y0dVOUluQmhjM04zYjNKa0lqNDhMMmx1Y0hWMFBqd3ZkR1ErRFFvSlBDOTBjajROQ2drOGRISStEUW9KQ1R4MFpENDhMM1JrUGcwS0NRazhkR1ErUEdsdWNIVjBJR2xrUFNKemRXSnRhWFFpSUhSNWNHVTlJbk4xWW0xcGRDSWdkbUZzZFdVOUlreHZaMmx1SWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4TDNSaFlteGxQZzBLQ1R3dlkyVnVkR1Z5UGcwS1BDOW1iM0p0UGcwS1NXWWdlVzkxSUdSdmJuUWdhR0YyWlNCaGJpQmhZMk52ZFc1MElIZHBkR2dnZFhNZ2RHaGxiaUJ3YkdWaGMyVWdQR0VnYUhKbFpqMGljbVZuYVhOMFpYSXVhbk53SWo1U1pXZHBjM1JsY2p3dllUNGdibTkzSUdadmNpQmhJR1p5WldVZ1lXTmpiM1Z1ZEM0TkNqeGljaTgrUEdKeUx6NE5DZzBLUEM5MFpENEtQQzkwY2o0S1BDOTBZV0pzWlQ0S1BDOTBaRDRLUEM5MGNqNEtQQzkwWVdKc1pUNEtQQzlqWlc1MFpYSStDand2WW05a2VUNEtQQzlvZEcxc1Bnb05DZzBL" + } + }, + { + "pk": 133, + "model": "dojo.burprawrequestresponse", + "fields": { + "finding": 8, + "burpRequestBase64": "UjBWVUlDOWliMlJuWldsMEwyeHZaMmx1TG1wemNDQklWRlJRTHpFdU1RMEtTRzl6ZERvZ2JHOWpZV3hvYjNOME9qZzRPRGdOQ2xWelpYSXRRV2RsYm5RNklFMXZlbWxzYkdFdk5TNHdJQ2hOWVdOcGJuUnZjMmc3SUVsdWRHVnNJRTFoWXlCUFV5QllJREV3TGpFeE95Qnlkam8wTnk0d0tTQkhaV05yYnk4eU1ERXdNREV3TVNCR2FYSmxabTk0THpRM0xqQU5Da0ZqWTJWd2REb2dkR1Y0ZEM5b2RHMXNMR0Z3Y0d4cFkyRjBhVzl1TDNob2RHMXNLM2h0YkN4aGNIQnNhV05oZEdsdmJpOTRiV3c3Y1Qwd0xqa3NLaThxTzNFOU1DNDREUXBCWTJObGNIUXRUR0Z1WjNWaFoyVTZJR1Z1TFZWVExHVnVPM0U5TUM0MURRcEJZMk5sY0hRdFJXNWpiMlJwYm1jNklHZDZhWEFzSUdSbFpteGhkR1VOQ2xKbFptVnlaWEk2SUdoMGRIQTZMeTlzYjJOaGJHaHZjM1E2T0RnNE9DOWliMlJuWldsMEx3MEtRMjl2YTJsbE9pQktVMFZUVTBsUFRrbEVQVFpGT1RVM04wRXhOa0pCUXpZeE9URXpSRVU1TjBFNE9EZEJSRFl3TWpjMURRcERiMjV1WldOMGFXOXVPaUJqYkc5elpRMEtEUW89", + "burpResponseBase64": "U0ZSVVVDOHhMakVnTWpBd0lBMEtVMlZ5ZG1WeU9pQkJjR0ZqYUdVdFEyOTViM1JsTHpFdU1RMEtRMjl1ZEdWdWRDMVVlWEJsT2lCMFpYaDBMMmgwYld3N1kyaGhjbk5sZEQxSlUwOHRPRGcxT1MweERRcERiMjUwWlc1MExVeGxibWQwYURvZ01qUTJNZzBLUkdGMFpUb2dVMkYwTENBeU55QkJkV2NnTWpBeE5pQXdNam93T0RvMU55QkhUVlFOQ2tOdmJtNWxZM1JwYjI0NklHTnNiM05sRFFvTkNnMEtEUW9OQ2cwS0Nnb0tDandoUkU5RFZGbFFSU0JJVkUxTUlGQlZRa3hKUXlBaUxTOHZWek5ETHk5RVZFUWdTRlJOVENBekxqSXZMMFZPSWo0S1BHaDBiV3crQ2p4b1pXRmtQZ284ZEdsMGJHVStWR2hsSUVKdlpHZGxTWFFnVTNSdmNtVThMM1JwZEd4bFBnbzhiR2x1YXlCb2NtVm1QU0p6ZEhsc1pTNWpjM01pSUhKbGJEMGljM1I1YkdWemFHVmxkQ0lnZEhsd1pUMGlkR1Y0ZEM5amMzTWlJQzgrQ2p4elkzSnBjSFFnZEhsd1pUMGlkR1Y0ZEM5cVlYWmhjMk55YVhCMElpQnpjbU05SWk0dmFuTXZkWFJwYkM1cWN5SStQQzl6WTNKcGNIUStDand2YUdWaFpENEtQR0p2WkhrK0NnbzhZMlZ1ZEdWeVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpnd0pTSWdZMnhoYzNNOUltSnZjbVJsY2lJK0NqeDBjaUJDUjBOUFRFOVNQU05ETTBRNVJrWStDangwWkNCaGJHbG5iajBpWTJWdWRHVnlJaUJqYjJ4emNHRnVQU0kySWo0S1BFZ3hQbFJvWlNCQ2IyUm5aVWwwSUZOMGIzSmxQQzlJTVQ0S1BIUmhZbXhsSUhkcFpIUm9QU0l4TURBbElpQmpiR0Z6Y3oxY0ltNXZZbTl5WkdWeVhDSStDangwY2lCQ1IwTlBURTlTUFNORE0wUTVSa1krQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTXpBbElqNG1ibUp6Y0RzOEwzUmtQZ284ZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJalF3SlNJK1YyVWdZbTlrWjJVZ2FYUXNJSE52SUhsdmRTQmtiMjUwSUdoaGRtVWdkRzhoUEM5MFpENEtQSFJrSUdGc2FXZHVQU0pqWlc1MFpYSWlJSGRwWkhSb1BTSXpNQ1VpSUhOMGVXeGxQU0owWlhoMExXRnNhV2R1T2lCeWFXZG9kQ0lnUGdwSGRXVnpkQ0IxYzJWeUNnbzhMM1J5UGdvOEwzUmhZbXhsUGdvOEwzUmtQZ284TDNSeVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTVRZbElpQkNSME5QVEU5U1BTTkZSVVZGUlVVK1BHRWdhSEpsWmowaWFHOXRaUzVxYzNBaVBraHZiV1U4TDJFK1BDOTBaRDRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUhkcFpIUm9QU0l4TmlVaUlFSkhRMDlNVDFJOUkwVkZSVVZGUlQ0OFlTQm9jbVZtUFNKaFltOTFkQzVxYzNBaVBrRmliM1YwSUZWelBDOWhQand2ZEdRK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQanhoSUdoeVpXWTlJbU52Ym5SaFkzUXVhbk53SWo1RGIyNTBZV04wSUZWelBDOWhQand2ZEdRK0Nqd2hMUzBnZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJakUySlNJK1BHRWdhSEpsWmowaVlXUnRhVzR1YW5Od0lqNUJaRzFwYmp3dllUNDhMM1JrTFMwK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQZ29LQ1FrOFlTQm9jbVZtUFNKc2IyZHBiaTVxYzNBaVBreHZaMmx1UEM5aFBnb0tQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGlZbUZ6YTJWMExtcHpjQ0krV1c5MWNpQkNZWE5yWlhROEwyRStQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGljMlZoY21Ob0xtcHpjQ0krVTJWaGNtTm9QQzloUGp3dmRHUStDand2ZEhJK0NqeDBjajRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUdOdmJITndZVzQ5SWpZaVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpFd01DVWlJR05zWVhOelBTSmliM0prWlhJaVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaWJHVm1kQ0lnZG1Gc2FXZHVQU0owYjNBaUlIZHBaSFJvUFNJeU5TVWlQZ284WVNCb2NtVm1QU0p3Y205a2RXTjBMbXB6Y0Q5MGVYQmxhV1E5TmlJK1JHOXZaR0ZvY3p3dllUNDhZbkl2UGdvOFlTQm9jbVZtUFNKd2NtOWtkV04wTG1wemNEOTBlWEJsYVdROU5TSStSMmw2Ylc5elBDOWhQanhpY2k4K0NqeGhJR2h5WldZOUluQnliMlIxWTNRdWFuTndQM1I1Y0dWcFpEMHpJajVVYUdsdVoyRnRZV3BwWjNNOEwyRStQR0p5THo0S1BHRWdhSEpsWmowaWNISnZaSFZqZEM1cWMzQS9kSGx3Wldsa1BUSWlQbFJvYVc1bmFXVnpQQzloUGp4aWNpOCtDanhoSUdoeVpXWTlJbkJ5YjJSMVkzUXVhbk53UDNSNWNHVnBaRDAzSWo1WGFHRjBZMmhoYldGallXeHNhWFJ6UEM5aFBqeGljaTgrQ2p4aElHaHlaV1k5SW5CeWIyUjFZM1F1YW5Od1AzUjVjR1ZwWkQwMElqNVhhR0YwYzJsMGN6d3ZZVDQ4WW5JdlBnbzhZU0JvY21WbVBTSndjbTlrZFdOMExtcHpjRDkwZVhCbGFXUTlNU0krVjJsa1oyVjBjend2WVQ0OFluSXZQZ29LUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K1BHSnlMejQ4WW5JdlBqeGljaTgrUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K0Nqd3ZkR1ErQ2p4MFpDQjJZV3hwWjI0OUluUnZjQ0lnZDJsa2RHZzlJamN3SlNJK0NnMEtEUW84YURNK1RHOW5hVzQ4TDJnelBnMEtVR3hsWVhObElHVnVkR1Z5SUhsdmRYSWdZM0psWkdWdWRHbGhiSE02SUR4aWNpOCtQR0p5THo0TkNqeG1iM0p0SUcxbGRHaHZaRDBpVUU5VFZDSStEUW9KUEdObGJuUmxjajROQ2drOGRHRmliR1UrRFFvSlBIUnlQZzBLQ1FrOGRHUStWWE5sY201aGJXVTZQQzkwWkQ0TkNna0pQSFJrUGp4cGJuQjFkQ0JwWkQwaWRYTmxjbTVoYldVaUlHNWhiV1U5SW5WelpYSnVZVzFsSWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4ZEhJK0RRb0pDVHgwWkQ1UVlYTnpkMjl5WkRvOEwzUmtQZzBLQ1FrOGRHUStQR2x1Y0hWMElHbGtQU0p3WVhOemQyOXlaQ0lnYm1GdFpUMGljR0Z6YzNkdmNtUWlJSFI1Y0dVOUluQmhjM04zYjNKa0lqNDhMMmx1Y0hWMFBqd3ZkR1ErRFFvSlBDOTBjajROQ2drOGRISStEUW9KQ1R4MFpENDhMM1JrUGcwS0NRazhkR1ErUEdsdWNIVjBJR2xrUFNKemRXSnRhWFFpSUhSNWNHVTlJbk4xWW0xcGRDSWdkbUZzZFdVOUlreHZaMmx1SWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4TDNSaFlteGxQZzBLQ1R3dlkyVnVkR1Z5UGcwS1BDOW1iM0p0UGcwS1NXWWdlVzkxSUdSdmJuUWdhR0YyWlNCaGJpQmhZMk52ZFc1MElIZHBkR2dnZFhNZ2RHaGxiaUJ3YkdWaGMyVWdQR0VnYUhKbFpqMGljbVZuYVhOMFpYSXVhbk53SWo1U1pXZHBjM1JsY2p3dllUNGdibTkzSUdadmNpQmhJR1p5WldVZ1lXTmpiM1Z1ZEM0TkNqeGljaTgrUEdKeUx6NE5DZzBLUEM5MFpENEtQQzkwY2o0S1BDOTBZV0pzWlQ0S1BDOTBaRDRLUEM5MGNqNEtQQzkwWVdKc1pUNEtQQzlqWlc1MFpYSStDand2WW05a2VUNEtQQzlvZEcxc1Bnb05DZzBL" + } + }, + { + "pk": 134, + "model": "dojo.burprawrequestresponse", + "fields": { + "finding": 8, + "burpRequestBase64": "UjBWVUlDOWliMlJuWldsMEwyeHZaMmx1TG1wemNDQklWRlJRTHpFdU1RMEtTRzl6ZERvZ2JHOWpZV3hvYjNOME9qZzRPRGdOQ2xWelpYSXRRV2RsYm5RNklFMXZlbWxzYkdFdk5TNHdJQ2hOWVdOcGJuUnZjMmc3SUVsdWRHVnNJRTFoWXlCUFV5QllJREV3TGpFeE95Qnlkam8wTnk0d0tTQkhaV05yYnk4eU1ERXdNREV3TVNCR2FYSmxabTk0THpRM0xqQU5Da0ZqWTJWd2REb2dkR1Y0ZEM5b2RHMXNMR0Z3Y0d4cFkyRjBhVzl1TDNob2RHMXNLM2h0YkN4aGNIQnNhV05oZEdsdmJpOTRiV3c3Y1Qwd0xqa3NLaThxTzNFOU1DNDREUXBCWTJObGNIUXRUR0Z1WjNWaFoyVTZJR1Z1TFZWVExHVnVPM0U5TUM0MURRcEJZMk5sY0hRdFJXNWpiMlJwYm1jNklHZDZhWEFzSUdSbFpteGhkR1VOQ2xKbFptVnlaWEk2SUdoMGRIQTZMeTlzYjJOaGJHaHZjM1E2T0RnNE9DOWliMlJuWldsMEx3MEtRMjl2YTJsbE9pQktVMFZUVTBsUFRrbEVQVFpGT1RVM04wRXhOa0pCUXpZeE9URXpSRVU1TjBFNE9EZEJSRFl3TWpjMURRcERiMjV1WldOMGFXOXVPaUJqYkc5elpRMEtEUW89", + "burpResponseBase64": "U0ZSVVVDOHhMakVnTWpBd0lBMEtVMlZ5ZG1WeU9pQkJjR0ZqYUdVdFEyOTViM1JsTHpFdU1RMEtRMjl1ZEdWdWRDMVVlWEJsT2lCMFpYaDBMMmgwYld3N1kyaGhjbk5sZEQxSlUwOHRPRGcxT1MweERRcERiMjUwWlc1MExVeGxibWQwYURvZ01qUTJNZzBLUkdGMFpUb2dVMkYwTENBeU55QkJkV2NnTWpBeE5pQXdNam93T0RvMU55QkhUVlFOQ2tOdmJtNWxZM1JwYjI0NklHTnNiM05sRFFvTkNnMEtEUW9OQ2cwS0Nnb0tDandoUkU5RFZGbFFSU0JJVkUxTUlGQlZRa3hKUXlBaUxTOHZWek5ETHk5RVZFUWdTRlJOVENBekxqSXZMMFZPSWo0S1BHaDBiV3crQ2p4b1pXRmtQZ284ZEdsMGJHVStWR2hsSUVKdlpHZGxTWFFnVTNSdmNtVThMM1JwZEd4bFBnbzhiR2x1YXlCb2NtVm1QU0p6ZEhsc1pTNWpjM01pSUhKbGJEMGljM1I1YkdWemFHVmxkQ0lnZEhsd1pUMGlkR1Y0ZEM5amMzTWlJQzgrQ2p4elkzSnBjSFFnZEhsd1pUMGlkR1Y0ZEM5cVlYWmhjMk55YVhCMElpQnpjbU05SWk0dmFuTXZkWFJwYkM1cWN5SStQQzl6WTNKcGNIUStDand2YUdWaFpENEtQR0p2WkhrK0NnbzhZMlZ1ZEdWeVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpnd0pTSWdZMnhoYzNNOUltSnZjbVJsY2lJK0NqeDBjaUJDUjBOUFRFOVNQU05ETTBRNVJrWStDangwWkNCaGJHbG5iajBpWTJWdWRHVnlJaUJqYjJ4emNHRnVQU0kySWo0S1BFZ3hQbFJvWlNCQ2IyUm5aVWwwSUZOMGIzSmxQQzlJTVQ0S1BIUmhZbXhsSUhkcFpIUm9QU0l4TURBbElpQmpiR0Z6Y3oxY0ltNXZZbTl5WkdWeVhDSStDangwY2lCQ1IwTlBURTlTUFNORE0wUTVSa1krQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTXpBbElqNG1ibUp6Y0RzOEwzUmtQZ284ZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJalF3SlNJK1YyVWdZbTlrWjJVZ2FYUXNJSE52SUhsdmRTQmtiMjUwSUdoaGRtVWdkRzhoUEM5MFpENEtQSFJrSUdGc2FXZHVQU0pqWlc1MFpYSWlJSGRwWkhSb1BTSXpNQ1VpSUhOMGVXeGxQU0owWlhoMExXRnNhV2R1T2lCeWFXZG9kQ0lnUGdwSGRXVnpkQ0IxYzJWeUNnbzhMM1J5UGdvOEwzUmhZbXhsUGdvOEwzUmtQZ284TDNSeVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTVRZbElpQkNSME5QVEU5U1BTTkZSVVZGUlVVK1BHRWdhSEpsWmowaWFHOXRaUzVxYzNBaVBraHZiV1U4TDJFK1BDOTBaRDRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUhkcFpIUm9QU0l4TmlVaUlFSkhRMDlNVDFJOUkwVkZSVVZGUlQ0OFlTQm9jbVZtUFNKaFltOTFkQzVxYzNBaVBrRmliM1YwSUZWelBDOWhQand2ZEdRK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQanhoSUdoeVpXWTlJbU52Ym5SaFkzUXVhbk53SWo1RGIyNTBZV04wSUZWelBDOWhQand2ZEdRK0Nqd2hMUzBnZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJakUySlNJK1BHRWdhSEpsWmowaVlXUnRhVzR1YW5Od0lqNUJaRzFwYmp3dllUNDhMM1JrTFMwK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQZ29LQ1FrOFlTQm9jbVZtUFNKc2IyZHBiaTVxYzNBaVBreHZaMmx1UEM5aFBnb0tQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGlZbUZ6YTJWMExtcHpjQ0krV1c5MWNpQkNZWE5yWlhROEwyRStQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGljMlZoY21Ob0xtcHpjQ0krVTJWaGNtTm9QQzloUGp3dmRHUStDand2ZEhJK0NqeDBjajRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUdOdmJITndZVzQ5SWpZaVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpFd01DVWlJR05zWVhOelBTSmliM0prWlhJaVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaWJHVm1kQ0lnZG1Gc2FXZHVQU0owYjNBaUlIZHBaSFJvUFNJeU5TVWlQZ284WVNCb2NtVm1QU0p3Y205a2RXTjBMbXB6Y0Q5MGVYQmxhV1E5TmlJK1JHOXZaR0ZvY3p3dllUNDhZbkl2UGdvOFlTQm9jbVZtUFNKd2NtOWtkV04wTG1wemNEOTBlWEJsYVdROU5TSStSMmw2Ylc5elBDOWhQanhpY2k4K0NqeGhJR2h5WldZOUluQnliMlIxWTNRdWFuTndQM1I1Y0dWcFpEMHpJajVVYUdsdVoyRnRZV3BwWjNNOEwyRStQR0p5THo0S1BHRWdhSEpsWmowaWNISnZaSFZqZEM1cWMzQS9kSGx3Wldsa1BUSWlQbFJvYVc1bmFXVnpQQzloUGp4aWNpOCtDanhoSUdoeVpXWTlJbkJ5YjJSMVkzUXVhbk53UDNSNWNHVnBaRDAzSWo1WGFHRjBZMmhoYldGallXeHNhWFJ6UEM5aFBqeGljaTgrQ2p4aElHaHlaV1k5SW5CeWIyUjFZM1F1YW5Od1AzUjVjR1ZwWkQwMElqNVhhR0YwYzJsMGN6d3ZZVDQ4WW5JdlBnbzhZU0JvY21WbVBTSndjbTlrZFdOMExtcHpjRDkwZVhCbGFXUTlNU0krVjJsa1oyVjBjend2WVQ0OFluSXZQZ29LUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K1BHSnlMejQ4WW5JdlBqeGljaTgrUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K0Nqd3ZkR1ErQ2p4MFpDQjJZV3hwWjI0OUluUnZjQ0lnZDJsa2RHZzlJamN3SlNJK0NnMEtEUW84YURNK1RHOW5hVzQ4TDJnelBnMEtVR3hsWVhObElHVnVkR1Z5SUhsdmRYSWdZM0psWkdWdWRHbGhiSE02SUR4aWNpOCtQR0p5THo0TkNqeG1iM0p0SUcxbGRHaHZaRDBpVUU5VFZDSStEUW9KUEdObGJuUmxjajROQ2drOGRHRmliR1UrRFFvSlBIUnlQZzBLQ1FrOGRHUStWWE5sY201aGJXVTZQQzkwWkQ0TkNna0pQSFJrUGp4cGJuQjFkQ0JwWkQwaWRYTmxjbTVoYldVaUlHNWhiV1U5SW5WelpYSnVZVzFsSWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4ZEhJK0RRb0pDVHgwWkQ1UVlYTnpkMjl5WkRvOEwzUmtQZzBLQ1FrOGRHUStQR2x1Y0hWMElHbGtQU0p3WVhOemQyOXlaQ0lnYm1GdFpUMGljR0Z6YzNkdmNtUWlJSFI1Y0dVOUluQmhjM04zYjNKa0lqNDhMMmx1Y0hWMFBqd3ZkR1ErRFFvSlBDOTBjajROQ2drOGRISStEUW9KQ1R4MFpENDhMM1JrUGcwS0NRazhkR1ErUEdsdWNIVjBJR2xrUFNKemRXSnRhWFFpSUhSNWNHVTlJbk4xWW0xcGRDSWdkbUZzZFdVOUlreHZaMmx1SWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4TDNSaFlteGxQZzBLQ1R3dlkyVnVkR1Z5UGcwS1BDOW1iM0p0UGcwS1NXWWdlVzkxSUdSdmJuUWdhR0YyWlNCaGJpQmhZMk52ZFc1MElIZHBkR2dnZFhNZ2RHaGxiaUJ3YkdWaGMyVWdQR0VnYUhKbFpqMGljbVZuYVhOMFpYSXVhbk53SWo1U1pXZHBjM1JsY2p3dllUNGdibTkzSUdadmNpQmhJR1p5WldVZ1lXTmpiM1Z1ZEM0TkNqeGljaTgrUEdKeUx6NE5DZzBLUEM5MFpENEtQQzkwY2o0S1BDOTBZV0pzWlQ0S1BDOTBaRDRLUEM5MGNqNEtQQzkwWVdKc1pUNEtQQzlqWlc1MFpYSStDand2WW05a2VUNEtQQzlvZEcxc1Bnb05DZzBL" + } + }, + { + "pk": 135, + "model": "dojo.burprawrequestresponse", + "fields": { + "finding": 8, + "burpRequestBase64": "UjBWVUlDOWliMlJuWldsMEwyeHZaMmx1TG1wemNDQklWRlJRTHpFdU1RMEtTRzl6ZERvZ2JHOWpZV3hvYjNOME9qZzRPRGdOQ2xWelpYSXRRV2RsYm5RNklFMXZlbWxzYkdFdk5TNHdJQ2hOWVdOcGJuUnZjMmc3SUVsdWRHVnNJRTFoWXlCUFV5QllJREV3TGpFeE95Qnlkam8wTnk0d0tTQkhaV05yYnk4eU1ERXdNREV3TVNCR2FYSmxabTk0THpRM0xqQU5Da0ZqWTJWd2REb2dkR1Y0ZEM5b2RHMXNMR0Z3Y0d4cFkyRjBhVzl1TDNob2RHMXNLM2h0YkN4aGNIQnNhV05oZEdsdmJpOTRiV3c3Y1Qwd0xqa3NLaThxTzNFOU1DNDREUXBCWTJObGNIUXRUR0Z1WjNWaFoyVTZJR1Z1TFZWVExHVnVPM0U5TUM0MURRcEJZMk5sY0hRdFJXNWpiMlJwYm1jNklHZDZhWEFzSUdSbFpteGhkR1VOQ2xKbFptVnlaWEk2SUdoMGRIQTZMeTlzYjJOaGJHaHZjM1E2T0RnNE9DOWliMlJuWldsMEx3MEtRMjl2YTJsbE9pQktVMFZUVTBsUFRrbEVQVFpGT1RVM04wRXhOa0pCUXpZeE9URXpSRVU1TjBFNE9EZEJSRFl3TWpjMURRcERiMjV1WldOMGFXOXVPaUJqYkc5elpRMEtEUW89", + "burpResponseBase64": "U0ZSVVVDOHhMakVnTWpBd0lBMEtVMlZ5ZG1WeU9pQkJjR0ZqYUdVdFEyOTViM1JsTHpFdU1RMEtRMjl1ZEdWdWRDMVVlWEJsT2lCMFpYaDBMMmgwYld3N1kyaGhjbk5sZEQxSlUwOHRPRGcxT1MweERRcERiMjUwWlc1MExVeGxibWQwYURvZ01qUTJNZzBLUkdGMFpUb2dVMkYwTENBeU55QkJkV2NnTWpBeE5pQXdNam93T0RvMU55QkhUVlFOQ2tOdmJtNWxZM1JwYjI0NklHTnNiM05sRFFvTkNnMEtEUW9OQ2cwS0Nnb0tDandoUkU5RFZGbFFSU0JJVkUxTUlGQlZRa3hKUXlBaUxTOHZWek5ETHk5RVZFUWdTRlJOVENBekxqSXZMMFZPSWo0S1BHaDBiV3crQ2p4b1pXRmtQZ284ZEdsMGJHVStWR2hsSUVKdlpHZGxTWFFnVTNSdmNtVThMM1JwZEd4bFBnbzhiR2x1YXlCb2NtVm1QU0p6ZEhsc1pTNWpjM01pSUhKbGJEMGljM1I1YkdWemFHVmxkQ0lnZEhsd1pUMGlkR1Y0ZEM5amMzTWlJQzgrQ2p4elkzSnBjSFFnZEhsd1pUMGlkR1Y0ZEM5cVlYWmhjMk55YVhCMElpQnpjbU05SWk0dmFuTXZkWFJwYkM1cWN5SStQQzl6WTNKcGNIUStDand2YUdWaFpENEtQR0p2WkhrK0NnbzhZMlZ1ZEdWeVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpnd0pTSWdZMnhoYzNNOUltSnZjbVJsY2lJK0NqeDBjaUJDUjBOUFRFOVNQU05ETTBRNVJrWStDangwWkNCaGJHbG5iajBpWTJWdWRHVnlJaUJqYjJ4emNHRnVQU0kySWo0S1BFZ3hQbFJvWlNCQ2IyUm5aVWwwSUZOMGIzSmxQQzlJTVQ0S1BIUmhZbXhsSUhkcFpIUm9QU0l4TURBbElpQmpiR0Z6Y3oxY0ltNXZZbTl5WkdWeVhDSStDangwY2lCQ1IwTlBURTlTUFNORE0wUTVSa1krQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTXpBbElqNG1ibUp6Y0RzOEwzUmtQZ284ZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJalF3SlNJK1YyVWdZbTlrWjJVZ2FYUXNJSE52SUhsdmRTQmtiMjUwSUdoaGRtVWdkRzhoUEM5MFpENEtQSFJrSUdGc2FXZHVQU0pqWlc1MFpYSWlJSGRwWkhSb1BTSXpNQ1VpSUhOMGVXeGxQU0owWlhoMExXRnNhV2R1T2lCeWFXZG9kQ0lnUGdwSGRXVnpkQ0IxYzJWeUNnbzhMM1J5UGdvOEwzUmhZbXhsUGdvOEwzUmtQZ284TDNSeVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTVRZbElpQkNSME5QVEU5U1BTTkZSVVZGUlVVK1BHRWdhSEpsWmowaWFHOXRaUzVxYzNBaVBraHZiV1U4TDJFK1BDOTBaRDRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUhkcFpIUm9QU0l4TmlVaUlFSkhRMDlNVDFJOUkwVkZSVVZGUlQ0OFlTQm9jbVZtUFNKaFltOTFkQzVxYzNBaVBrRmliM1YwSUZWelBDOWhQand2ZEdRK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQanhoSUdoeVpXWTlJbU52Ym5SaFkzUXVhbk53SWo1RGIyNTBZV04wSUZWelBDOWhQand2ZEdRK0Nqd2hMUzBnZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJakUySlNJK1BHRWdhSEpsWmowaVlXUnRhVzR1YW5Od0lqNUJaRzFwYmp3dllUNDhMM1JrTFMwK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQZ29LQ1FrOFlTQm9jbVZtUFNKc2IyZHBiaTVxYzNBaVBreHZaMmx1UEM5aFBnb0tQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGlZbUZ6YTJWMExtcHpjQ0krV1c5MWNpQkNZWE5yWlhROEwyRStQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGljMlZoY21Ob0xtcHpjQ0krVTJWaGNtTm9QQzloUGp3dmRHUStDand2ZEhJK0NqeDBjajRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUdOdmJITndZVzQ5SWpZaVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpFd01DVWlJR05zWVhOelBTSmliM0prWlhJaVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaWJHVm1kQ0lnZG1Gc2FXZHVQU0owYjNBaUlIZHBaSFJvUFNJeU5TVWlQZ284WVNCb2NtVm1QU0p3Y205a2RXTjBMbXB6Y0Q5MGVYQmxhV1E5TmlJK1JHOXZaR0ZvY3p3dllUNDhZbkl2UGdvOFlTQm9jbVZtUFNKd2NtOWtkV04wTG1wemNEOTBlWEJsYVdROU5TSStSMmw2Ylc5elBDOWhQanhpY2k4K0NqeGhJR2h5WldZOUluQnliMlIxWTNRdWFuTndQM1I1Y0dWcFpEMHpJajVVYUdsdVoyRnRZV3BwWjNNOEwyRStQR0p5THo0S1BHRWdhSEpsWmowaWNISnZaSFZqZEM1cWMzQS9kSGx3Wldsa1BUSWlQbFJvYVc1bmFXVnpQQzloUGp4aWNpOCtDanhoSUdoeVpXWTlJbkJ5YjJSMVkzUXVhbk53UDNSNWNHVnBaRDAzSWo1WGFHRjBZMmhoYldGallXeHNhWFJ6UEM5aFBqeGljaTgrQ2p4aElHaHlaV1k5SW5CeWIyUjFZM1F1YW5Od1AzUjVjR1ZwWkQwMElqNVhhR0YwYzJsMGN6d3ZZVDQ4WW5JdlBnbzhZU0JvY21WbVBTSndjbTlrZFdOMExtcHpjRDkwZVhCbGFXUTlNU0krVjJsa1oyVjBjend2WVQ0OFluSXZQZ29LUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K1BHSnlMejQ4WW5JdlBqeGljaTgrUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K0Nqd3ZkR1ErQ2p4MFpDQjJZV3hwWjI0OUluUnZjQ0lnZDJsa2RHZzlJamN3SlNJK0NnMEtEUW84YURNK1RHOW5hVzQ4TDJnelBnMEtVR3hsWVhObElHVnVkR1Z5SUhsdmRYSWdZM0psWkdWdWRHbGhiSE02SUR4aWNpOCtQR0p5THo0TkNqeG1iM0p0SUcxbGRHaHZaRDBpVUU5VFZDSStEUW9KUEdObGJuUmxjajROQ2drOGRHRmliR1UrRFFvSlBIUnlQZzBLQ1FrOGRHUStWWE5sY201aGJXVTZQQzkwWkQ0TkNna0pQSFJrUGp4cGJuQjFkQ0JwWkQwaWRYTmxjbTVoYldVaUlHNWhiV1U5SW5WelpYSnVZVzFsSWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4ZEhJK0RRb0pDVHgwWkQ1UVlYTnpkMjl5WkRvOEwzUmtQZzBLQ1FrOGRHUStQR2x1Y0hWMElHbGtQU0p3WVhOemQyOXlaQ0lnYm1GdFpUMGljR0Z6YzNkdmNtUWlJSFI1Y0dVOUluQmhjM04zYjNKa0lqNDhMMmx1Y0hWMFBqd3ZkR1ErRFFvSlBDOTBjajROQ2drOGRISStEUW9KQ1R4MFpENDhMM1JrUGcwS0NRazhkR1ErUEdsdWNIVjBJR2xrUFNKemRXSnRhWFFpSUhSNWNHVTlJbk4xWW0xcGRDSWdkbUZzZFdVOUlreHZaMmx1SWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4TDNSaFlteGxQZzBLQ1R3dlkyVnVkR1Z5UGcwS1BDOW1iM0p0UGcwS1NXWWdlVzkxSUdSdmJuUWdhR0YyWlNCaGJpQmhZMk52ZFc1MElIZHBkR2dnZFhNZ2RHaGxiaUJ3YkdWaGMyVWdQR0VnYUhKbFpqMGljbVZuYVhOMFpYSXVhbk53SWo1U1pXZHBjM1JsY2p3dllUNGdibTkzSUdadmNpQmhJR1p5WldVZ1lXTmpiM1Z1ZEM0TkNqeGljaTgrUEdKeUx6NE5DZzBLUEM5MFpENEtQQzkwY2o0S1BDOTBZV0pzWlQ0S1BDOTBaRDRLUEM5MGNqNEtQQzkwWVdKc1pUNEtQQzlqWlc1MFpYSStDand2WW05a2VUNEtQQzlvZEcxc1Bnb05DZzBL" + } + }, + { + "pk": 136, + "model": "dojo.burprawrequestresponse", + "fields": { + "finding": 8, + "burpRequestBase64": "UjBWVUlDOWliMlJuWldsMEwyeHZaMmx1TG1wemNDQklWRlJRTHpFdU1RMEtTRzl6ZERvZ2JHOWpZV3hvYjNOME9qZzRPRGdOQ2xWelpYSXRRV2RsYm5RNklFMXZlbWxzYkdFdk5TNHdJQ2hOWVdOcGJuUnZjMmc3SUVsdWRHVnNJRTFoWXlCUFV5QllJREV3TGpFeE95Qnlkam8wTnk0d0tTQkhaV05yYnk4eU1ERXdNREV3TVNCR2FYSmxabTk0THpRM0xqQU5Da0ZqWTJWd2REb2dkR1Y0ZEM5b2RHMXNMR0Z3Y0d4cFkyRjBhVzl1TDNob2RHMXNLM2h0YkN4aGNIQnNhV05oZEdsdmJpOTRiV3c3Y1Qwd0xqa3NLaThxTzNFOU1DNDREUXBCWTJObGNIUXRUR0Z1WjNWaFoyVTZJR1Z1TFZWVExHVnVPM0U5TUM0MURRcEJZMk5sY0hRdFJXNWpiMlJwYm1jNklHZDZhWEFzSUdSbFpteGhkR1VOQ2xKbFptVnlaWEk2SUdoMGRIQTZMeTlzYjJOaGJHaHZjM1E2T0RnNE9DOWliMlJuWldsMEx3MEtRMjl2YTJsbE9pQktVMFZUVTBsUFRrbEVQVFpGT1RVM04wRXhOa0pCUXpZeE9URXpSRVU1TjBFNE9EZEJSRFl3TWpjMURRcERiMjV1WldOMGFXOXVPaUJqYkc5elpRMEtEUW89", + "burpResponseBase64": "U0ZSVVVDOHhMakVnTWpBd0lBMEtVMlZ5ZG1WeU9pQkJjR0ZqYUdVdFEyOTViM1JsTHpFdU1RMEtRMjl1ZEdWdWRDMVVlWEJsT2lCMFpYaDBMMmgwYld3N1kyaGhjbk5sZEQxSlUwOHRPRGcxT1MweERRcERiMjUwWlc1MExVeGxibWQwYURvZ01qUTJNZzBLUkdGMFpUb2dVMkYwTENBeU55QkJkV2NnTWpBeE5pQXdNam93T0RvMU55QkhUVlFOQ2tOdmJtNWxZM1JwYjI0NklHTnNiM05sRFFvTkNnMEtEUW9OQ2cwS0Nnb0tDandoUkU5RFZGbFFSU0JJVkUxTUlGQlZRa3hKUXlBaUxTOHZWek5ETHk5RVZFUWdTRlJOVENBekxqSXZMMFZPSWo0S1BHaDBiV3crQ2p4b1pXRmtQZ284ZEdsMGJHVStWR2hsSUVKdlpHZGxTWFFnVTNSdmNtVThMM1JwZEd4bFBnbzhiR2x1YXlCb2NtVm1QU0p6ZEhsc1pTNWpjM01pSUhKbGJEMGljM1I1YkdWemFHVmxkQ0lnZEhsd1pUMGlkR1Y0ZEM5amMzTWlJQzgrQ2p4elkzSnBjSFFnZEhsd1pUMGlkR1Y0ZEM5cVlYWmhjMk55YVhCMElpQnpjbU05SWk0dmFuTXZkWFJwYkM1cWN5SStQQzl6WTNKcGNIUStDand2YUdWaFpENEtQR0p2WkhrK0NnbzhZMlZ1ZEdWeVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpnd0pTSWdZMnhoYzNNOUltSnZjbVJsY2lJK0NqeDBjaUJDUjBOUFRFOVNQU05ETTBRNVJrWStDangwWkNCaGJHbG5iajBpWTJWdWRHVnlJaUJqYjJ4emNHRnVQU0kySWo0S1BFZ3hQbFJvWlNCQ2IyUm5aVWwwSUZOMGIzSmxQQzlJTVQ0S1BIUmhZbXhsSUhkcFpIUm9QU0l4TURBbElpQmpiR0Z6Y3oxY0ltNXZZbTl5WkdWeVhDSStDangwY2lCQ1IwTlBURTlTUFNORE0wUTVSa1krQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTXpBbElqNG1ibUp6Y0RzOEwzUmtQZ284ZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJalF3SlNJK1YyVWdZbTlrWjJVZ2FYUXNJSE52SUhsdmRTQmtiMjUwSUdoaGRtVWdkRzhoUEM5MFpENEtQSFJrSUdGc2FXZHVQU0pqWlc1MFpYSWlJSGRwWkhSb1BTSXpNQ1VpSUhOMGVXeGxQU0owWlhoMExXRnNhV2R1T2lCeWFXZG9kQ0lnUGdwSGRXVnpkQ0IxYzJWeUNnbzhMM1J5UGdvOEwzUmhZbXhsUGdvOEwzUmtQZ284TDNSeVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTVRZbElpQkNSME5QVEU5U1BTTkZSVVZGUlVVK1BHRWdhSEpsWmowaWFHOXRaUzVxYzNBaVBraHZiV1U4TDJFK1BDOTBaRDRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUhkcFpIUm9QU0l4TmlVaUlFSkhRMDlNVDFJOUkwVkZSVVZGUlQ0OFlTQm9jbVZtUFNKaFltOTFkQzVxYzNBaVBrRmliM1YwSUZWelBDOWhQand2ZEdRK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQanhoSUdoeVpXWTlJbU52Ym5SaFkzUXVhbk53SWo1RGIyNTBZV04wSUZWelBDOWhQand2ZEdRK0Nqd2hMUzBnZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJakUySlNJK1BHRWdhSEpsWmowaVlXUnRhVzR1YW5Od0lqNUJaRzFwYmp3dllUNDhMM1JrTFMwK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQZ29LQ1FrOFlTQm9jbVZtUFNKc2IyZHBiaTVxYzNBaVBreHZaMmx1UEM5aFBnb0tQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGlZbUZ6YTJWMExtcHpjQ0krV1c5MWNpQkNZWE5yWlhROEwyRStQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGljMlZoY21Ob0xtcHpjQ0krVTJWaGNtTm9QQzloUGp3dmRHUStDand2ZEhJK0NqeDBjajRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUdOdmJITndZVzQ5SWpZaVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpFd01DVWlJR05zWVhOelBTSmliM0prWlhJaVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaWJHVm1kQ0lnZG1Gc2FXZHVQU0owYjNBaUlIZHBaSFJvUFNJeU5TVWlQZ284WVNCb2NtVm1QU0p3Y205a2RXTjBMbXB6Y0Q5MGVYQmxhV1E5TmlJK1JHOXZaR0ZvY3p3dllUNDhZbkl2UGdvOFlTQm9jbVZtUFNKd2NtOWtkV04wTG1wemNEOTBlWEJsYVdROU5TSStSMmw2Ylc5elBDOWhQanhpY2k4K0NqeGhJR2h5WldZOUluQnliMlIxWTNRdWFuTndQM1I1Y0dWcFpEMHpJajVVYUdsdVoyRnRZV3BwWjNNOEwyRStQR0p5THo0S1BHRWdhSEpsWmowaWNISnZaSFZqZEM1cWMzQS9kSGx3Wldsa1BUSWlQbFJvYVc1bmFXVnpQQzloUGp4aWNpOCtDanhoSUdoeVpXWTlJbkJ5YjJSMVkzUXVhbk53UDNSNWNHVnBaRDAzSWo1WGFHRjBZMmhoYldGallXeHNhWFJ6UEM5aFBqeGljaTgrQ2p4aElHaHlaV1k5SW5CeWIyUjFZM1F1YW5Od1AzUjVjR1ZwWkQwMElqNVhhR0YwYzJsMGN6d3ZZVDQ4WW5JdlBnbzhZU0JvY21WbVBTSndjbTlrZFdOMExtcHpjRDkwZVhCbGFXUTlNU0krVjJsa1oyVjBjend2WVQ0OFluSXZQZ29LUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K1BHSnlMejQ4WW5JdlBqeGljaTgrUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K0Nqd3ZkR1ErQ2p4MFpDQjJZV3hwWjI0OUluUnZjQ0lnZDJsa2RHZzlJamN3SlNJK0NnMEtEUW84YURNK1RHOW5hVzQ4TDJnelBnMEtVR3hsWVhObElHVnVkR1Z5SUhsdmRYSWdZM0psWkdWdWRHbGhiSE02SUR4aWNpOCtQR0p5THo0TkNqeG1iM0p0SUcxbGRHaHZaRDBpVUU5VFZDSStEUW9KUEdObGJuUmxjajROQ2drOGRHRmliR1UrRFFvSlBIUnlQZzBLQ1FrOGRHUStWWE5sY201aGJXVTZQQzkwWkQ0TkNna0pQSFJrUGp4cGJuQjFkQ0JwWkQwaWRYTmxjbTVoYldVaUlHNWhiV1U5SW5WelpYSnVZVzFsSWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4ZEhJK0RRb0pDVHgwWkQ1UVlYTnpkMjl5WkRvOEwzUmtQZzBLQ1FrOGRHUStQR2x1Y0hWMElHbGtQU0p3WVhOemQyOXlaQ0lnYm1GdFpUMGljR0Z6YzNkdmNtUWlJSFI1Y0dVOUluQmhjM04zYjNKa0lqNDhMMmx1Y0hWMFBqd3ZkR1ErRFFvSlBDOTBjajROQ2drOGRISStEUW9KQ1R4MFpENDhMM1JrUGcwS0NRazhkR1ErUEdsdWNIVjBJR2xrUFNKemRXSnRhWFFpSUhSNWNHVTlJbk4xWW0xcGRDSWdkbUZzZFdVOUlreHZaMmx1SWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4TDNSaFlteGxQZzBLQ1R3dlkyVnVkR1Z5UGcwS1BDOW1iM0p0UGcwS1NXWWdlVzkxSUdSdmJuUWdhR0YyWlNCaGJpQmhZMk52ZFc1MElIZHBkR2dnZFhNZ2RHaGxiaUJ3YkdWaGMyVWdQR0VnYUhKbFpqMGljbVZuYVhOMFpYSXVhbk53SWo1U1pXZHBjM1JsY2p3dllUNGdibTkzSUdadmNpQmhJR1p5WldVZ1lXTmpiM1Z1ZEM0TkNqeGljaTgrUEdKeUx6NE5DZzBLUEM5MFpENEtQQzkwY2o0S1BDOTBZV0pzWlQ0S1BDOTBaRDRLUEM5MGNqNEtQQzkwWVdKc1pUNEtQQzlqWlc1MFpYSStDand2WW05a2VUNEtQQzlvZEcxc1Bnb05DZzBL" + } + }, + { + "pk": 137, + "model": "dojo.burprawrequestresponse", + "fields": { + "finding": 8, + "burpRequestBase64": "UjBWVUlDOWliMlJuWldsMEwyeHZaMmx1TG1wemNDQklWRlJRTHpFdU1RMEtTRzl6ZERvZ2JHOWpZV3hvYjNOME9qZzRPRGdOQ2xWelpYSXRRV2RsYm5RNklFMXZlbWxzYkdFdk5TNHdJQ2hOWVdOcGJuUnZjMmc3SUVsdWRHVnNJRTFoWXlCUFV5QllJREV3TGpFeE95Qnlkam8wTnk0d0tTQkhaV05yYnk4eU1ERXdNREV3TVNCR2FYSmxabTk0THpRM0xqQU5Da0ZqWTJWd2REb2dkR1Y0ZEM5b2RHMXNMR0Z3Y0d4cFkyRjBhVzl1TDNob2RHMXNLM2h0YkN4aGNIQnNhV05oZEdsdmJpOTRiV3c3Y1Qwd0xqa3NLaThxTzNFOU1DNDREUXBCWTJObGNIUXRUR0Z1WjNWaFoyVTZJR1Z1TFZWVExHVnVPM0U5TUM0MURRcEJZMk5sY0hRdFJXNWpiMlJwYm1jNklHZDZhWEFzSUdSbFpteGhkR1VOQ2xKbFptVnlaWEk2SUdoMGRIQTZMeTlzYjJOaGJHaHZjM1E2T0RnNE9DOWliMlJuWldsMEx3MEtRMjl2YTJsbE9pQktVMFZUVTBsUFRrbEVQVFpGT1RVM04wRXhOa0pCUXpZeE9URXpSRVU1TjBFNE9EZEJSRFl3TWpjMURRcERiMjV1WldOMGFXOXVPaUJqYkc5elpRMEtEUW89", + "burpResponseBase64": "U0ZSVVVDOHhMakVnTWpBd0lBMEtVMlZ5ZG1WeU9pQkJjR0ZqYUdVdFEyOTViM1JsTHpFdU1RMEtRMjl1ZEdWdWRDMVVlWEJsT2lCMFpYaDBMMmgwYld3N1kyaGhjbk5sZEQxSlUwOHRPRGcxT1MweERRcERiMjUwWlc1MExVeGxibWQwYURvZ01qUTJNZzBLUkdGMFpUb2dVMkYwTENBeU55QkJkV2NnTWpBeE5pQXdNam93T0RvMU55QkhUVlFOQ2tOdmJtNWxZM1JwYjI0NklHTnNiM05sRFFvTkNnMEtEUW9OQ2cwS0Nnb0tDandoUkU5RFZGbFFSU0JJVkUxTUlGQlZRa3hKUXlBaUxTOHZWek5ETHk5RVZFUWdTRlJOVENBekxqSXZMMFZPSWo0S1BHaDBiV3crQ2p4b1pXRmtQZ284ZEdsMGJHVStWR2hsSUVKdlpHZGxTWFFnVTNSdmNtVThMM1JwZEd4bFBnbzhiR2x1YXlCb2NtVm1QU0p6ZEhsc1pTNWpjM01pSUhKbGJEMGljM1I1YkdWemFHVmxkQ0lnZEhsd1pUMGlkR1Y0ZEM5amMzTWlJQzgrQ2p4elkzSnBjSFFnZEhsd1pUMGlkR1Y0ZEM5cVlYWmhjMk55YVhCMElpQnpjbU05SWk0dmFuTXZkWFJwYkM1cWN5SStQQzl6WTNKcGNIUStDand2YUdWaFpENEtQR0p2WkhrK0NnbzhZMlZ1ZEdWeVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpnd0pTSWdZMnhoYzNNOUltSnZjbVJsY2lJK0NqeDBjaUJDUjBOUFRFOVNQU05ETTBRNVJrWStDangwWkNCaGJHbG5iajBpWTJWdWRHVnlJaUJqYjJ4emNHRnVQU0kySWo0S1BFZ3hQbFJvWlNCQ2IyUm5aVWwwSUZOMGIzSmxQQzlJTVQ0S1BIUmhZbXhsSUhkcFpIUm9QU0l4TURBbElpQmpiR0Z6Y3oxY0ltNXZZbTl5WkdWeVhDSStDangwY2lCQ1IwTlBURTlTUFNORE0wUTVSa1krQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTXpBbElqNG1ibUp6Y0RzOEwzUmtQZ284ZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJalF3SlNJK1YyVWdZbTlrWjJVZ2FYUXNJSE52SUhsdmRTQmtiMjUwSUdoaGRtVWdkRzhoUEM5MFpENEtQSFJrSUdGc2FXZHVQU0pqWlc1MFpYSWlJSGRwWkhSb1BTSXpNQ1VpSUhOMGVXeGxQU0owWlhoMExXRnNhV2R1T2lCeWFXZG9kQ0lnUGdwSGRXVnpkQ0IxYzJWeUNnbzhMM1J5UGdvOEwzUmhZbXhsUGdvOEwzUmtQZ284TDNSeVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTVRZbElpQkNSME5QVEU5U1BTTkZSVVZGUlVVK1BHRWdhSEpsWmowaWFHOXRaUzVxYzNBaVBraHZiV1U4TDJFK1BDOTBaRDRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUhkcFpIUm9QU0l4TmlVaUlFSkhRMDlNVDFJOUkwVkZSVVZGUlQ0OFlTQm9jbVZtUFNKaFltOTFkQzVxYzNBaVBrRmliM1YwSUZWelBDOWhQand2ZEdRK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQanhoSUdoeVpXWTlJbU52Ym5SaFkzUXVhbk53SWo1RGIyNTBZV04wSUZWelBDOWhQand2ZEdRK0Nqd2hMUzBnZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJakUySlNJK1BHRWdhSEpsWmowaVlXUnRhVzR1YW5Od0lqNUJaRzFwYmp3dllUNDhMM1JrTFMwK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQZ29LQ1FrOFlTQm9jbVZtUFNKc2IyZHBiaTVxYzNBaVBreHZaMmx1UEM5aFBnb0tQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGlZbUZ6YTJWMExtcHpjQ0krV1c5MWNpQkNZWE5yWlhROEwyRStQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGljMlZoY21Ob0xtcHpjQ0krVTJWaGNtTm9QQzloUGp3dmRHUStDand2ZEhJK0NqeDBjajRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUdOdmJITndZVzQ5SWpZaVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpFd01DVWlJR05zWVhOelBTSmliM0prWlhJaVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaWJHVm1kQ0lnZG1Gc2FXZHVQU0owYjNBaUlIZHBaSFJvUFNJeU5TVWlQZ284WVNCb2NtVm1QU0p3Y205a2RXTjBMbXB6Y0Q5MGVYQmxhV1E5TmlJK1JHOXZaR0ZvY3p3dllUNDhZbkl2UGdvOFlTQm9jbVZtUFNKd2NtOWtkV04wTG1wemNEOTBlWEJsYVdROU5TSStSMmw2Ylc5elBDOWhQanhpY2k4K0NqeGhJR2h5WldZOUluQnliMlIxWTNRdWFuTndQM1I1Y0dWcFpEMHpJajVVYUdsdVoyRnRZV3BwWjNNOEwyRStQR0p5THo0S1BHRWdhSEpsWmowaWNISnZaSFZqZEM1cWMzQS9kSGx3Wldsa1BUSWlQbFJvYVc1bmFXVnpQQzloUGp4aWNpOCtDanhoSUdoeVpXWTlJbkJ5YjJSMVkzUXVhbk53UDNSNWNHVnBaRDAzSWo1WGFHRjBZMmhoYldGallXeHNhWFJ6UEM5aFBqeGljaTgrQ2p4aElHaHlaV1k5SW5CeWIyUjFZM1F1YW5Od1AzUjVjR1ZwWkQwMElqNVhhR0YwYzJsMGN6d3ZZVDQ4WW5JdlBnbzhZU0JvY21WbVBTSndjbTlrZFdOMExtcHpjRDkwZVhCbGFXUTlNU0krVjJsa1oyVjBjend2WVQ0OFluSXZQZ29LUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K1BHSnlMejQ4WW5JdlBqeGljaTgrUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K0Nqd3ZkR1ErQ2p4MFpDQjJZV3hwWjI0OUluUnZjQ0lnZDJsa2RHZzlJamN3SlNJK0NnMEtEUW84YURNK1RHOW5hVzQ4TDJnelBnMEtVR3hsWVhObElHVnVkR1Z5SUhsdmRYSWdZM0psWkdWdWRHbGhiSE02SUR4aWNpOCtQR0p5THo0TkNqeG1iM0p0SUcxbGRHaHZaRDBpVUU5VFZDSStEUW9KUEdObGJuUmxjajROQ2drOGRHRmliR1UrRFFvSlBIUnlQZzBLQ1FrOGRHUStWWE5sY201aGJXVTZQQzkwWkQ0TkNna0pQSFJrUGp4cGJuQjFkQ0JwWkQwaWRYTmxjbTVoYldVaUlHNWhiV1U5SW5WelpYSnVZVzFsSWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4ZEhJK0RRb0pDVHgwWkQ1UVlYTnpkMjl5WkRvOEwzUmtQZzBLQ1FrOGRHUStQR2x1Y0hWMElHbGtQU0p3WVhOemQyOXlaQ0lnYm1GdFpUMGljR0Z6YzNkdmNtUWlJSFI1Y0dVOUluQmhjM04zYjNKa0lqNDhMMmx1Y0hWMFBqd3ZkR1ErRFFvSlBDOTBjajROQ2drOGRISStEUW9KQ1R4MFpENDhMM1JrUGcwS0NRazhkR1ErUEdsdWNIVjBJR2xrUFNKemRXSnRhWFFpSUhSNWNHVTlJbk4xWW0xcGRDSWdkbUZzZFdVOUlreHZaMmx1SWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4TDNSaFlteGxQZzBLQ1R3dlkyVnVkR1Z5UGcwS1BDOW1iM0p0UGcwS1NXWWdlVzkxSUdSdmJuUWdhR0YyWlNCaGJpQmhZMk52ZFc1MElIZHBkR2dnZFhNZ2RHaGxiaUJ3YkdWaGMyVWdQR0VnYUhKbFpqMGljbVZuYVhOMFpYSXVhbk53SWo1U1pXZHBjM1JsY2p3dllUNGdibTkzSUdadmNpQmhJR1p5WldVZ1lXTmpiM1Z1ZEM0TkNqeGljaTgrUEdKeUx6NE5DZzBLUEM5MFpENEtQQzkwY2o0S1BDOTBZV0pzWlQ0S1BDOTBaRDRLUEM5MGNqNEtQQzkwWVdKc1pUNEtQQzlqWlc1MFpYSStDand2WW05a2VUNEtQQzlvZEcxc1Bnb05DZzBL" + } + }, + { + "pk": 138, + "model": "dojo.burprawrequestresponse", + "fields": { + "finding": 8, + "burpRequestBase64": "UjBWVUlDOWliMlJuWldsMEwyeHZaMmx1TG1wemNDQklWRlJRTHpFdU1RMEtTRzl6ZERvZ2JHOWpZV3hvYjNOME9qZzRPRGdOQ2xWelpYSXRRV2RsYm5RNklFMXZlbWxzYkdFdk5TNHdJQ2hOWVdOcGJuUnZjMmc3SUVsdWRHVnNJRTFoWXlCUFV5QllJREV3TGpFeE95Qnlkam8wTnk0d0tTQkhaV05yYnk4eU1ERXdNREV3TVNCR2FYSmxabTk0THpRM0xqQU5Da0ZqWTJWd2REb2dkR1Y0ZEM5b2RHMXNMR0Z3Y0d4cFkyRjBhVzl1TDNob2RHMXNLM2h0YkN4aGNIQnNhV05oZEdsdmJpOTRiV3c3Y1Qwd0xqa3NLaThxTzNFOU1DNDREUXBCWTJObGNIUXRUR0Z1WjNWaFoyVTZJR1Z1TFZWVExHVnVPM0U5TUM0MURRcEJZMk5sY0hRdFJXNWpiMlJwYm1jNklHZDZhWEFzSUdSbFpteGhkR1VOQ2xKbFptVnlaWEk2SUdoMGRIQTZMeTlzYjJOaGJHaHZjM1E2T0RnNE9DOWliMlJuWldsMEx3MEtRMjl2YTJsbE9pQktVMFZUVTBsUFRrbEVQVFpGT1RVM04wRXhOa0pCUXpZeE9URXpSRVU1TjBFNE9EZEJSRFl3TWpjMURRcERiMjV1WldOMGFXOXVPaUJqYkc5elpRMEtEUW89", + "burpResponseBase64": "U0ZSVVVDOHhMakVnTWpBd0lBMEtVMlZ5ZG1WeU9pQkJjR0ZqYUdVdFEyOTViM1JsTHpFdU1RMEtRMjl1ZEdWdWRDMVVlWEJsT2lCMFpYaDBMMmgwYld3N1kyaGhjbk5sZEQxSlUwOHRPRGcxT1MweERRcERiMjUwWlc1MExVeGxibWQwYURvZ01qUTJNZzBLUkdGMFpUb2dVMkYwTENBeU55QkJkV2NnTWpBeE5pQXdNam93T0RvMU55QkhUVlFOQ2tOdmJtNWxZM1JwYjI0NklHTnNiM05sRFFvTkNnMEtEUW9OQ2cwS0Nnb0tDandoUkU5RFZGbFFSU0JJVkUxTUlGQlZRa3hKUXlBaUxTOHZWek5ETHk5RVZFUWdTRlJOVENBekxqSXZMMFZPSWo0S1BHaDBiV3crQ2p4b1pXRmtQZ284ZEdsMGJHVStWR2hsSUVKdlpHZGxTWFFnVTNSdmNtVThMM1JwZEd4bFBnbzhiR2x1YXlCb2NtVm1QU0p6ZEhsc1pTNWpjM01pSUhKbGJEMGljM1I1YkdWemFHVmxkQ0lnZEhsd1pUMGlkR1Y0ZEM5amMzTWlJQzgrQ2p4elkzSnBjSFFnZEhsd1pUMGlkR1Y0ZEM5cVlYWmhjMk55YVhCMElpQnpjbU05SWk0dmFuTXZkWFJwYkM1cWN5SStQQzl6WTNKcGNIUStDand2YUdWaFpENEtQR0p2WkhrK0NnbzhZMlZ1ZEdWeVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpnd0pTSWdZMnhoYzNNOUltSnZjbVJsY2lJK0NqeDBjaUJDUjBOUFRFOVNQU05ETTBRNVJrWStDangwWkNCaGJHbG5iajBpWTJWdWRHVnlJaUJqYjJ4emNHRnVQU0kySWo0S1BFZ3hQbFJvWlNCQ2IyUm5aVWwwSUZOMGIzSmxQQzlJTVQ0S1BIUmhZbXhsSUhkcFpIUm9QU0l4TURBbElpQmpiR0Z6Y3oxY0ltNXZZbTl5WkdWeVhDSStDangwY2lCQ1IwTlBURTlTUFNORE0wUTVSa1krQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTXpBbElqNG1ibUp6Y0RzOEwzUmtQZ284ZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJalF3SlNJK1YyVWdZbTlrWjJVZ2FYUXNJSE52SUhsdmRTQmtiMjUwSUdoaGRtVWdkRzhoUEM5MFpENEtQSFJrSUdGc2FXZHVQU0pqWlc1MFpYSWlJSGRwWkhSb1BTSXpNQ1VpSUhOMGVXeGxQU0owWlhoMExXRnNhV2R1T2lCeWFXZG9kQ0lnUGdwSGRXVnpkQ0IxYzJWeUNnbzhMM1J5UGdvOEwzUmhZbXhsUGdvOEwzUmtQZ284TDNSeVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTVRZbElpQkNSME5QVEU5U1BTTkZSVVZGUlVVK1BHRWdhSEpsWmowaWFHOXRaUzVxYzNBaVBraHZiV1U4TDJFK1BDOTBaRDRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUhkcFpIUm9QU0l4TmlVaUlFSkhRMDlNVDFJOUkwVkZSVVZGUlQ0OFlTQm9jbVZtUFNKaFltOTFkQzVxYzNBaVBrRmliM1YwSUZWelBDOWhQand2ZEdRK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQanhoSUdoeVpXWTlJbU52Ym5SaFkzUXVhbk53SWo1RGIyNTBZV04wSUZWelBDOWhQand2ZEdRK0Nqd2hMUzBnZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJakUySlNJK1BHRWdhSEpsWmowaVlXUnRhVzR1YW5Od0lqNUJaRzFwYmp3dllUNDhMM1JrTFMwK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQZ29LQ1FrOFlTQm9jbVZtUFNKc2IyZHBiaTVxYzNBaVBreHZaMmx1UEM5aFBnb0tQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGlZbUZ6YTJWMExtcHpjQ0krV1c5MWNpQkNZWE5yWlhROEwyRStQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGljMlZoY21Ob0xtcHpjQ0krVTJWaGNtTm9QQzloUGp3dmRHUStDand2ZEhJK0NqeDBjajRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUdOdmJITndZVzQ5SWpZaVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpFd01DVWlJR05zWVhOelBTSmliM0prWlhJaVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaWJHVm1kQ0lnZG1Gc2FXZHVQU0owYjNBaUlIZHBaSFJvUFNJeU5TVWlQZ284WVNCb2NtVm1QU0p3Y205a2RXTjBMbXB6Y0Q5MGVYQmxhV1E5TmlJK1JHOXZaR0ZvY3p3dllUNDhZbkl2UGdvOFlTQm9jbVZtUFNKd2NtOWtkV04wTG1wemNEOTBlWEJsYVdROU5TSStSMmw2Ylc5elBDOWhQanhpY2k4K0NqeGhJR2h5WldZOUluQnliMlIxWTNRdWFuTndQM1I1Y0dWcFpEMHpJajVVYUdsdVoyRnRZV3BwWjNNOEwyRStQR0p5THo0S1BHRWdhSEpsWmowaWNISnZaSFZqZEM1cWMzQS9kSGx3Wldsa1BUSWlQbFJvYVc1bmFXVnpQQzloUGp4aWNpOCtDanhoSUdoeVpXWTlJbkJ5YjJSMVkzUXVhbk53UDNSNWNHVnBaRDAzSWo1WGFHRjBZMmhoYldGallXeHNhWFJ6UEM5aFBqeGljaTgrQ2p4aElHaHlaV1k5SW5CeWIyUjFZM1F1YW5Od1AzUjVjR1ZwWkQwMElqNVhhR0YwYzJsMGN6d3ZZVDQ4WW5JdlBnbzhZU0JvY21WbVBTSndjbTlrZFdOMExtcHpjRDkwZVhCbGFXUTlNU0krVjJsa1oyVjBjend2WVQ0OFluSXZQZ29LUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K1BHSnlMejQ4WW5JdlBqeGljaTgrUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K0Nqd3ZkR1ErQ2p4MFpDQjJZV3hwWjI0OUluUnZjQ0lnZDJsa2RHZzlJamN3SlNJK0NnMEtEUW84YURNK1RHOW5hVzQ4TDJnelBnMEtVR3hsWVhObElHVnVkR1Z5SUhsdmRYSWdZM0psWkdWdWRHbGhiSE02SUR4aWNpOCtQR0p5THo0TkNqeG1iM0p0SUcxbGRHaHZaRDBpVUU5VFZDSStEUW9KUEdObGJuUmxjajROQ2drOGRHRmliR1UrRFFvSlBIUnlQZzBLQ1FrOGRHUStWWE5sY201aGJXVTZQQzkwWkQ0TkNna0pQSFJrUGp4cGJuQjFkQ0JwWkQwaWRYTmxjbTVoYldVaUlHNWhiV1U5SW5WelpYSnVZVzFsSWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4ZEhJK0RRb0pDVHgwWkQ1UVlYTnpkMjl5WkRvOEwzUmtQZzBLQ1FrOGRHUStQR2x1Y0hWMElHbGtQU0p3WVhOemQyOXlaQ0lnYm1GdFpUMGljR0Z6YzNkdmNtUWlJSFI1Y0dVOUluQmhjM04zYjNKa0lqNDhMMmx1Y0hWMFBqd3ZkR1ErRFFvSlBDOTBjajROQ2drOGRISStEUW9KQ1R4MFpENDhMM1JrUGcwS0NRazhkR1ErUEdsdWNIVjBJR2xrUFNKemRXSnRhWFFpSUhSNWNHVTlJbk4xWW0xcGRDSWdkbUZzZFdVOUlreHZaMmx1SWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4TDNSaFlteGxQZzBLQ1R3dlkyVnVkR1Z5UGcwS1BDOW1iM0p0UGcwS1NXWWdlVzkxSUdSdmJuUWdhR0YyWlNCaGJpQmhZMk52ZFc1MElIZHBkR2dnZFhNZ2RHaGxiaUJ3YkdWaGMyVWdQR0VnYUhKbFpqMGljbVZuYVhOMFpYSXVhbk53SWo1U1pXZHBjM1JsY2p3dllUNGdibTkzSUdadmNpQmhJR1p5WldVZ1lXTmpiM1Z1ZEM0TkNqeGljaTgrUEdKeUx6NE5DZzBLUEM5MFpENEtQQzkwY2o0S1BDOTBZV0pzWlQ0S1BDOTBaRDRLUEM5MGNqNEtQQzkwWVdKc1pUNEtQQzlqWlc1MFpYSStDand2WW05a2VUNEtQQzlvZEcxc1Bnb05DZzBL" + } + }, + { + "pk": 139, + "model": "dojo.burprawrequestresponse", + "fields": { + "finding": 8, + "burpRequestBase64": "UjBWVUlDOWliMlJuWldsMEwyeHZaMmx1TG1wemNDQklWRlJRTHpFdU1RMEtTRzl6ZERvZ2JHOWpZV3hvYjNOME9qZzRPRGdOQ2xWelpYSXRRV2RsYm5RNklFMXZlbWxzYkdFdk5TNHdJQ2hOWVdOcGJuUnZjMmc3SUVsdWRHVnNJRTFoWXlCUFV5QllJREV3TGpFeE95Qnlkam8wTnk0d0tTQkhaV05yYnk4eU1ERXdNREV3TVNCR2FYSmxabTk0THpRM0xqQU5Da0ZqWTJWd2REb2dkR1Y0ZEM5b2RHMXNMR0Z3Y0d4cFkyRjBhVzl1TDNob2RHMXNLM2h0YkN4aGNIQnNhV05oZEdsdmJpOTRiV3c3Y1Qwd0xqa3NLaThxTzNFOU1DNDREUXBCWTJObGNIUXRUR0Z1WjNWaFoyVTZJR1Z1TFZWVExHVnVPM0U5TUM0MURRcEJZMk5sY0hRdFJXNWpiMlJwYm1jNklHZDZhWEFzSUdSbFpteGhkR1VOQ2xKbFptVnlaWEk2SUdoMGRIQTZMeTlzYjJOaGJHaHZjM1E2T0RnNE9DOWliMlJuWldsMEx3MEtRMjl2YTJsbE9pQktVMFZUVTBsUFRrbEVQVFpGT1RVM04wRXhOa0pCUXpZeE9URXpSRVU1TjBFNE9EZEJSRFl3TWpjMURRcERiMjV1WldOMGFXOXVPaUJqYkc5elpRMEtEUW89", + "burpResponseBase64": "U0ZSVVVDOHhMakVnTWpBd0lBMEtVMlZ5ZG1WeU9pQkJjR0ZqYUdVdFEyOTViM1JsTHpFdU1RMEtRMjl1ZEdWdWRDMVVlWEJsT2lCMFpYaDBMMmgwYld3N1kyaGhjbk5sZEQxSlUwOHRPRGcxT1MweERRcERiMjUwWlc1MExVeGxibWQwYURvZ01qUTJNZzBLUkdGMFpUb2dVMkYwTENBeU55QkJkV2NnTWpBeE5pQXdNam93T0RvMU55QkhUVlFOQ2tOdmJtNWxZM1JwYjI0NklHTnNiM05sRFFvTkNnMEtEUW9OQ2cwS0Nnb0tDandoUkU5RFZGbFFSU0JJVkUxTUlGQlZRa3hKUXlBaUxTOHZWek5ETHk5RVZFUWdTRlJOVENBekxqSXZMMFZPSWo0S1BHaDBiV3crQ2p4b1pXRmtQZ284ZEdsMGJHVStWR2hsSUVKdlpHZGxTWFFnVTNSdmNtVThMM1JwZEd4bFBnbzhiR2x1YXlCb2NtVm1QU0p6ZEhsc1pTNWpjM01pSUhKbGJEMGljM1I1YkdWemFHVmxkQ0lnZEhsd1pUMGlkR1Y0ZEM5amMzTWlJQzgrQ2p4elkzSnBjSFFnZEhsd1pUMGlkR1Y0ZEM5cVlYWmhjMk55YVhCMElpQnpjbU05SWk0dmFuTXZkWFJwYkM1cWN5SStQQzl6WTNKcGNIUStDand2YUdWaFpENEtQR0p2WkhrK0NnbzhZMlZ1ZEdWeVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpnd0pTSWdZMnhoYzNNOUltSnZjbVJsY2lJK0NqeDBjaUJDUjBOUFRFOVNQU05ETTBRNVJrWStDangwWkNCaGJHbG5iajBpWTJWdWRHVnlJaUJqYjJ4emNHRnVQU0kySWo0S1BFZ3hQbFJvWlNCQ2IyUm5aVWwwSUZOMGIzSmxQQzlJTVQ0S1BIUmhZbXhsSUhkcFpIUm9QU0l4TURBbElpQmpiR0Z6Y3oxY0ltNXZZbTl5WkdWeVhDSStDangwY2lCQ1IwTlBURTlTUFNORE0wUTVSa1krQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTXpBbElqNG1ibUp6Y0RzOEwzUmtQZ284ZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJalF3SlNJK1YyVWdZbTlrWjJVZ2FYUXNJSE52SUhsdmRTQmtiMjUwSUdoaGRtVWdkRzhoUEM5MFpENEtQSFJrSUdGc2FXZHVQU0pqWlc1MFpYSWlJSGRwWkhSb1BTSXpNQ1VpSUhOMGVXeGxQU0owWlhoMExXRnNhV2R1T2lCeWFXZG9kQ0lnUGdwSGRXVnpkQ0IxYzJWeUNnbzhMM1J5UGdvOEwzUmhZbXhsUGdvOEwzUmtQZ284TDNSeVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTVRZbElpQkNSME5QVEU5U1BTTkZSVVZGUlVVK1BHRWdhSEpsWmowaWFHOXRaUzVxYzNBaVBraHZiV1U4TDJFK1BDOTBaRDRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUhkcFpIUm9QU0l4TmlVaUlFSkhRMDlNVDFJOUkwVkZSVVZGUlQ0OFlTQm9jbVZtUFNKaFltOTFkQzVxYzNBaVBrRmliM1YwSUZWelBDOWhQand2ZEdRK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQanhoSUdoeVpXWTlJbU52Ym5SaFkzUXVhbk53SWo1RGIyNTBZV04wSUZWelBDOWhQand2ZEdRK0Nqd2hMUzBnZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJakUySlNJK1BHRWdhSEpsWmowaVlXUnRhVzR1YW5Od0lqNUJaRzFwYmp3dllUNDhMM1JrTFMwK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQZ29LQ1FrOFlTQm9jbVZtUFNKc2IyZHBiaTVxYzNBaVBreHZaMmx1UEM5aFBnb0tQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGlZbUZ6YTJWMExtcHpjQ0krV1c5MWNpQkNZWE5yWlhROEwyRStQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGljMlZoY21Ob0xtcHpjQ0krVTJWaGNtTm9QQzloUGp3dmRHUStDand2ZEhJK0NqeDBjajRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUdOdmJITndZVzQ5SWpZaVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpFd01DVWlJR05zWVhOelBTSmliM0prWlhJaVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaWJHVm1kQ0lnZG1Gc2FXZHVQU0owYjNBaUlIZHBaSFJvUFNJeU5TVWlQZ284WVNCb2NtVm1QU0p3Y205a2RXTjBMbXB6Y0Q5MGVYQmxhV1E5TmlJK1JHOXZaR0ZvY3p3dllUNDhZbkl2UGdvOFlTQm9jbVZtUFNKd2NtOWtkV04wTG1wemNEOTBlWEJsYVdROU5TSStSMmw2Ylc5elBDOWhQanhpY2k4K0NqeGhJR2h5WldZOUluQnliMlIxWTNRdWFuTndQM1I1Y0dWcFpEMHpJajVVYUdsdVoyRnRZV3BwWjNNOEwyRStQR0p5THo0S1BHRWdhSEpsWmowaWNISnZaSFZqZEM1cWMzQS9kSGx3Wldsa1BUSWlQbFJvYVc1bmFXVnpQQzloUGp4aWNpOCtDanhoSUdoeVpXWTlJbkJ5YjJSMVkzUXVhbk53UDNSNWNHVnBaRDAzSWo1WGFHRjBZMmhoYldGallXeHNhWFJ6UEM5aFBqeGljaTgrQ2p4aElHaHlaV1k5SW5CeWIyUjFZM1F1YW5Od1AzUjVjR1ZwWkQwMElqNVhhR0YwYzJsMGN6d3ZZVDQ4WW5JdlBnbzhZU0JvY21WbVBTSndjbTlrZFdOMExtcHpjRDkwZVhCbGFXUTlNU0krVjJsa1oyVjBjend2WVQ0OFluSXZQZ29LUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K1BHSnlMejQ4WW5JdlBqeGljaTgrUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K0Nqd3ZkR1ErQ2p4MFpDQjJZV3hwWjI0OUluUnZjQ0lnZDJsa2RHZzlJamN3SlNJK0NnMEtEUW84YURNK1RHOW5hVzQ4TDJnelBnMEtVR3hsWVhObElHVnVkR1Z5SUhsdmRYSWdZM0psWkdWdWRHbGhiSE02SUR4aWNpOCtQR0p5THo0TkNqeG1iM0p0SUcxbGRHaHZaRDBpVUU5VFZDSStEUW9KUEdObGJuUmxjajROQ2drOGRHRmliR1UrRFFvSlBIUnlQZzBLQ1FrOGRHUStWWE5sY201aGJXVTZQQzkwWkQ0TkNna0pQSFJrUGp4cGJuQjFkQ0JwWkQwaWRYTmxjbTVoYldVaUlHNWhiV1U5SW5WelpYSnVZVzFsSWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4ZEhJK0RRb0pDVHgwWkQ1UVlYTnpkMjl5WkRvOEwzUmtQZzBLQ1FrOGRHUStQR2x1Y0hWMElHbGtQU0p3WVhOemQyOXlaQ0lnYm1GdFpUMGljR0Z6YzNkdmNtUWlJSFI1Y0dVOUluQmhjM04zYjNKa0lqNDhMMmx1Y0hWMFBqd3ZkR1ErRFFvSlBDOTBjajROQ2drOGRISStEUW9KQ1R4MFpENDhMM1JrUGcwS0NRazhkR1ErUEdsdWNIVjBJR2xrUFNKemRXSnRhWFFpSUhSNWNHVTlJbk4xWW0xcGRDSWdkbUZzZFdVOUlreHZaMmx1SWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4TDNSaFlteGxQZzBLQ1R3dlkyVnVkR1Z5UGcwS1BDOW1iM0p0UGcwS1NXWWdlVzkxSUdSdmJuUWdhR0YyWlNCaGJpQmhZMk52ZFc1MElIZHBkR2dnZFhNZ2RHaGxiaUJ3YkdWaGMyVWdQR0VnYUhKbFpqMGljbVZuYVhOMFpYSXVhbk53SWo1U1pXZHBjM1JsY2p3dllUNGdibTkzSUdadmNpQmhJR1p5WldVZ1lXTmpiM1Z1ZEM0TkNqeGljaTgrUEdKeUx6NE5DZzBLUEM5MFpENEtQQzkwY2o0S1BDOTBZV0pzWlQ0S1BDOTBaRDRLUEM5MGNqNEtQQzkwWVdKc1pUNEtQQzlqWlc1MFpYSStDand2WW05a2VUNEtQQzlvZEcxc1Bnb05DZzBL" + } + }, + { + "pk": 140, + "model": "dojo.burprawrequestresponse", + "fields": { + "finding": 8, + "burpRequestBase64": "UjBWVUlDOWliMlJuWldsMEwyeHZaMmx1TG1wemNDQklWRlJRTHpFdU1RMEtTRzl6ZERvZ2JHOWpZV3hvYjNOME9qZzRPRGdOQ2xWelpYSXRRV2RsYm5RNklFMXZlbWxzYkdFdk5TNHdJQ2hOWVdOcGJuUnZjMmc3SUVsdWRHVnNJRTFoWXlCUFV5QllJREV3TGpFeE95Qnlkam8wTnk0d0tTQkhaV05yYnk4eU1ERXdNREV3TVNCR2FYSmxabTk0THpRM0xqQU5Da0ZqWTJWd2REb2dkR1Y0ZEM5b2RHMXNMR0Z3Y0d4cFkyRjBhVzl1TDNob2RHMXNLM2h0YkN4aGNIQnNhV05oZEdsdmJpOTRiV3c3Y1Qwd0xqa3NLaThxTzNFOU1DNDREUXBCWTJObGNIUXRUR0Z1WjNWaFoyVTZJR1Z1TFZWVExHVnVPM0U5TUM0MURRcEJZMk5sY0hRdFJXNWpiMlJwYm1jNklHZDZhWEFzSUdSbFpteGhkR1VOQ2xKbFptVnlaWEk2SUdoMGRIQTZMeTlzYjJOaGJHaHZjM1E2T0RnNE9DOWliMlJuWldsMEx3MEtRMjl2YTJsbE9pQktVMFZUVTBsUFRrbEVQVFpGT1RVM04wRXhOa0pCUXpZeE9URXpSRVU1TjBFNE9EZEJSRFl3TWpjMURRcERiMjV1WldOMGFXOXVPaUJqYkc5elpRMEtEUW89", + "burpResponseBase64": "U0ZSVVVDOHhMakVnTWpBd0lBMEtVMlZ5ZG1WeU9pQkJjR0ZqYUdVdFEyOTViM1JsTHpFdU1RMEtRMjl1ZEdWdWRDMVVlWEJsT2lCMFpYaDBMMmgwYld3N1kyaGhjbk5sZEQxSlUwOHRPRGcxT1MweERRcERiMjUwWlc1MExVeGxibWQwYURvZ01qUTJNZzBLUkdGMFpUb2dVMkYwTENBeU55QkJkV2NnTWpBeE5pQXdNam93T0RvMU55QkhUVlFOQ2tOdmJtNWxZM1JwYjI0NklHTnNiM05sRFFvTkNnMEtEUW9OQ2cwS0Nnb0tDandoUkU5RFZGbFFSU0JJVkUxTUlGQlZRa3hKUXlBaUxTOHZWek5ETHk5RVZFUWdTRlJOVENBekxqSXZMMFZPSWo0S1BHaDBiV3crQ2p4b1pXRmtQZ284ZEdsMGJHVStWR2hsSUVKdlpHZGxTWFFnVTNSdmNtVThMM1JwZEd4bFBnbzhiR2x1YXlCb2NtVm1QU0p6ZEhsc1pTNWpjM01pSUhKbGJEMGljM1I1YkdWemFHVmxkQ0lnZEhsd1pUMGlkR1Y0ZEM5amMzTWlJQzgrQ2p4elkzSnBjSFFnZEhsd1pUMGlkR1Y0ZEM5cVlYWmhjMk55YVhCMElpQnpjbU05SWk0dmFuTXZkWFJwYkM1cWN5SStQQzl6WTNKcGNIUStDand2YUdWaFpENEtQR0p2WkhrK0NnbzhZMlZ1ZEdWeVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpnd0pTSWdZMnhoYzNNOUltSnZjbVJsY2lJK0NqeDBjaUJDUjBOUFRFOVNQU05ETTBRNVJrWStDangwWkNCaGJHbG5iajBpWTJWdWRHVnlJaUJqYjJ4emNHRnVQU0kySWo0S1BFZ3hQbFJvWlNCQ2IyUm5aVWwwSUZOMGIzSmxQQzlJTVQ0S1BIUmhZbXhsSUhkcFpIUm9QU0l4TURBbElpQmpiR0Z6Y3oxY0ltNXZZbTl5WkdWeVhDSStDangwY2lCQ1IwTlBURTlTUFNORE0wUTVSa1krQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTXpBbElqNG1ibUp6Y0RzOEwzUmtQZ284ZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJalF3SlNJK1YyVWdZbTlrWjJVZ2FYUXNJSE52SUhsdmRTQmtiMjUwSUdoaGRtVWdkRzhoUEM5MFpENEtQSFJrSUdGc2FXZHVQU0pqWlc1MFpYSWlJSGRwWkhSb1BTSXpNQ1VpSUhOMGVXeGxQU0owWlhoMExXRnNhV2R1T2lCeWFXZG9kQ0lnUGdwSGRXVnpkQ0IxYzJWeUNnbzhMM1J5UGdvOEwzUmhZbXhsUGdvOEwzUmtQZ284TDNSeVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaVkyVnVkR1Z5SWlCM2FXUjBhRDBpTVRZbElpQkNSME5QVEU5U1BTTkZSVVZGUlVVK1BHRWdhSEpsWmowaWFHOXRaUzVxYzNBaVBraHZiV1U4TDJFK1BDOTBaRDRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUhkcFpIUm9QU0l4TmlVaUlFSkhRMDlNVDFJOUkwVkZSVVZGUlQ0OFlTQm9jbVZtUFNKaFltOTFkQzVxYzNBaVBrRmliM1YwSUZWelBDOWhQand2ZEdRK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQanhoSUdoeVpXWTlJbU52Ym5SaFkzUXVhbk53SWo1RGIyNTBZV04wSUZWelBDOWhQand2ZEdRK0Nqd2hMUzBnZEdRZ1lXeHBaMjQ5SW1ObGJuUmxjaUlnZDJsa2RHZzlJakUySlNJK1BHRWdhSEpsWmowaVlXUnRhVzR1YW5Od0lqNUJaRzFwYmp3dllUNDhMM1JrTFMwK0NnbzhkR1FnWVd4cFoyNDlJbU5sYm5SbGNpSWdkMmxrZEdnOUlqRTJKU0lnUWtkRFQweFBVajBqUlVWRlJVVkZQZ29LQ1FrOFlTQm9jbVZtUFNKc2IyZHBiaTVxYzNBaVBreHZaMmx1UEM5aFBnb0tQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGlZbUZ6YTJWMExtcHpjQ0krV1c5MWNpQkNZWE5yWlhROEwyRStQQzkwWkQ0S0NqeDBaQ0JoYkdsbmJqMGlZMlZ1ZEdWeUlpQjNhV1IwYUQwaU1UWWxJaUJDUjBOUFRFOVNQU05GUlVWRlJVVStQR0VnYUhKbFpqMGljMlZoY21Ob0xtcHpjQ0krVTJWaGNtTm9QQzloUGp3dmRHUStDand2ZEhJK0NqeDBjajRLUEhSa0lHRnNhV2R1UFNKalpXNTBaWElpSUdOdmJITndZVzQ5SWpZaVBnbzhkR0ZpYkdVZ2QybGtkR2c5SWpFd01DVWlJR05zWVhOelBTSmliM0prWlhJaVBnbzhkSEkrQ2p4MFpDQmhiR2xuYmowaWJHVm1kQ0lnZG1Gc2FXZHVQU0owYjNBaUlIZHBaSFJvUFNJeU5TVWlQZ284WVNCb2NtVm1QU0p3Y205a2RXTjBMbXB6Y0Q5MGVYQmxhV1E5TmlJK1JHOXZaR0ZvY3p3dllUNDhZbkl2UGdvOFlTQm9jbVZtUFNKd2NtOWtkV04wTG1wemNEOTBlWEJsYVdROU5TSStSMmw2Ylc5elBDOWhQanhpY2k4K0NqeGhJR2h5WldZOUluQnliMlIxWTNRdWFuTndQM1I1Y0dWcFpEMHpJajVVYUdsdVoyRnRZV3BwWjNNOEwyRStQR0p5THo0S1BHRWdhSEpsWmowaWNISnZaSFZqZEM1cWMzQS9kSGx3Wldsa1BUSWlQbFJvYVc1bmFXVnpQQzloUGp4aWNpOCtDanhoSUdoeVpXWTlJbkJ5YjJSMVkzUXVhbk53UDNSNWNHVnBaRDAzSWo1WGFHRjBZMmhoYldGallXeHNhWFJ6UEM5aFBqeGljaTgrQ2p4aElHaHlaV1k5SW5CeWIyUjFZM1F1YW5Od1AzUjVjR1ZwWkQwMElqNVhhR0YwYzJsMGN6d3ZZVDQ4WW5JdlBnbzhZU0JvY21WbVBTSndjbTlrZFdOMExtcHpjRDkwZVhCbGFXUTlNU0krVjJsa1oyVjBjend2WVQ0OFluSXZQZ29LUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K1BHSnlMejQ4WW5JdlBqeGljaTgrUEdKeUx6NDhZbkl2UGp4aWNpOCtQR0p5THo0OFluSXZQanhpY2k4K0Nqd3ZkR1ErQ2p4MFpDQjJZV3hwWjI0OUluUnZjQ0lnZDJsa2RHZzlJamN3SlNJK0NnMEtEUW84YURNK1RHOW5hVzQ4TDJnelBnMEtVR3hsWVhObElHVnVkR1Z5SUhsdmRYSWdZM0psWkdWdWRHbGhiSE02SUR4aWNpOCtQR0p5THo0TkNqeG1iM0p0SUcxbGRHaHZaRDBpVUU5VFZDSStEUW9KUEdObGJuUmxjajROQ2drOGRHRmliR1UrRFFvSlBIUnlQZzBLQ1FrOGRHUStWWE5sY201aGJXVTZQQzkwWkQ0TkNna0pQSFJrUGp4cGJuQjFkQ0JwWkQwaWRYTmxjbTVoYldVaUlHNWhiV1U5SW5WelpYSnVZVzFsSWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4ZEhJK0RRb0pDVHgwWkQ1UVlYTnpkMjl5WkRvOEwzUmtQZzBLQ1FrOGRHUStQR2x1Y0hWMElHbGtQU0p3WVhOemQyOXlaQ0lnYm1GdFpUMGljR0Z6YzNkdmNtUWlJSFI1Y0dVOUluQmhjM04zYjNKa0lqNDhMMmx1Y0hWMFBqd3ZkR1ErRFFvSlBDOTBjajROQ2drOGRISStEUW9KQ1R4MFpENDhMM1JrUGcwS0NRazhkR1ErUEdsdWNIVjBJR2xrUFNKemRXSnRhWFFpSUhSNWNHVTlJbk4xWW0xcGRDSWdkbUZzZFdVOUlreHZaMmx1SWo0OEwybHVjSFYwUGp3dmRHUStEUW9KUEM5MGNqNE5DZ2s4TDNSaFlteGxQZzBLQ1R3dlkyVnVkR1Z5UGcwS1BDOW1iM0p0UGcwS1NXWWdlVzkxSUdSdmJuUWdhR0YyWlNCaGJpQmhZMk52ZFc1MElIZHBkR2dnZFhNZ2RHaGxiaUJ3YkdWaGMyVWdQR0VnYUhKbFpqMGljbVZuYVhOMFpYSXVhbk53SWo1U1pXZHBjM1JsY2p3dllUNGdibTkzSUdadmNpQmhJR1p5WldVZ1lXTmpiM1Z1ZEM0TkNqeGljaTgrUEdKeUx6NE5DZzBLUEM5MFpENEtQQzkwY2o0S1BDOTBZV0pzWlQ0S1BDOTBaRDRLUEM5MGNqNEtQQzkwWVdKc1pUNEtQQzlqWlc1MFpYSStDand2WW05a2VUNEtQQzlvZEcxc1Bnb05DZzBL" + } + } +] \ No newline at end of file diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index b0bc3c4da2..d8f37f8680 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -200,6 +200,8 @@ # maximum number of result in search as search can be an expensive operation DD_SEARCH_MAX_RESULTS=(int, 100), DD_SIMILAR_FINDINGS_MAX_RESULTS=(int, 25), + # The maximum number of request/response pairs to return from the API. Values <0 return all pairs. + DD_MAX_REQRESP_FROM_API=(int, -1), DD_MAX_AUTOCOMPLETE_WORDS=(int, 20000), DD_JIRA_SSL_VERIFY=(bool, True), # You can set extra Jira issue types via a simple env var that supports a csv format, like "Work Item,Vulnerability" @@ -233,7 +235,6 @@ DD_FEATURE_FINDING_GROUPS=(bool, True), DD_JIRA_TEMPLATE_ROOT=(str, 'dojo/templates/issue-trackers'), DD_TEMPLATE_DIR_PREFIX=(str, 'dojo/templates/'), - # Initial behaviour in Defect Dojo was to delete all duplicates when an original was deleted # New behaviour is to leave the duplicates in place, but set the oldest of duplicates as new original # Set to True to revert to the old behaviour where all duplicates are deleted @@ -599,6 +600,7 @@ def generate_url(scheme, double_slashes, user, password, host, port, path, param SEARCH_MAX_RESULTS = env('DD_SEARCH_MAX_RESULTS') SIMILAR_FINDINGS_MAX_RESULTS = env('DD_SIMILAR_FINDINGS_MAX_RESULTS') +MAX_REQRESP_FROM_API = env('DD_MAX_REQRESP_FROM_API') MAX_AUTOCOMPLETE_WORDS = env('DD_MAX_AUTOCOMPLETE_WORDS') LOGIN_EXEMPT_URLS = ( diff --git a/dojo/urls.py b/dojo/urls.py index 4500e1e49d..3b5c335ada 100755 --- a/dojo/urls.py +++ b/dojo/urls.py @@ -81,7 +81,7 @@ v2_api.register(r'engagements', EngagementViewSet) v2_api.register(r'development_environments', DevelopmentEnvironmentViewSet) v2_api.register(r'finding_templates', FindingTemplatesViewSet) -v2_api.register(r'findings', FindingViewSet) +v2_api.register(r'findings', FindingViewSet, basename='finding') v2_api.register(r'jira_configurations', JiraInstanceViewSet) # backwards compatibility v2_api.register(r'jira_instances', JiraInstanceViewSet) v2_api.register(r'jira_finding_mappings', JiraIssuesViewSet) diff --git a/readme-docs/DOCKER.md b/readme-docs/DOCKER.md index 2dbb8a5f52..d88bfd29ba 100644 --- a/readme-docs/DOCKER.md +++ b/readme-docs/DOCKER.md @@ -335,16 +335,26 @@ The integration-tests are under `tests` ## Running the unit tests + +### All tests This will run all unit-tests and leave the uwsgi container up: ``` docker/setEnv.sh unit_tests ./dc-up.sh ``` -Enter the container to run more tests: +### Limited tests +If you want to enter the container to run more tests or a single test case, leave setEnv in normal or dev mode: +``` +docker/setEnv.sh dev +./dc-up.sh +``` +Then ``` -docker-compose exec uwsgi bash +docker ps +#find the name of the uwsgi container from the above command +docker exec -ti [container-name] bash ``` Rerun all the tests: diff --git a/unittests/scans/burp_api/many_reqresp.json b/unittests/scans/burp_api/many_reqresp.json new file mode 100644 index 0000000000..ee33a933ce --- /dev/null +++ b/unittests/scans/burp_api/many_reqresp.json @@ -0,0 +1,734 @@ +{ + "task_id": "3", + "scan_status": "auditing", + "scan_metrics": { + "crawl_requests_made": 90, + "crawl_network_errors": 0, + "crawl_unique_locations_visited": 19, + "crawl_requests_queued": 0, + "audit_queue_items_completed": 0, + "audit_queue_items_waiting": 27, + "audit_requests_made": 4336, + "audit_network_errors": 0, + "issue_events": 1, + "crawl_and_audit_caption": "Auditing. Estimating time remaining...", + "crawl_and_audit_progress": 0 + }, + "message": "", + "issue_events": [ + { + "id": "0", + "type": "issue_found", + "issue": { + "name": "Robots.txt file", + "type_index": 6292992, + "serial_number": "3242427303404163072", + "origin": "https://juice-shop.herokuapp.com", + "path": "/robots.txt", + "severity": "info", + "confidence": "certain", + "description": "The web server contains a robots.txt file.", + "caption": "/robots.txt", + "evidence": [ + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + }, + { + "type": "HighlightSegment", + "data": "L2Z0cC9janVtLmJhaw==", + "length": 13 + }, + { + "type": "DataSegment", + "data": "IEhUVFAvMS4xDQpIb3N0OiBqdWljZS1zaG9wLmhlcm9rdWFwcC5jb20NCkFjY2VwdC1FbmNvZGluZzogZ3ppcCwgZGVmbGF0ZQ0KQWNjZXB0OiAqLyoNCkFjY2VwdC1MYW5ndWFnZTogZW4tVVMsZW4tR0I7cT0wLjksZW47cT0wLjgNClVzZXItQWdlbnQ6IE1vemlsbGEvNS4wIChXaW5kb3dzIE5UIDEwLjA7IFdpbjY0OyB4NjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS84Ni4wLjQyNDAuMTgzIFNhZmFyaS81MzcuMzYNCkNvbm5lY3Rpb246IGNsb3NlDQpDYWNoZS1Db250cm9sOiBtYXgtYWdlPTANClJlZmVyZXI6IGh0dHBzOi8vanVpY2Utc2hvcC5oZXJva3VhcHAuY29tL2Z0cC8NCkNvb2tpZTogaW89blNTbUFxS1RCaDBnNGhEOEFBYVQ7IGxhbmd1YWdlPWVuOyB3ZWxjb21lYmFubmVyX3N0YXR1cz1kaXNtaXNzDQoNCg==", + "length": 433 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEg", + "length": 9 + }, + { + "type": "HighlightSegment", + "data": "NDAz", + "length": 3 + }, + { + "type": "DataSegment", + "data": "IEZvcmJpZGRlbg0KU2VydmVyOiBDb3dib3kNCkNvbm5lY3Rpb246IGNsb3NlDQpBY2Nlc3MtQ29udHJvbC1BbGxvdy1PcmlnaW46ICoNClgtQ29udGVudC1UeXBlLU9wdGlvbnM6IG5vc25pZmYNClgtRnJhbWUtT3B0aW9uczogU0FNRU9SSUdJTg0KRmVhdHVyZS1Qb2xpY3k6IHBheW1lbnQgJ3NlbGYnDQpDb250ZW50LVR5cGU6IA==", + "length": 187 + }, + { + "type": "HighlightSegment", + "data": "dGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04", + "length": 24 + }, + { + "type": "DataSegment", + "data": "DQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6Mjc6MzUgR01UDQpWaWE6IDEuMSB2ZWd1cg0KQ29udGVudC1MZW5ndGg6IA==", + "length": 94 + }, + { + "type": "HighlightSegment", + "data": "MTg1Mg==", + "length": 4 + }, + { + "type": "DataSegment", + "data": "DQoNCjxodG1sPgogIDxoZWFkPgogICAgPG1ldGEgY2hhcnNldD0ndXRmLTgnPiAKICAgIDx0aXRsZT4=", + "length": 59 + }, + { + "type": "HighlightSegment", + "data": "RXJyb3I6IE9ubHkgLm1kIGFuZCAucGRmIGZpbGVzIGFyZSBhbGxvd2VkIQ==", + "length": 43 + }, + { + "type": "DataSegment", + "data": "PC90aXRsZT4KICAgIDxzdHlsZT4qIHsKICBtYXJnaW46IDA7CiAgcGFkZGluZzogMDsKICBvdXRsaW5lOiAwOwp9Cgpib2R5IHsKICBwYWRkaW5nOiA4MHB4IDEwMHB4OwogIGZv", + "length": 102 + }, + { + "type": "SnipSegment", + "length": 577 + }, + { + "type": "DataSegment", + "data": "PGgxPg==", + "length": 4 + }, + { + "type": "HighlightSegment", + "data": "T1dBU1AgSnVpY2UgU2hvcCAoRXhwcmVzcyBeNC4xNy4xKQ==", + "length": 34 + }, + { + "type": "DataSegment", + "data": "PC9oMT4=", + "length": 5 + }, + { + "type": "SnipSegment", + "length": 861 + }, + { + "type": "DataSegment", + "data": "PGxpPg==", + "length": 4 + }, + { + "type": "HighlightSegment", + "data": "ICZuYnNwOyAmbmJzcDthdCAvYXBwL25vZGVfbW9kdWxlcy9zZXJ2ZS1pbmRleC9pbmRleC5qczoxMzU6MTY=", + "length": 62 + }, + { + "type": "DataSegment", + "data": "PC9saT48bGk+", + "length": 9 + }, + { + "type": "HighlightSegment", + "data": "ICZuYnNwOyAmbmJzcDthdCBGU1JlcUNhbGxiYWNrLm9uY29tcGxldGUgKGZzLmpzOjE4MzoyMSk=", + "length": 56 + }, + { + "type": "DataSegment", + "data": "PC9saT4=", + "length": 5 + }, + { + "type": "SnipSegment", + "length": 35 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + }, + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IENvd2JveQ0KQ29ubmVjdGlvbjogY2xvc2UNCkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbjogKg0KWC1Db250ZW50LVR5cGUtT3B0aW9uczogbm9zbmlmZg0KWC1GcmFtZS1PcHRpb25zOiBTQU1FT1JJR0lODQpGZWF0dXJlLVBvbGljeTogcGF5bWVudCAnc2VsZicNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1MZW5ndGg6IDI4DQpFdGFnOiBXLyIxYy04SGdGNm1OeWhzU0ZLMHBhc2NDOXVCMHdqWDAiDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6MjQ6NTEgR01UDQpWaWE6IDEuMSB2ZWd1cg0KDQpVc2VyLWFnZW50OiAqCkRpc2FsbG93OiAvZnRw", + "length": 387 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + }, + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IENvd2JveQ0KQ29ubmVjdGlvbjogY2xvc2UNCkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbjogKg0KWC1Db250ZW50LVR5cGUtT3B0aW9uczogbm9zbmlmZg0KWC1GcmFtZS1PcHRpb25zOiBTQU1FT1JJR0lODQpGZWF0dXJlLVBvbGljeTogcGF5bWVudCAnc2VsZicNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1MZW5ndGg6IDI4DQpFdGFnOiBXLyIxYy04SGdGNm1OeWhzU0ZLMHBhc2NDOXVCMHdqWDAiDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6MjQ6NTEgR01UDQpWaWE6IDEuMSB2ZWd1cg0KDQpVc2VyLWFnZW50OiAqCkRpc2FsbG93OiAvZnRw", + "length": 387 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + }, + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IENvd2JveQ0KQ29ubmVjdGlvbjogY2xvc2UNCkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbjogKg0KWC1Db250ZW50LVR5cGUtT3B0aW9uczogbm9zbmlmZg0KWC1GcmFtZS1PcHRpb25zOiBTQU1FT1JJR0lODQpGZWF0dXJlLVBvbGljeTogcGF5bWVudCAnc2VsZicNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1MZW5ndGg6IDI4DQpFdGFnOiBXLyIxYy04SGdGNm1OeWhzU0ZLMHBhc2NDOXVCMHdqWDAiDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6MjQ6NTEgR01UDQpWaWE6IDEuMSB2ZWd1cg0KDQpVc2VyLWFnZW50OiAqCkRpc2FsbG93OiAvZnRw", + "length": 387 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + }, + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IENvd2JveQ0KQ29ubmVjdGlvbjogY2xvc2UNCkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbjogKg0KWC1Db250ZW50LVR5cGUtT3B0aW9uczogbm9zbmlmZg0KWC1GcmFtZS1PcHRpb25zOiBTQU1FT1JJR0lODQpGZWF0dXJlLVBvbGljeTogcGF5bWVudCAnc2VsZicNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1MZW5ndGg6IDI4DQpFdGFnOiBXLyIxYy04SGdGNm1OeWhzU0ZLMHBhc2NDOXVCMHdqWDAiDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6MjQ6NTEgR01UDQpWaWE6IDEuMSB2ZWd1cg0KDQpVc2VyLWFnZW50OiAqCkRpc2FsbG93OiAvZnRw", + "length": 387 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + }, + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IENvd2JveQ0KQ29ubmVjdGlvbjogY2xvc2UNCkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbjogKg0KWC1Db250ZW50LVR5cGUtT3B0aW9uczogbm9zbmlmZg0KWC1GcmFtZS1PcHRpb25zOiBTQU1FT1JJR0lODQpGZWF0dXJlLVBvbGljeTogcGF5bWVudCAnc2VsZicNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1MZW5ndGg6IDI4DQpFdGFnOiBXLyIxYy04SGdGNm1OeWhzU0ZLMHBhc2NDOXVCMHdqWDAiDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6MjQ6NTEgR01UDQpWaWE6IDEuMSB2ZWd1cg0KDQpVc2VyLWFnZW50OiAqCkRpc2FsbG93OiAvZnRw", + "length": 387 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + }, + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IENvd2JveQ0KQ29ubmVjdGlvbjogY2xvc2UNCkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbjogKg0KWC1Db250ZW50LVR5cGUtT3B0aW9uczogbm9zbmlmZg0KWC1GcmFtZS1PcHRpb25zOiBTQU1FT1JJR0lODQpGZWF0dXJlLVBvbGljeTogcGF5bWVudCAnc2VsZicNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1MZW5ndGg6IDI4DQpFdGFnOiBXLyIxYy04SGdGNm1OeWhzU0ZLMHBhc2NDOXVCMHdqWDAiDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6MjQ6NTEgR01UDQpWaWE6IDEuMSB2ZWd1cg0KDQpVc2VyLWFnZW50OiAqCkRpc2FsbG93OiAvZnRw", + "length": 387 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + }, + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IENvd2JveQ0KQ29ubmVjdGlvbjogY2xvc2UNCkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbjogKg0KWC1Db250ZW50LVR5cGUtT3B0aW9uczogbm9zbmlmZg0KWC1GcmFtZS1PcHRpb25zOiBTQU1FT1JJR0lODQpGZWF0dXJlLVBvbGljeTogcGF5bWVudCAnc2VsZicNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1MZW5ndGg6IDI4DQpFdGFnOiBXLyIxYy04SGdGNm1OeWhzU0ZLMHBhc2NDOXVCMHdqWDAiDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6MjQ6NTEgR01UDQpWaWE6IDEuMSB2ZWd1cg0KDQpVc2VyLWFnZW50OiAqCkRpc2FsbG93OiAvZnRw", + "length": 387 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + }, + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IENvd2JveQ0KQ29ubmVjdGlvbjogY2xvc2UNCkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbjogKg0KWC1Db250ZW50LVR5cGUtT3B0aW9uczogbm9zbmlmZg0KWC1GcmFtZS1PcHRpb25zOiBTQU1FT1JJR0lODQpGZWF0dXJlLVBvbGljeTogcGF5bWVudCAnc2VsZicNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1MZW5ndGg6IDI4DQpFdGFnOiBXLyIxYy04SGdGNm1OeWhzU0ZLMHBhc2NDOXVCMHdqWDAiDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6MjQ6NTEgR01UDQpWaWE6IDEuMSB2ZWd1cg0KDQpVc2VyLWFnZW50OiAqCkRpc2FsbG93OiAvZnRw", + "length": 387 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + }, + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IENvd2JveQ0KQ29ubmVjdGlvbjogY2xvc2UNCkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbjogKg0KWC1Db250ZW50LVR5cGUtT3B0aW9uczogbm9zbmlmZg0KWC1GcmFtZS1PcHRpb25zOiBTQU1FT1JJR0lODQpGZWF0dXJlLVBvbGljeTogcGF5bWVudCAnc2VsZicNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1MZW5ndGg6IDI4DQpFdGFnOiBXLyIxYy04SGdGNm1OeWhzU0ZLMHBhc2NDOXVCMHdqWDAiDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6MjQ6NTEgR01UDQpWaWE6IDEuMSB2ZWd1cg0KDQpVc2VyLWFnZW50OiAqCkRpc2FsbG93OiAvZnRw", + "length": 387 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + }, + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IENvd2JveQ0KQ29ubmVjdGlvbjogY2xvc2UNCkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbjogKg0KWC1Db250ZW50LVR5cGUtT3B0aW9uczogbm9zbmlmZg0KWC1GcmFtZS1PcHRpb25zOiBTQU1FT1JJR0lODQpGZWF0dXJlLVBvbGljeTogcGF5bWVudCAnc2VsZicNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1MZW5ndGg6IDI4DQpFdGFnOiBXLyIxYy04SGdGNm1OeWhzU0ZLMHBhc2NDOXVCMHdqWDAiDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6MjQ6NTEgR01UDQpWaWE6IDEuMSB2ZWd1cg0KDQpVc2VyLWFnZW50OiAqCkRpc2FsbG93OiAvZnRw", + "length": 387 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + }, + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IENvd2JveQ0KQ29ubmVjdGlvbjogY2xvc2UNCkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbjogKg0KWC1Db250ZW50LVR5cGUtT3B0aW9uczogbm9zbmlmZg0KWC1GcmFtZS1PcHRpb25zOiBTQU1FT1JJR0lODQpGZWF0dXJlLVBvbGljeTogcGF5bWVudCAnc2VsZicNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1MZW5ndGg6IDI4DQpFdGFnOiBXLyIxYy04SGdGNm1OeWhzU0ZLMHBhc2NDOXVCMHdqWDAiDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6MjQ6NTEgR01UDQpWaWE6IDEuMSB2ZWd1cg0KDQpVc2VyLWFnZW50OiAqCkRpc2FsbG93OiAvZnRw", + "length": 387 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + }, + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IENvd2JveQ0KQ29ubmVjdGlvbjogY2xvc2UNCkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbjogKg0KWC1Db250ZW50LVR5cGUtT3B0aW9uczogbm9zbmlmZg0KWC1GcmFtZS1PcHRpb25zOiBTQU1FT1JJR0lODQpGZWF0dXJlLVBvbGljeTogcGF5bWVudCAnc2VsZicNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1MZW5ndGg6IDI4DQpFdGFnOiBXLyIxYy04SGdGNm1OeWhzU0ZLMHBhc2NDOXVCMHdqWDAiDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6MjQ6NTEgR01UDQpWaWE6IDEuMSB2ZWd1cg0KDQpVc2VyLWFnZW50OiAqCkRpc2FsbG93OiAvZnRw", + "length": 387 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + }, + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IENvd2JveQ0KQ29ubmVjdGlvbjogY2xvc2UNCkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbjogKg0KWC1Db250ZW50LVR5cGUtT3B0aW9uczogbm9zbmlmZg0KWC1GcmFtZS1PcHRpb25zOiBTQU1FT1JJR0lODQpGZWF0dXJlLVBvbGljeTogcGF5bWVudCAnc2VsZicNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1MZW5ndGg6IDI4DQpFdGFnOiBXLyIxYy04SGdGNm1OeWhzU0ZLMHBhc2NDOXVCMHdqWDAiDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6MjQ6NTEgR01UDQpWaWE6IDEuMSB2ZWd1cg0KDQpVc2VyLWFnZW50OiAqCkRpc2FsbG93OiAvZnRw", + "length": 387 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + }, + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IENvd2JveQ0KQ29ubmVjdGlvbjogY2xvc2UNCkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbjogKg0KWC1Db250ZW50LVR5cGUtT3B0aW9uczogbm9zbmlmZg0KWC1GcmFtZS1PcHRpb25zOiBTQU1FT1JJR0lODQpGZWF0dXJlLVBvbGljeTogcGF5bWVudCAnc2VsZicNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1MZW5ndGg6IDI4DQpFdGFnOiBXLyIxYy04SGdGNm1OeWhzU0ZLMHBhc2NDOXVCMHdqWDAiDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6MjQ6NTEgR01UDQpWaWE6IDEuMSB2ZWd1cg0KDQpVc2VyLWFnZW50OiAqCkRpc2FsbG93OiAvZnRw", + "length": 387 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + }, + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IENvd2JveQ0KQ29ubmVjdGlvbjogY2xvc2UNCkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbjogKg0KWC1Db250ZW50LVR5cGUtT3B0aW9uczogbm9zbmlmZg0KWC1GcmFtZS1PcHRpb25zOiBTQU1FT1JJR0lODQpGZWF0dXJlLVBvbGljeTogcGF5bWVudCAnc2VsZicNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1MZW5ndGg6IDI4DQpFdGFnOiBXLyIxYy04SGdGNm1OeWhzU0ZLMHBhc2NDOXVCMHdqWDAiDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6MjQ6NTEgR01UDQpWaWE6IDEuMSB2ZWd1cg0KDQpVc2VyLWFnZW50OiAqCkRpc2FsbG93OiAvZnRw", + "length": 387 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + }, + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IENvd2JveQ0KQ29ubmVjdGlvbjogY2xvc2UNCkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbjogKg0KWC1Db250ZW50LVR5cGUtT3B0aW9uczogbm9zbmlmZg0KWC1GcmFtZS1PcHRpb25zOiBTQU1FT1JJR0lODQpGZWF0dXJlLVBvbGljeTogcGF5bWVudCAnc2VsZicNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1MZW5ndGg6IDI4DQpFdGFnOiBXLyIxYy04SGdGNm1OeWhzU0ZLMHBhc2NDOXVCMHdqWDAiDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6MjQ6NTEgR01UDQpWaWE6IDEuMSB2ZWd1cg0KDQpVc2VyLWFnZW50OiAqCkRpc2FsbG93OiAvZnRw", + "length": 387 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + }, + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IENvd2JveQ0KQ29ubmVjdGlvbjogY2xvc2UNCkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbjogKg0KWC1Db250ZW50LVR5cGUtT3B0aW9uczogbm9zbmlmZg0KWC1GcmFtZS1PcHRpb25zOiBTQU1FT1JJR0lODQpGZWF0dXJlLVBvbGljeTogcGF5bWVudCAnc2VsZicNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1MZW5ndGg6IDI4DQpFdGFnOiBXLyIxYy04SGdGNm1OeWhzU0ZLMHBhc2NDOXVCMHdqWDAiDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6MjQ6NTEgR01UDQpWaWE6IDEuMSB2ZWd1cg0KDQpVc2VyLWFnZW50OiAqCkRpc2FsbG93OiAvZnRw", + "length": 387 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + }, + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IENvd2JveQ0KQ29ubmVjdGlvbjogY2xvc2UNCkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbjogKg0KWC1Db250ZW50LVR5cGUtT3B0aW9uczogbm9zbmlmZg0KWC1GcmFtZS1PcHRpb25zOiBTQU1FT1JJR0lODQpGZWF0dXJlLVBvbGljeTogcGF5bWVudCAnc2VsZicNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1MZW5ndGg6IDI4DQpFdGFnOiBXLyIxYy04SGdGNm1OeWhzU0ZLMHBhc2NDOXVCMHdqWDAiDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6MjQ6NTEgR01UDQpWaWE6IDEuMSB2ZWd1cg0KDQpVc2VyLWFnZW50OiAqCkRpc2FsbG93OiAvZnRw", + "length": 387 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + }, + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IENvd2JveQ0KQ29ubmVjdGlvbjogY2xvc2UNCkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbjogKg0KWC1Db250ZW50LVR5cGUtT3B0aW9uczogbm9zbmlmZg0KWC1GcmFtZS1PcHRpb25zOiBTQU1FT1JJR0lODQpGZWF0dXJlLVBvbGljeTogcGF5bWVudCAnc2VsZicNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1MZW5ndGg6IDI4DQpFdGFnOiBXLyIxYy04SGdGNm1OeWhzU0ZLMHBhc2NDOXVCMHdqWDAiDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6MjQ6NTEgR01UDQpWaWE6IDEuMSB2ZWd1cg0KDQpVc2VyLWFnZW50OiAqCkRpc2FsbG93OiAvZnRw", + "length": 387 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + }, + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IENvd2JveQ0KQ29ubmVjdGlvbjogY2xvc2UNCkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbjogKg0KWC1Db250ZW50LVR5cGUtT3B0aW9uczogbm9zbmlmZg0KWC1GcmFtZS1PcHRpb25zOiBTQU1FT1JJR0lODQpGZWF0dXJlLVBvbGljeTogcGF5bWVudCAnc2VsZicNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1MZW5ndGg6IDI4DQpFdGFnOiBXLyIxYy04SGdGNm1OeWhzU0ZLMHBhc2NDOXVCMHdqWDAiDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6MjQ6NTEgR01UDQpWaWE6IDEuMSB2ZWd1cg0KDQpVc2VyLWFnZW50OiAqCkRpc2FsbG93OiAvZnRw", + "length": 387 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + }, + { + "type": "FirstOrderEvidence", + "detail": { + "band_flags": [ + "in_band" + ] + }, + "request_response": { + "url": "https://juice-shop.herokuapp.com/robots.txt", + "request": [ + { + "type": "DataSegment", + "data": "R0VUIA==", + "length": 4 + } + ], + "response": [ + { + "type": "DataSegment", + "data": "SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IENvd2JveQ0KQ29ubmVjdGlvbjogY2xvc2UNCkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbjogKg0KWC1Db250ZW50LVR5cGUtT3B0aW9uczogbm9zbmlmZg0KWC1GcmFtZS1PcHRpb25zOiBTQU1FT1JJR0lODQpGZWF0dXJlLVBvbGljeTogcGF5bWVudCAnc2VsZicNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KQ29udGVudC1MZW5ndGg6IDI4DQpFdGFnOiBXLyIxYy04SGdGNm1OeWhzU0ZLMHBhc2NDOXVCMHdqWDAiDQpWYXJ5OiBBY2NlcHQtRW5jb2RpbmcNCkRhdGU6IFR1ZSwgMTkgSmFuIDIwMjEgMTQ6MjQ6NTEgR01UDQpWaWE6IDEuMSB2ZWd1cg0KDQpVc2VyLWFnZW50OiAqCkRpc2FsbG93OiAvZnRw", + "length": 387 + } + ], + "was_redirect_followed": false, + "request_time": "1611066291482" + } + } + ], + "internal_data": "eyJmbGFncyI6MCwidmFyaWFudCI6MCwiaXNzdWVfZGV0YWlsc19tYXAiOnt9fQ==" + } + } + ] +} \ No newline at end of file diff --git a/unittests/test_apiv2_limit_reqresp.py b/unittests/test_apiv2_limit_reqresp.py new file mode 100644 index 0000000000..0701b39b14 --- /dev/null +++ b/unittests/test_apiv2_limit_reqresp.py @@ -0,0 +1,42 @@ +from rest_framework.test import APITestCase, APIClient +from django.urls import reverse +from rest_framework.authtoken.models import Token +from django.conf import settings + + +class APILimitReqRespPairsTest(APITestCase): + """ + Test the MAX_REQRESP_FROM_API setting for /api/v2/findings/{id}/request_response/ + """ + + fixtures = ['unit_limit_reqresp.json'] + + def setUp(self: object): + token = Token.objects.get(user__username='admin') + self.client = APIClient() + self.client.credentials(HTTP_AUTHORIZATION='Token ' + token.key) + + def assertReqrespValue(self: object, value: int, expect_notequal: bool = False) -> None: + settings.MAX_REQRESP_FROM_API = value + r = self.client.get(reverse('finding-list'), format='json') + results = r.json()['results'] + # get finding with id 8 + finding = self.getFinding(8, results) + if expect_notequal: + self.assertNotEqual(len(finding['request_response']['req_resp']), value) + else: + self.assertEqual(len(finding['request_response']['req_resp']), value) + + def getFinding(self: object, idn: int, results: list) -> dict: + for result in results: + if result['id'] == idn: + return result + return None + + def test_reqresp(self: object) -> None: + self.assertReqrespValue(5) + self.assertReqrespValue(10) + self.assertReqrespValue(18) # actual number of reqresp + self.assertReqrespValue(100, True) # more than the number in the request + self.assertReqrespValue(-1, True) # default value of MAX_REQRESP_FROM_API + self.assertReqrespValue(-100, True) # crazy negative value From 3f5c75adeb9c5fcc13a81343adf6a6f9005fdaef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 13:39:56 -0500 Subject: [PATCH 058/138] Bump asteval from 0.9.31 to 0.9.32 (#9980) Bumps [asteval](https://github.com/lmfit/asteval) from 0.9.31 to 0.9.32. - [Release notes](https://github.com/lmfit/asteval/releases) - [Commits](https://github.com/lmfit/asteval/compare/0.9.31...0.9.32) --- updated-dependencies: - dependency-name: asteval dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 3252d044ce..ecc4706f78 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # requirements.txt for DefectDojo using Python 3.x -asteval==0.9.31 +asteval==0.9.32 bleach==6.1.0 bleach[css] celery==5.3.6 From 201d1341ff252fc75d618936fc88f38d219f308a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 14:02:28 -0500 Subject: [PATCH 059/138] Bump drf-spectacular from 0.27.1 to 0.27.2 (#9981) Bumps [drf-spectacular](https://github.com/tfranzel/drf-spectacular) from 0.27.1 to 0.27.2. - [Release notes](https://github.com/tfranzel/drf-spectacular/releases) - [Changelog](https://github.com/tfranzel/drf-spectacular/blob/master/CHANGELOG.rst) - [Commits](https://github.com/tfranzel/drf-spectacular/compare/0.27.1...0.27.2) --- updated-dependencies: - dependency-name: drf-spectacular dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index ecc4706f78..70b5008232 100644 --- a/requirements.txt +++ b/requirements.txt @@ -69,7 +69,7 @@ django-fieldsignals==0.7.0 hyperlink==21.0.0 django-test-migrations==1.3.0 djangosaml2==1.9.1 -drf-spectacular==0.27.1 +drf-spectacular==0.27.2 drf-spectacular-sidecar==2024.4.1 django-ratelimit==4.1.0 argon2-cffi==23.1.0 From 7e49e67669a0663bb8cfd3f38917909daed1de72 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 16:26:25 -0500 Subject: [PATCH 060/138] Bump cryptography from 42.0.4 to 42.0.5 (#9989) Bumps [cryptography](https://github.com/pyca/cryptography) from 42.0.4 to 42.0.5. - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/42.0.4...42.0.5) --- updated-dependencies: - dependency-name: cryptography dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 70b5008232..1e79bdb10b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -36,7 +36,7 @@ mysqlclient==2.1.1 openpyxl==3.1.2 Pillow==10.3.0 # required by django-imagekit psycopg2-binary==2.9.9 -cryptography==42.0.4 +cryptography==42.0.5 python-dateutil==2.9.0.post0 pytz==2024.1 redis==5.0.3 From 5edeadeaf084bdeb736cd2dcb965ece66bc7233c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 16:27:15 -0500 Subject: [PATCH 061/138] Bump pdfmake from 0.2.7 to 0.2.10 in /components (#9994) Bumps [pdfmake](https://github.com/bpampuch/pdfmake) from 0.2.7 to 0.2.10. - [Release notes](https://github.com/bpampuch/pdfmake/releases) - [Changelog](https://github.com/bpampuch/pdfmake/blob/0.2.10/CHANGELOG.md) - [Commits](https://github.com/bpampuch/pdfmake/compare/0.2.7...0.2.10) --- updated-dependencies: - dependency-name: pdfmake dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- components/package.json | 2 +- components/yarn.lock | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/components/package.json b/components/package.json index 41e9d22009..c40e094660 100644 --- a/components/package.json +++ b/components/package.json @@ -35,7 +35,7 @@ "metismenu": "~3.0.7", "moment": "^2.29.4", "morris.js": "morrisjs/morris.js", - "pdfmake": "^0.2.7", + "pdfmake": "^0.2.10", "startbootstrap-sb-admin-2": "1.0.7" }, "engines": { diff --git a/components/yarn.lock b/components/yarn.lock index d3d65c363f..669fa12a8b 100644 --- a/components/yarn.lock +++ b/components/yarn.lock @@ -27,14 +27,14 @@ brfs "^2.0.2" unicode-trie "^2.0.0" -"@foliojs-fork/pdfkit@^0.13.0": - version "0.13.0" - resolved "https://registry.yarnpkg.com/@foliojs-fork/pdfkit/-/pdfkit-0.13.0.tgz#54f5368d8cf74d8edc81a175ccda1fd9655f2db9" - integrity sha512-YXeG1fml9k97YNC9K8e292Pj2JzGt9uOIiBFuQFxHsdQ45BlxW+JU3RQK6JAvXU7kjhjP8rCcYvpk36JLD33sQ== +"@foliojs-fork/pdfkit@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@foliojs-fork/pdfkit/-/pdfkit-0.14.0.tgz#ed1868050edd2904284655f8dcddd56b49576c98" + integrity sha512-nMOiQAv6id89MT3tVTCgc7HxD5ZMANwio2o5yvs5sexQkC0KI3BLaLakpsrHmFfeGFAhqPmZATZGbJGXTUebpg== dependencies: "@foliojs-fork/fontkit" "^1.9.1" "@foliojs-fork/linebreak" "^1.1.1" - crypto-js "^4.0.0" + crypto-js "^4.2.0" png-js "^1.0.0" "@foliojs-fork/restructure@^2.0.2": @@ -252,7 +252,7 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -crypto-js@^4.0.0: +crypto-js@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631" integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q== @@ -824,13 +824,13 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -pdfmake@^0.2.7: - version "0.2.7" - resolved "https://registry.yarnpkg.com/pdfmake/-/pdfmake-0.2.7.tgz#a7a46532ffde032674929988393c20b075cf65e3" - integrity sha512-ClLpgx30H5G3EDvRW1MrA1Xih6YxEaSgIVFrOyBMgAAt62V+hxsyWAi6JNP7u1Fc5JKYAbpb4RRVw8Rhvmz5cQ== +pdfmake@^0.2.10: + version "0.2.10" + resolved "https://registry.yarnpkg.com/pdfmake/-/pdfmake-0.2.10.tgz#a8a0ee8a5acca8f5d728e0dfe4db8be5f1b9ec6b" + integrity sha512-doipFnmE1UHSk+Z3wfQuVweVQqx2pE/Ns2G5gCqZmWwqjDj+mZHnZYH/ryXWoIfD+iVdZUAutgI/VHkTCN+Xrw== dependencies: "@foliojs-fork/linebreak" "^1.1.1" - "@foliojs-fork/pdfkit" "^0.13.0" + "@foliojs-fork/pdfkit" "^0.14.0" iconv-lite "^0.6.3" xmldoc "^1.1.2" From 5bc689b26165ecc3bf7b631fc01556ffece5998a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 16:27:58 -0500 Subject: [PATCH 062/138] Bump social-auth-core from 4.5.2 to 4.5.3 (#9992) Bumps [social-auth-core](https://github.com/python-social-auth/social-core) from 4.5.2 to 4.5.3. - [Release notes](https://github.com/python-social-auth/social-core/releases) - [Changelog](https://github.com/python-social-auth/social-core/blob/master/CHANGELOG.md) - [Commits](https://github.com/python-social-auth/social-core/compare/4.5.2...4.5.3) --- updated-dependencies: - dependency-name: social-auth-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 1e79bdb10b..79c8aff94e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -48,7 +48,7 @@ vobject==0.9.7 whitenoise==5.2.0 titlecase==2.4.1 social-auth-app-django==5.4.0 -social-auth-core==4.5.2 +social-auth-core==4.5.3 Python-jose==3.3.0 gitpython==3.1.41 debugpy==1.8.0 From 4e61c52c90b2c7c65718ca1a279dd2426c5508b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 20:11:49 -0500 Subject: [PATCH 063/138] Bump jquery from 3.7.0 to 3.7.1 in /components (#9997) Bumps [jquery](https://github.com/jquery/jquery) from 3.7.0 to 3.7.1. - [Release notes](https://github.com/jquery/jquery/releases) - [Commits](https://github.com/jquery/jquery/compare/3.7.0...3.7.1) --- updated-dependencies: - dependency-name: jquery dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- components/package.json | 2 +- components/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/components/package.json b/components/package.json index c40e094660..e4f8f640d1 100644 --- a/components/package.json +++ b/components/package.json @@ -24,7 +24,7 @@ "font-awesome": "^4.0.0", "fullcalendar": "^3.10.2", "google-code-prettify": "^1.0.0", - "jquery": "^3.7.0", + "jquery": "^3.7.1", "jquery-highlight": "3.5.0", "jquery-ui": "1.13.2", "jquery.cookie": "1.4.1", diff --git a/components/yarn.lock b/components/yarn.lock index 669fa12a8b..eccea14f17 100644 --- a/components/yarn.lock +++ b/components/yarn.lock @@ -699,10 +699,10 @@ jquery.hotkeys@jeresig/jquery.hotkeys#master: version "0.2.0" resolved "https://codeload.github.com/jeresig/jquery.hotkeys/tar.gz/f24f1da275aab7881ab501055c256add6f690de4" -"jquery@>= 1.0.0", jquery@>=1.7, jquery@>=1.7.0, "jquery@>=1.8.0 <4.0.0", jquery@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.0.tgz#fe2c01a05da500709006d8790fe21c8a39d75612" - integrity sha512-umpJ0/k8X0MvD1ds0P9SfowREz2LenHsQaxSohMZ5OMNEU2r0tf8pdeEFTHMFxWVxKNyU9rTtK3CWzUCTKJUeQ== +"jquery@>= 1.0.0", jquery@>=1.7, jquery@>=1.7.0, "jquery@>=1.8.0 <4.0.0", jquery@^3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de" + integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg== jszip@^3.10.1: version "3.10.1" From 2ae59c9e194d30bf561084a6dda9848f6dbfb814 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 20:15:05 -0500 Subject: [PATCH 064/138] Bump html2text from 2020.1.16 to 2024.2.26 (#9990) * Bump html2text from 2020.1.16 to 2024.2.26 Bumps [html2text](https://github.com/Alir3z4/html2text) from 2020.1.16 to 2024.2.26. - [Release notes](https://github.com/Alir3z4/html2text/releases) - [Changelog](https://github.com/Alir3z4/html2text/blob/master/ChangeLog.rst) - [Commits](https://github.com/Alir3z4/html2text/compare/2020.1.16...2024.2.26) --- updated-dependencies: - dependency-name: html2text dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Fixing Spotbugs unit test error with new html2text version (#10003) --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> --- requirements.txt | 2 +- unittests/tools/test_spotbugs_parser.py | 13 ++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/requirements.txt b/requirements.txt index 79c8aff94e..b7d1fc018d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -26,7 +26,7 @@ django-watson==1.6.3 django-prometheus==2.3.1 Django==4.1.13 djangorestframework==3.14.0 -html2text==2020.1.16 +html2text==2024.2.26 humanize==4.9.0 jira==3.8.0 PyGithub==1.58.2 diff --git a/unittests/tools/test_spotbugs_parser.py b/unittests/tools/test_spotbugs_parser.py index ff98db715e..153fca7666 100644 --- a/unittests/tools/test_spotbugs_parser.py +++ b/unittests/tools/test_spotbugs_parser.py @@ -4,7 +4,6 @@ class TestSpotbugsParser(DojoTestCase): - def test_no_findings(self): parser = SpotbugsParser() findings = parser.get_findings(get_unit_tests_path() + "/scans/spotbugs/no_finding.xml", Test()) @@ -76,19 +75,15 @@ def test_description(self): test_finding = findings[0] # Test if line 13 is correct self.assertEqual( - "At IdentityFunctionCommandInjection.kt:[lines 20-170]", - test_finding.description.splitlines()[12] + "At IdentityFunctionCommandInjection.kt:[lines 20-170]", test_finding.description.splitlines()[12] ) def test_mitigation(self): parser = SpotbugsParser() findings = parser.get_findings(get_unit_tests_path() + "/scans/spotbugs/many_findings.xml", Test()) test_finding = findings[0] - # Test if line 10 is correct - self.assertEqual( - "#### Example", - test_finding.mitigation.splitlines()[9] - ) + # Test if line 8 is correct + self.assertEqual("#### Example", test_finding.mitigation.splitlines()[7]) def test_references(self): parser = SpotbugsParser() @@ -97,7 +92,7 @@ def test_references(self): # Test if line 2 is correct self.assertEqual( "[OWASP: Top 10 2013-A1-Injection](https://www.owasp.org/index.php/Top_10_2013-A1-Injection)", - test_finding.references.splitlines()[1] + test_finding.references.splitlines()[1], ) def test_version_4_4(self): From 04eb64c90622db3a88c9df3967c5a4071fb663b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 20:15:45 -0500 Subject: [PATCH 065/138] Bump moment from 2.29.4 to 2.30.1 in /components (#9996) Bumps [moment](https://github.com/moment/moment) from 2.29.4 to 2.30.1. - [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md) - [Commits](https://github.com/moment/moment/compare/2.29.4...2.30.1) --- updated-dependencies: - dependency-name: moment dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- components/package.json | 2 +- components/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/components/package.json b/components/package.json index e4f8f640d1..c4a54fb35b 100644 --- a/components/package.json +++ b/components/package.json @@ -33,7 +33,7 @@ "jszip": "^3.10.1", "justgage": "^1.6.1", "metismenu": "~3.0.7", - "moment": "^2.29.4", + "moment": "^2.30.1", "morris.js": "morrisjs/morris.js", "pdfmake": "^0.2.10", "startbootstrap-sb-admin-2": "1.0.7" diff --git a/components/yarn.lock b/components/yarn.lock index eccea14f17..cf04ed850d 100644 --- a/components/yarn.lock +++ b/components/yarn.lock @@ -765,10 +765,10 @@ minimist@^1.1.3: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== -moment@^2.29.4: - version "2.29.4" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" - integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== +moment@^2.30.1: + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== morris.js@morrisjs/morris.js: version "0.5.1" From a7e5444216bf93e8a870dd3dbba8a50d0fe26d31 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 20:17:07 -0500 Subject: [PATCH 066/138] Bump markdown from 3.5.2 to 3.6 (#9991) Bumps [markdown](https://github.com/Python-Markdown/markdown) from 3.5.2 to 3.6. - [Release notes](https://github.com/Python-Markdown/markdown/releases) - [Changelog](https://github.com/Python-Markdown/markdown/blob/master/docs/changelog.md) - [Commits](https://github.com/Python-Markdown/markdown/compare/3.5.2...3.6) --- updated-dependencies: - dependency-name: markdown dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index b7d1fc018d..6113936336 100644 --- a/requirements.txt +++ b/requirements.txt @@ -31,7 +31,7 @@ humanize==4.9.0 jira==3.8.0 PyGithub==1.58.2 lxml==5.2.1 -Markdown==3.5.2 +Markdown==3.6 mysqlclient==2.1.1 openpyxl==3.1.2 Pillow==10.3.0 # required by django-imagekit From d7ba8e811c8a234e73a05bf9160649bf2235ce86 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 11:59:34 -0500 Subject: [PATCH 067/138] Bump boto3 from 1.34.35 to 1.34.89 (#10007) Bumps [boto3](https://github.com/boto/boto3) from 1.34.35 to 1.34.89. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.34.35...1.34.89) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 6113936336..fd8e274d19 100644 --- a/requirements.txt +++ b/requirements.txt @@ -75,7 +75,7 @@ django-ratelimit==4.1.0 argon2-cffi==23.1.0 blackduck==1.1.0 pycurl==7.45.2 # Required for Celery Broker AWS (SQS) support -boto3==1.34.35 # Required for Celery Broker AWS (SQS) support +boto3==1.34.89 # Required for Celery Broker AWS (SQS) support netaddr==0.10.1 vulners==2.1.5 fontawesomefree==6.5.1 From d334ea388b633d0b2acc029a1185cf3f1d589c8d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 12:00:32 -0500 Subject: [PATCH 068/138] Bump debugpy from 1.8.0 to 1.8.1 (#10005) Bumps [debugpy](https://github.com/microsoft/debugpy) from 1.8.0 to 1.8.1. - [Release notes](https://github.com/microsoft/debugpy/releases) - [Commits](https://github.com/microsoft/debugpy/compare/v1.8.0...v1.8.1) --- updated-dependencies: - dependency-name: debugpy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index fd8e274d19..db948179a1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -51,7 +51,7 @@ social-auth-app-django==5.4.0 social-auth-core==4.5.3 Python-jose==3.3.0 gitpython==3.1.41 -debugpy==1.8.0 +debugpy==1.8.1 python-gitlab==4.4.0 cpe==1.2.1 packageurl-python==0.13.4 From 959c30713f3832373245ca33fac09495a7b6d56b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 12:01:36 -0500 Subject: [PATCH 069/138] Bump sqlalchemy from 2.0.25 to 2.0.29 (#10006) Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 2.0.25 to 2.0.29. - [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases) - [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst) - [Commits](https://github.com/sqlalchemy/sqlalchemy/commits) --- updated-dependencies: - dependency-name: sqlalchemy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index db948179a1..8a902d5a4c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -41,7 +41,7 @@ python-dateutil==2.9.0.post0 pytz==2024.1 redis==5.0.3 requests==2.31.0 -sqlalchemy==2.0.25 # Required by Celery broker transport +sqlalchemy==2.0.29 # Required by Celery broker transport urllib3==1.26.18 uWSGI==2.0.23 vobject==0.9.7 From 3f080bbfaad8baedcf9aa88fb80ab6551b2e7cde Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 14:21:15 -0500 Subject: [PATCH 070/138] Bump packageurl-python from 0.13.4 to 0.15.0 (#10008) Bumps [packageurl-python](https://github.com/package-url/packageurl-python) from 0.13.4 to 0.15.0. - [Release notes](https://github.com/package-url/packageurl-python/releases) - [Changelog](https://github.com/package-url/packageurl-python/blob/main/CHANGELOG.rst) - [Commits](https://github.com/package-url/packageurl-python/compare/v0.13.4...v0.15.0) --- updated-dependencies: - dependency-name: packageurl-python dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 8a902d5a4c..5f1437bfde 100644 --- a/requirements.txt +++ b/requirements.txt @@ -54,7 +54,7 @@ gitpython==3.1.41 debugpy==1.8.1 python-gitlab==4.4.0 cpe==1.2.1 -packageurl-python==0.13.4 +packageurl-python==0.15.0 django-crum==0.7.9 JSON-log-formatter==1.0 django-split-settings==1.2.0 From 1bdb9dd951fda17d95f28056598b880f68fc7c01 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 15:10:39 -0500 Subject: [PATCH 071/138] Bump netaddr from 0.10.1 to 1.2.1 (#10004) * Bump netaddr from 0.10.1 to 1.2.1 Bumps [netaddr](https://github.com/netaddr/netaddr) from 0.10.1 to 1.2.1. - [Release notes](https://github.com/netaddr/netaddr/releases) - [Changelog](https://github.com/netaddr/netaddr/blob/master/CHANGELOG.rst) - [Commits](https://github.com/netaddr/netaddr/compare/0.10.1...1.2.1) --- updated-dependencies: - dependency-name: netaddr dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Replacing deprecated netaddr 'is_private' call (#10010) --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> --- dojo/tools/asff/parser.py | 9 +++++++-- requirements.txt | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/dojo/tools/asff/parser.py b/dojo/tools/asff/parser.py index 1f4d96f567..a936a831f3 100644 --- a/dojo/tools/asff/parser.py +++ b/dojo/tools/asff/parser.py @@ -56,7 +56,7 @@ def get_findings(self, file, test): if resource["Type"] == "AwsEc2Instance" and "Details" in resource: details = resource["Details"]["AwsEc2Instance"] for ip in details.get("IpV4Addresses", []): - # Adding only private IP addresses as endpoints: + # Adding only non-"global" IP addresses as endpoints: # # 1. **Stability**: In AWS, the private IP address of an EC2 instance remains consistent # unless the instance is terminated. In contrast, public IP addresses in AWS are separate @@ -68,7 +68,12 @@ def get_findings(self, file, test): # # By limiting our endpoints to private IP addresses, we're ensuring that the data remains # relevant even if the AWS resources undergo changes, and we also ensure a cleaner representation. - if IPAddress(ip).is_private(): + # + # netaddr deprecated the "is_private" method previously used here, so the logic has been + # flipped to exclude "global" addresses. + # + # Ref: https://netaddr.readthedocs.io/en/latest/api.html#netaddr.IPAddress.is_global + if not IPAddress(ip).is_global(): endpoints.append(Endpoint(host=ip)) finding.unsaved_endpoints = endpoints diff --git a/requirements.txt b/requirements.txt index 5f1437bfde..6a32977b20 100644 --- a/requirements.txt +++ b/requirements.txt @@ -76,6 +76,6 @@ argon2-cffi==23.1.0 blackduck==1.1.0 pycurl==7.45.2 # Required for Celery Broker AWS (SQS) support boto3==1.34.89 # Required for Celery Broker AWS (SQS) support -netaddr==0.10.1 +netaddr==1.2.1 vulners==2.1.5 fontawesomefree==6.5.1 From e55cb26993c34cdd5748d32c5b5d713a3ae3d80c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 17:47:30 -0500 Subject: [PATCH 072/138] Bump blackduck from 1.1.0 to 1.1.3 (#10013) Bumps [blackduck](https://github.com/blackducksoftware/hub-rest-api-python) from 1.1.0 to 1.1.3. - [Commits](https://github.com/blackducksoftware/hub-rest-api-python/commits) --- updated-dependencies: - dependency-name: blackduck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 6a32977b20..5f60b863b2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -73,7 +73,7 @@ drf-spectacular==0.27.2 drf-spectacular-sidecar==2024.4.1 django-ratelimit==4.1.0 argon2-cffi==23.1.0 -blackduck==1.1.0 +blackduck==1.1.3 pycurl==7.45.2 # Required for Celery Broker AWS (SQS) support boto3==1.34.89 # Required for Celery Broker AWS (SQS) support netaddr==1.2.1 From f81ef87948769ee2d0a45b6ea4f3a672b9f8a811 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 17:47:53 -0500 Subject: [PATCH 073/138] Bump gitpython from 3.1.41 to 3.1.43 (#10015) Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.41 to 3.1.43. - [Release notes](https://github.com/gitpython-developers/GitPython/releases) - [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES) - [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.41...3.1.43) --- updated-dependencies: - dependency-name: gitpython dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 5f60b863b2..9984479971 100644 --- a/requirements.txt +++ b/requirements.txt @@ -50,7 +50,7 @@ titlecase==2.4.1 social-auth-app-django==5.4.0 social-auth-core==4.5.3 Python-jose==3.3.0 -gitpython==3.1.41 +gitpython==3.1.43 debugpy==1.8.1 python-gitlab==4.4.0 cpe==1.2.1 From 5fbe73da618980bb45620bf658a2de9e91a8431c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 17:48:56 -0500 Subject: [PATCH 074/138] Bump redis from 5.0.3 to 5.0.4 (#10017) Bumps [redis](https://github.com/redis/redis-py) from 5.0.3 to 5.0.4. - [Release notes](https://github.com/redis/redis-py/releases) - [Changelog](https://github.com/redis/redis-py/blob/master/CHANGES) - [Commits](https://github.com/redis/redis-py/compare/v5.0.3...v5.0.4) --- updated-dependencies: - dependency-name: redis dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 9984479971..9abcfea174 100644 --- a/requirements.txt +++ b/requirements.txt @@ -39,7 +39,7 @@ psycopg2-binary==2.9.9 cryptography==42.0.5 python-dateutil==2.9.0.post0 pytz==2024.1 -redis==5.0.3 +redis==5.0.4 requests==2.31.0 sqlalchemy==2.0.29 # Required by Celery broker transport urllib3==1.26.18 From ae34ae87410347e0ba950920fcb9d1ece4cd7d6e Mon Sep 17 00:00:00 2001 From: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> Date: Tue, 23 Apr 2024 17:53:50 -0500 Subject: [PATCH 075/138] Set Finding date if nothing is set from the parser (#10018) --- dojo/models.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dojo/models.py b/dojo/models.py index 05a32887be..07f4255fb5 100755 --- a/dojo/models.py +++ b/dojo/models.py @@ -2993,11 +2993,12 @@ def save(self, dedupe_option=True, rules_option=True, product_grading_option=Tru if not user: from dojo.utils import get_current_user user = get_current_user() - # Title Casing from titlecase import titlecase self.title = titlecase(self.title[:511]) - + # Set the date of the finding if nothing is supplied + if self.date is None: + self.date = timezone.now() # Assign the numerical severity for correct sorting order self.numerical_severity = Finding.get_numerical_severity(self.severity) From ad61d7b3addf7714046d740f1f28d303bde96cc0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 18:04:19 -0500 Subject: [PATCH 076/138] Bump djangosaml2 from 1.9.1 to 1.9.2 (#10014) Bumps [djangosaml2](https://github.com/IdentityPython/djangosaml2) from 1.9.1 to 1.9.2. - [Release notes](https://github.com/IdentityPython/djangosaml2/releases) - [Changelog](https://github.com/IdentityPython/djangosaml2/blob/master/CHANGES) - [Commits](https://github.com/IdentityPython/djangosaml2/compare/v1.9.1...v1.9.2) --- updated-dependencies: - dependency-name: djangosaml2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 9abcfea174..6742868b9b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -68,7 +68,7 @@ cvss==3.1 django-fieldsignals==0.7.0 hyperlink==21.0.0 django-test-migrations==1.3.0 -djangosaml2==1.9.1 +djangosaml2==1.9.2 drf-spectacular==0.27.2 drf-spectacular-sidecar==2024.4.1 django-ratelimit==4.1.0 From 16b7583807ec2df7980439d8ddcae0dc35a2fb0e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 18:16:31 -0500 Subject: [PATCH 077/138] Bump pycurl from 7.45.2 to 7.45.3 (#10016) Bumps [pycurl](https://github.com/pycurl/pycurl) from 7.45.2 to 7.45.3. - [Changelog](https://github.com/pycurl/pycurl/blob/master/ChangeLog) - [Commits](https://github.com/pycurl/pycurl/commits) --- updated-dependencies: - dependency-name: pycurl dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 6742868b9b..bd126ae1ff 100644 --- a/requirements.txt +++ b/requirements.txt @@ -74,7 +74,7 @@ drf-spectacular-sidecar==2024.4.1 django-ratelimit==4.1.0 argon2-cffi==23.1.0 blackduck==1.1.3 -pycurl==7.45.2 # Required for Celery Broker AWS (SQS) support +pycurl==7.45.3 # Required for Celery Broker AWS (SQS) support boto3==1.34.89 # Required for Celery Broker AWS (SQS) support netaddr==1.2.1 vulners==2.1.5 From 054e0eb0f934fdf702d52d35d18ecf0f07435466 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 20:48:35 -0500 Subject: [PATCH 078/138] Bump celery from 5.3.6 to 5.4.0 (#10019) Bumps [celery](https://github.com/celery/celery) from 5.3.6 to 5.4.0. - [Release notes](https://github.com/celery/celery/releases) - [Changelog](https://github.com/celery/celery/blob/main/Changelog.rst) - [Commits](https://github.com/celery/celery/compare/v5.3.6...v5.4.0) --- updated-dependencies: - dependency-name: celery dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index bd126ae1ff..9e0810a790 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ asteval==0.9.32 bleach==6.1.0 bleach[css] -celery==5.3.6 +celery==5.4.0 coverage==7.4.4 defusedxml==0.7.1 django_celery_results==2.5.1 From ae77019d180ffad5a77d726f053b135dcd9ce5b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Apr 2024 11:59:52 -0500 Subject: [PATCH 079/138] Bump coverage from 7.4.4 to 7.5.0 (#10020) Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.4.4 to 7.5.0. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.4.4...7.5.0) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 9e0810a790..957a306625 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ asteval==0.9.32 bleach==6.1.0 bleach[css] celery==5.4.0 -coverage==7.4.4 +coverage==7.5.0 defusedxml==0.7.1 django_celery_results==2.5.1 django-auditlog==2.3.0 From 527145ed066e5f14028ef12b2252f4ad3538f218 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Apr 2024 12:00:43 -0500 Subject: [PATCH 080/138] Bump uwsgi from 2.0.23 to 2.0.25.1 (#10023) Bumps [uwsgi](https://uwsgi-docs.readthedocs.io/en/latest/) from 2.0.23 to 2.0.25.1. --- updated-dependencies: - dependency-name: uwsgi dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 957a306625..ddad0b5f4c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -43,7 +43,7 @@ redis==5.0.4 requests==2.31.0 sqlalchemy==2.0.29 # Required by Celery broker transport urllib3==1.26.18 -uWSGI==2.0.23 +uWSGI==2.0.25.1 vobject==0.9.7 whitenoise==5.2.0 titlecase==2.4.1 From d6ba4fb798161bfca58d73446008930338889d40 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Apr 2024 12:14:55 -0500 Subject: [PATCH 081/138] Bump django-split-settings from 1.2.0 to 1.3.1 (#10022) Bumps [django-split-settings](https://github.com/sponsors/wemake-services) from 1.2.0 to 1.3.1. - [Commits](https://github.com/sponsors/wemake-services/commits) --- updated-dependencies: - dependency-name: django-split-settings dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index ddad0b5f4c..033a882698 100644 --- a/requirements.txt +++ b/requirements.txt @@ -57,7 +57,7 @@ cpe==1.2.1 packageurl-python==0.15.0 django-crum==0.7.9 JSON-log-formatter==1.0 -django-split-settings==1.2.0 +django-split-settings==1.3.1 django-debug-toolbar==4.3.0 django-debug-toolbar-request-history==0.1.4 vcrpy==6.0.1 From 94a5b7394e299eb0d2035e0968fed19a65c45f2d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Apr 2024 15:27:32 -0500 Subject: [PATCH 082/138] Bump boto3 from 1.34.89 to 1.34.90 (#10024) Bumps [boto3](https://github.com/boto/boto3) from 1.34.89 to 1.34.90. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.34.89...1.34.90) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 033a882698..72ca999171 100644 --- a/requirements.txt +++ b/requirements.txt @@ -75,7 +75,7 @@ django-ratelimit==4.1.0 argon2-cffi==23.1.0 blackduck==1.1.3 pycurl==7.45.3 # Required for Celery Broker AWS (SQS) support -boto3==1.34.89 # Required for Celery Broker AWS (SQS) support +boto3==1.34.90 # Required for Celery Broker AWS (SQS) support netaddr==1.2.1 vulners==2.1.5 fontawesomefree==6.5.1 From 30e2ddb7c97a5bd4a90ef5197a05acf87f856339 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 16:48:02 -0500 Subject: [PATCH 083/138] Bump boto3 from 1.34.90 to 1.34.92 (#10036) Bumps [boto3](https://github.com/boto/boto3) from 1.34.90 to 1.34.92. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.34.90...1.34.92) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 72ca999171..42489368f0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -75,7 +75,7 @@ django-ratelimit==4.1.0 argon2-cffi==23.1.0 blackduck==1.1.3 pycurl==7.45.3 # Required for Celery Broker AWS (SQS) support -boto3==1.34.90 # Required for Celery Broker AWS (SQS) support +boto3==1.34.92 # Required for Celery Broker AWS (SQS) support netaddr==1.2.1 vulners==2.1.5 fontawesomefree==6.5.1 From e9b28b85f2508660dc1f215a4bd256ef3617a8c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 17:29:09 -0500 Subject: [PATCH 084/138] Bump social-auth-app-django from 5.4.0 to 5.4.1 (#10029) Dependabot couldn't find the original pull request head commit, 34219f3e44275611493b6d52bdd710faeb2673f6. Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 42489368f0..6deae665ff 100644 --- a/requirements.txt +++ b/requirements.txt @@ -47,7 +47,7 @@ uWSGI==2.0.25.1 vobject==0.9.7 whitenoise==5.2.0 titlecase==2.4.1 -social-auth-app-django==5.4.0 +social-auth-app-django==5.4.1 social-auth-core==4.5.3 Python-jose==3.3.0 gitpython==3.1.43 From fbe9047b5ae3e7a1b47027df6c078395285ce93e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 17:56:36 -0500 Subject: [PATCH 085/138] Bump social-auth-core from 4.5.3 to 4.5.4 (#10030) Dependabot couldn't find the original pull request head commit, 09cba57af6d020030b7eb5b8b2b3e9f9d7f90afa. Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 6deae665ff..163c42b5a2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -48,7 +48,7 @@ vobject==0.9.7 whitenoise==5.2.0 titlecase==2.4.1 social-auth-app-django==5.4.1 -social-auth-core==4.5.3 +social-auth-core==4.5.4 Python-jose==3.3.0 gitpython==3.1.43 debugpy==1.8.1 From 67d1c30d8882e8feed721e2138bf30a82508a2d2 Mon Sep 17 00:00:00 2001 From: DefectDojo release bot Date: Fri, 26 Apr 2024 04:05:46 +0000 Subject: [PATCH 086/138] Update versions in application files --- components/package.json | 2 +- dojo/__init__.py | 2 +- helm/defectdojo/Chart.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/package.json b/components/package.json index 4ccd070939..41e9d22009 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "defectdojo", - "version": "2.33.6", + "version": "2.34.0-dev", "license" : "BSD-3-Clause", "private": true, "dependencies": { diff --git a/dojo/__init__.py b/dojo/__init__.py index 3a41507bec..4758913441 100644 --- a/dojo/__init__.py +++ b/dojo/__init__.py @@ -4,6 +4,6 @@ # Django starts so that shared_task will use this app. from .celery import app as celery_app # noqa: F401 -__version__ = '2.33.6' +__version__ = '2.34.0-dev' __url__ = 'https://github.com/DefectDojo/django-DefectDojo' __docs__ = 'https://documentation.defectdojo.com' diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index a7521386fc..ed6f8396e6 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 -appVersion: "2.33.6" +appVersion: "2.34.0-dev" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.124 +version: 1.6.125-dev icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap From 7f548e4c45a582cb81bae008b7ff87e406c33635 Mon Sep 17 00:00:00 2001 From: DefectDojo Date: Fri, 26 Apr 2024 04:12:58 +0000 Subject: [PATCH 087/138] Update helm lock file Signed-off-by: DefectDojo --- helm/defectdojo/Chart.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/helm/defectdojo/Chart.lock b/helm/defectdojo/Chart.lock index 0cd1eabf96..f02ae0074d 100644 --- a/helm/defectdojo/Chart.lock +++ b/helm/defectdojo/Chart.lock @@ -13,6 +13,6 @@ dependencies: version: 11.16.2 - name: redis repository: https://charts.bitnami.com/bitnami - version: 19.1.2 -digest: sha256:175b6a0625ae97af141faf363d504b0bccbcbd06bb5c01d014e7e3c82b78a0c8 -generated: "2024-04-22T15:02:23.837536991Z" + version: 19.1.3 +digest: sha256:2592451989dc8d0db275de473ec1fe041fbe2cba82ca19c76247b82954633e90 +generated: "2024-04-26T04:12:49.983759527Z" From 3249d8a8ffd13e170a7b1b91241f86b12ec59777 Mon Sep 17 00:00:00 2001 From: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> Date: Thu, 25 Apr 2024 23:16:00 -0500 Subject: [PATCH 088/138] Update parser.py --- dojo/tools/semgrep/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/tools/semgrep/parser.py b/dojo/tools/semgrep/parser.py index ff54dab352..509e221a10 100644 --- a/dojo/tools/semgrep/parser.py +++ b/dojo/tools/semgrep/parser.py @@ -4,7 +4,7 @@ # Parser for semgrep -class SemgrepParser(object): +class SemgrepParser: def get_scan_types(self): return ["Semgrep JSON Report"] From 2db4e3a16cccb4b701e538e1fffcf027b3a90c12 Mon Sep 17 00:00:00 2001 From: davidhernandeze Date: Fri, 26 Apr 2024 23:26:37 -0500 Subject: [PATCH 089/138] add findings_count ordering to filters (#10045) include dojo_sort snippet in findings_count table header add findings_count annotation to include column in query --- dojo/filters.py | 2 ++ dojo/product/views.py | 4 ++++ dojo/templates/dojo/product.html | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/dojo/filters.py b/dojo/filters.py index f355625d80..619fc8b1b6 100644 --- a/dojo/filters.py +++ b/dojo/filters.py @@ -1182,6 +1182,7 @@ class ProductFilter(DojoFilter): ('origin', 'origin'), ('external_audience', 'external_audience'), ('internet_accessible', 'internet_accessible'), + ('findings_count', 'findings_count') ), field_labels={ 'name': 'Product Name', @@ -1193,6 +1194,7 @@ class ProductFilter(DojoFilter): 'origin': 'Origin ', 'external_audience': 'External Audience ', 'internet_accessible': 'Internet Accessible ', + 'findings_count': 'Findings Count ', } ) diff --git a/dojo/product/views.py b/dojo/product/views.py index 09f0e007b0..c100a9531b 100755 --- a/dojo/product/views.py +++ b/dojo/product/views.py @@ -68,6 +68,10 @@ def product(request): # see https://code.djangoproject.com/ticket/23771 and https://code.djangoproject.com/ticket/25375 name_words = prods.values_list('name', flat=True) + prods = prods.annotate( + findings_count=Count('engagement__test__finding', filter=Q(engagement__test__finding__active=True)) + ) + prod_filter = ProductFilter(request.GET, queryset=prods, user=request.user) prod_list = get_page_items(request, prod_filter.qs, 25) diff --git a/dojo/templates/dojo/product.html b/dojo/templates/dojo/product.html index d022812de8..6dd7859204 100644 --- a/dojo/templates/dojo/product.html +++ b/dojo/templates/dojo/product.html @@ -62,7 +62,7 @@

{% if system_settings.enable_github %} GitHub {% endif %} - Active (Verified) Findings + {% dojo_sort request 'Active (Verified) Findings' 'findings_count' %} Vulnerable Hosts / Endpoints Contact {% comment %} The display field is translated in the function. No need to translate here as well{% endcomment %} From 7b2fc37ebccaccbec2f412d754b29307f273b436 Mon Sep 17 00:00:00 2001 From: davidhernandeze Date: Fri, 26 Apr 2024 23:30:52 -0500 Subject: [PATCH 090/138] add target start and target end filters for engagements (#9914) --- dojo/filters.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dojo/filters.py b/dojo/filters.py index 619fc8b1b6..71731be624 100644 --- a/dojo/filters.py +++ b/dojo/filters.py @@ -847,6 +847,8 @@ class EngagementDirectFilter(DojoFilter): lead = ModelChoiceFilter(queryset=Dojo_User.objects.none(), label="Lead") version = CharFilter(field_name='version', lookup_expr='icontains', label='Engagement version') test__version = CharFilter(field_name='test__version', lookup_expr='icontains', label='Test version') + target_start = DateRangeFilter() + target_end = DateRangeFilter() product__name = CharFilter(lookup_expr='icontains', label='Product name contains') product__prod_type = ModelMultipleChoiceFilter( From 6d7c476e57410d6387702cc170f0907660349da2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 11:58:28 -0500 Subject: [PATCH 091/138] Bump nginx from 1.25.5-alpine to 1.26.0-alpine (#10057) Bumps nginx from 1.25.5-alpine to 1.26.0-alpine. --- updated-dependencies: - dependency-name: nginx dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Dockerfile.nginx-alpine | 2 +- Dockerfile.nginx-debian | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile.nginx-alpine b/Dockerfile.nginx-alpine index c2ba916d1e..338d9d6be1 100644 --- a/Dockerfile.nginx-alpine +++ b/Dockerfile.nginx-alpine @@ -140,7 +140,7 @@ COPY manage.py ./ COPY dojo/ ./dojo/ RUN env DD_SECRET_KEY='.' python3 manage.py collectstatic --noinput && true -FROM nginx:1.25.5-alpine@sha256:7bd88800d8c18d4f73feeee25e04fcdbeecfc5e0a2b7254a90f4816bb67beadd +FROM nginx:1.26.0-alpine@sha256:ca16009a8c25f52193506d4c90c98efbad4b6cbe73372e2a27972f05c5e02f15 ARG uid=1001 ARG appuser=defectdojo COPY --from=collectstatic /app/static/ /usr/share/nginx/html/static/ diff --git a/Dockerfile.nginx-debian b/Dockerfile.nginx-debian index 07379aa170..f2e518ddcd 100644 --- a/Dockerfile.nginx-debian +++ b/Dockerfile.nginx-debian @@ -75,7 +75,7 @@ COPY dojo/ ./dojo/ RUN env DD_SECRET_KEY='.' python3 manage.py collectstatic --noinput && true -FROM nginx:1.25.5-alpine@sha256:7bd88800d8c18d4f73feeee25e04fcdbeecfc5e0a2b7254a90f4816bb67beadd +FROM nginx:1.26.0-alpine@sha256:ca16009a8c25f52193506d4c90c98efbad4b6cbe73372e2a27972f05c5e02f15 ARG uid=1001 ARG appuser=defectdojo COPY --from=collectstatic /app/static/ /usr/share/nginx/html/static/ From fd11ce8419aaf8f471e54da20f7223ff8ed157b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 11:59:24 -0500 Subject: [PATCH 092/138] Bump jquery-ui from 1.13.2 to 1.13.3 in /components (#10056) Bumps [jquery-ui](https://github.com/jquery/jquery-ui) from 1.13.2 to 1.13.3. - [Release notes](https://github.com/jquery/jquery-ui/releases) - [Commits](https://github.com/jquery/jquery-ui/compare/1.13.2...1.13.3) --- updated-dependencies: - dependency-name: jquery-ui dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- components/package.json | 2 +- components/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/components/package.json b/components/package.json index c4a54fb35b..631abc21df 100644 --- a/components/package.json +++ b/components/package.json @@ -26,7 +26,7 @@ "google-code-prettify": "^1.0.0", "jquery": "^3.7.1", "jquery-highlight": "3.5.0", - "jquery-ui": "1.13.2", + "jquery-ui": "1.13.3", "jquery.cookie": "1.4.1", "jquery.flot.tooltip": "^0.9.0", "jquery.hotkeys": "jeresig/jquery.hotkeys#master", diff --git a/components/yarn.lock b/components/yarn.lock index cf04ed850d..e346338a1b 100644 --- a/components/yarn.lock +++ b/components/yarn.lock @@ -678,10 +678,10 @@ jquery-highlight@3.5.0: dependencies: jquery ">= 1.0.0" -jquery-ui@1.13.2: - version "1.13.2" - resolved "https://registry.yarnpkg.com/jquery-ui/-/jquery-ui-1.13.2.tgz#de03580ae6604773602f8d786ad1abfb75232034" - integrity sha512-wBZPnqWs5GaYJmo1Jj0k/mrSkzdQzKDwhXNtHKcBdAcKVxMM3KNYFq+iJ2i1rwiG53Z8M4mTn3Qxrm17uH1D4Q== +jquery-ui@1.13.3: + version "1.13.3" + resolved "https://registry.yarnpkg.com/jquery-ui/-/jquery-ui-1.13.3.tgz#d9f5292b2857fa1f2fdbbe8f2e66081664eb9bc5" + integrity sha512-D2YJfswSJRh/B8M/zCowDpNFfwsDmtfnMPwjJTyvl+CBqzpYwQ+gFYIbUUlzijy/Qvoy30H1YhoSui4MNYpRwA== dependencies: jquery ">=1.8.0 <4.0.0" From c948edd978704e8f1e66a6c1708a746c08da00bf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 11:59:58 -0500 Subject: [PATCH 093/138] Bump boto3 from 1.34.92 to 1.34.93 (#10054) Bumps [boto3](https://github.com/boto/boto3) from 1.34.92 to 1.34.93. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.34.92...1.34.93) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 163c42b5a2..f4f03b816f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -75,7 +75,7 @@ django-ratelimit==4.1.0 argon2-cffi==23.1.0 blackduck==1.1.3 pycurl==7.45.3 # Required for Celery Broker AWS (SQS) support -boto3==1.34.92 # Required for Celery Broker AWS (SQS) support +boto3==1.34.93 # Required for Celery Broker AWS (SQS) support netaddr==1.2.1 vulners==2.1.5 fontawesomefree==6.5.1 From c1f1b8a01e2c899c4b077a50c6da5a60840e0cea Mon Sep 17 00:00:00 2001 From: DefectDojo release bot Date: Mon, 29 Apr 2024 17:58:40 +0000 Subject: [PATCH 094/138] Update versions in application files --- components/package.json | 2 +- dojo/__init__.py | 2 +- helm/defectdojo/Chart.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/package.json b/components/package.json index 8b076e0bbb..41e9d22009 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "defectdojo", - "version": "2.33.7", + "version": "2.34.0-dev", "license" : "BSD-3-Clause", "private": true, "dependencies": { diff --git a/dojo/__init__.py b/dojo/__init__.py index 24987ce2ac..4758913441 100644 --- a/dojo/__init__.py +++ b/dojo/__init__.py @@ -4,6 +4,6 @@ # Django starts so that shared_task will use this app. from .celery import app as celery_app # noqa: F401 -__version__ = '2.33.7' +__version__ = '2.34.0-dev' __url__ = 'https://github.com/DefectDojo/django-DefectDojo' __docs__ = 'https://documentation.defectdojo.com' diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index c405d96054..a1845c51b1 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 -appVersion: "2.33.7" +appVersion: "2.34.0-dev" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.125 +version: 1.6.126-dev icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap From 31fae89cd8a609e5a8922fc2f6b674c29a070852 Mon Sep 17 00:00:00 2001 From: DefectDojo release bot Date: Mon, 29 Apr 2024 17:58:41 +0000 Subject: [PATCH 095/138] Update versions in application files --- components/package.json | 2 +- dojo/__init__.py | 2 +- helm/defectdojo/Chart.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/package.json b/components/package.json index 8b076e0bbb..41e9d22009 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "defectdojo", - "version": "2.33.7", + "version": "2.34.0-dev", "license" : "BSD-3-Clause", "private": true, "dependencies": { diff --git a/dojo/__init__.py b/dojo/__init__.py index 24987ce2ac..4758913441 100644 --- a/dojo/__init__.py +++ b/dojo/__init__.py @@ -4,6 +4,6 @@ # Django starts so that shared_task will use this app. from .celery import app as celery_app # noqa: F401 -__version__ = '2.33.7' +__version__ = '2.34.0-dev' __url__ = 'https://github.com/DefectDojo/django-DefectDojo' __docs__ = 'https://documentation.defectdojo.com' diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index c405d96054..a1845c51b1 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 -appVersion: "2.33.7" +appVersion: "2.34.0-dev" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.125 +version: 1.6.126-dev icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap From 57853ad419f2eff9e0b1bba7e7d1cfa2c97fb705 Mon Sep 17 00:00:00 2001 From: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> Date: Mon, 29 Apr 2024 13:28:57 -0500 Subject: [PATCH 096/138] Fix ruff errors --- dojo/filters.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dojo/filters.py b/dojo/filters.py index b4ce74cce4..92bf923754 100644 --- a/dojo/filters.py +++ b/dojo/filters.py @@ -2526,11 +2526,11 @@ def __init__(self, *args, **kwargs): self.user = None if 'user' in kwargs: self.user = kwargs.pop('user') - super(EndpointFilterWithoutObjectLookups, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) @property def qs(self): - parent = super(EndpointFilterWithoutObjectLookups, self).qs + parent = super().qs return get_authorized_endpoints(Permissions.Endpoint_View, parent) class Meta: @@ -2689,7 +2689,7 @@ class Meta: def __init__(self, *args, **kwargs): self.engagement = kwargs.pop('engagement') - super(EngagementTestFilterWithoutObjectLookups, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.form.fields['test_type'].queryset = Test_Type.objects.filter(test__engagement=self.engagement).distinct().order_by('name') From 85f7804342bf3225010a20766e3cbaa416a58a2d Mon Sep 17 00:00:00 2001 From: MarianG Date: Tue, 30 Apr 2024 14:24:58 +0200 Subject: [PATCH 097/138] fix: Qualys Parser used a Date Field for the mitigation_date, however the Finding-Model requires a DateTime Field which is not compatible and imports are getting canceled (#9888) --- dojo/tools/qualys/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/tools/qualys/parser.py b/dojo/tools/qualys/parser.py index b8498962f1..68bc6ecfb7 100644 --- a/dojo/tools/qualys/parser.py +++ b/dojo/tools/qualys/parser.py @@ -173,7 +173,7 @@ def parse_finding(host, tree): if last_fixed is not None: _temp["mitigation_date"] = datetime.datetime.strptime( last_fixed, "%Y-%m-%dT%H:%M:%SZ" - ).date() + ) else: _temp["mitigation_date"] = None # read cvss value if present From 7d26341697f029951fd542782d0377a13b9c6eeb Mon Sep 17 00:00:00 2001 From: Harold Blankenship <36673698+hblankenship@users.noreply.github.com> Date: Tue, 30 Apr 2024 09:11:13 -0500 Subject: [PATCH 098/138] Unit Tests: Correct File Close Warnings (#10055) * files in unnittest * missed file open * fix linter issues from editing merges * indentation fix * remove whitespaces * fix flake issues --- unittests/dojo_test_case.py | 158 ++-- unittests/test_apiv2_scan_import_options.py | 30 +- unittests/test_endpoint_meta_import.py | 17 +- unittests/test_import_reimport.py | 79 +- unittests/test_importers_closeold.py | 36 +- unittests/test_importers_importer.py | 218 ++--- unittests/test_parsers.py | 52 +- unittests/test_rest_framework.py | 806 +++++++++-------- unittests/tools/test_acunetix_parser.py | 580 ++++++------ unittests/tools/test_anchore_engine_parser.py | 49 +- unittests/tools/test_anchore_grype_parser.py | 372 ++++---- .../tools/test_anchorectl_policies_parser.py | 34 +- .../tools/test_anchorectl_vulns_parser.py | 34 +- unittests/tools/test_api_blackduck_parser.py | 63 +- unittests/tools/test_api_cobalt_parser.py | 483 +++++----- unittests/tools/test_api_vulners_parser.py | 70 +- unittests/tools/test_aqua_parser.py | 48 +- unittests/tools/test_auditjs_parser.py | 113 ++- ..._security_center_recommendations_parser.py | 112 +-- unittests/tools/test_bandit_parser.py | 170 ++-- unittests/tools/test_brakeman_parser.py | 26 +- unittests/tools/test_bugcrowd_parser.py | 44 +- unittests/tools/test_cargo_audit_parser.py | 128 +-- unittests/tools/test_checkmarx_osa_parser.py | 7 +- unittests/tools/test_checkov_parser.py | 138 +-- unittests/tools/test_chefinspect_parser.py | 24 +- unittests/tools/test_cobalt_parser.py | 24 +- unittests/tools/test_codechecker_parser.py | 146 +-- unittests/tools/test_contrast_parser.py | 110 +-- unittests/tools/test_coverity_api_parser.py | 154 ++-- unittests/tools/test_cred_scan_parser.py | 34 +- unittests/tools/test_crunch42_parser.py | 42 +- .../tools/test_dependency_check_parser.py | 488 +++++----- .../tools/test_dependency_track_parser.py | 122 ++- unittests/tools/test_detect_secrets_parser.py | 112 +-- unittests/tools/test_dockerbench_parser.py | 94 +- unittests/tools/test_dockle_parser.py | 70 +- unittests/tools/test_dsop_parser.py | 24 +- unittests/tools/test_fortify_parser.py | 144 +-- unittests/tools/test_generic_parser.py | 410 ++++----- unittests/tools/test_ggshield_parser.py | 57 +- .../tools/test_github_vulnerability_parser.py | 456 +++++----- unittests/tools/test_gitlab_dast_parser.py | 236 ++--- .../tools/test_gitlab_dep_scan_parser.py | 102 +-- unittests/tools/test_gitleaks_parser.py | 182 ++-- unittests/tools/test_gosec_parser.py | 16 +- unittests/tools/test_govulncheck_parser.py | 217 +++-- unittests/tools/test_h1_parser.py | 24 +- .../tools/test_harbor_vulnerability_parser.py | 84 +- unittests/tools/test_humble_parser.py | 52 +- unittests/tools/test_huskyci_parser.py | 41 +- unittests/tools/test_hydra_parser.py | 185 ++-- unittests/tools/test_immuniweb_parser.py | 36 +- unittests/tools/test_intsights_parser.py | 97 +- unittests/tools/test_kics_parser.py | 360 ++++---- unittests/tools/test_kiuwan_parser.py | 40 +- unittests/tools/test_kubebench_parser.py | 80 +- unittests/tools/test_kubehunter_parser.py | 61 +- unittests/tools/test_kubescape_parser.py | 33 +- unittests/tools/test_mend_parser.py | 44 +- unittests/tools/test_meterian_parser.py | 124 ++- .../test_microfocus_webinspect_parser.py | 172 ++-- unittests/tools/test_mobsfscan_parser.py | 287 +++--- .../tools/test_mozilla_observatory_parser.py | 422 ++++----- unittests/tools/test_nancy_parser.py | 53 +- unittests/tools/test_netsparker_parser.py | 140 +-- unittests/tools/test_nexpose_parser.py | 393 ++++---- unittests/tools/test_nikto_parser.py | 290 +++--- unittests/tools/test_nmap_parser.py | 220 ++--- unittests/tools/test_noseyparker_parser.py | 59 +- unittests/tools/test_npm_audit_parser.py | 115 ++- unittests/tools/test_nuclei_parser.py | 432 +++++---- unittests/tools/test_pmd_parser.py | 28 +- unittests/tools/test_pwn_sast_parser.py | 52 +- .../test_qualys_infrascan_webgui_parser.py | 104 +-- unittests/tools/test_qualys_parser.py | 238 ++--- .../tools/test_redhatsatellite_parser.py | 30 +- unittests/tools/test_retirejs_parser.py | 70 +- unittests/tools/test_risk_recon_parser.py | 40 +- unittests/tools/test_rusty_hog_parser.py | 170 ++-- unittests/tools/test_sarif_parser.py | 842 +++++++++--------- unittests/tools/test_scantist_parser.py | 52 +- unittests/tools/test_scout_suite_parser.py | 146 +-- unittests/tools/test_semgrep_parser.py | 227 +++-- unittests/tools/test_skf_parser.py | 16 +- unittests/tools/test_sonarqube_parser.py | 20 + unittests/tools/test_ssh_audit_parser.py | 64 +- unittests/tools/test_sslscan_parser.py | 36 +- unittests/tools/test_sslyze_parser.py | 246 ++--- unittests/tools/test_stackhawk_parser.py | 379 ++++---- unittests/tools/test_sysdig_reports_parser.py | 82 +- unittests/tools/test_talisman_parser.py | 61 +- unittests/tools/test_tenable_parser.py | 488 +++++----- unittests/tools/test_terrascan_parser.py | 196 ++-- unittests/tools/test_testssl_parser.py | 174 ++-- unittests/tools/test_tfsec_parser.py | 176 ++-- unittests/tools/test_trivy_operator_parser.py | 250 +++--- unittests/tools/test_trivy_parser.py | 306 +++---- unittests/tools/test_trufflehog3_parser.py | 146 +-- unittests/tools/test_trufflehog_parser.py | 48 +- .../tools/test_trustwave_fusion_api_parser.py | 114 +-- unittests/tools/test_trustwave_parser.py | 80 +- unittests/tools/test_veracode_parser.py | 651 +++++++------- unittests/tools/test_veracode_sca_parser.py | 146 +-- unittests/tools/test_wapiti_parser.py | 98 +- unittests/tools/test_wazuh_parser.py | 78 +- unittests/tools/test_wfuzz_parser.py | 80 +- .../tools/test_whitehat_sentinel_parser.py | 28 +- unittests/tools/test_wiz_parser.py | 66 +- unittests/tools/test_wpscan_parser.py | 250 +++--- unittests/tools/test_xanitizer_parser.py | 40 +- unittests/tools/test_yarn_audit_parser.py | 105 +-- unittests/tools/test_zap_parser.py | 380 ++++---- 113 files changed, 8836 insertions(+), 8942 deletions(-) diff --git a/unittests/dojo_test_case.py b/unittests/dojo_test_case.py index 97683a4968..62f2d9a7a6 100644 --- a/unittests/dojo_test_case.py +++ b/unittests/dojo_test_case.py @@ -470,119 +470,123 @@ def import_scan_with_params(self, filename, scan_type='ZAP Scan', engagement=1, push_to_jira=None, endpoint_to_add=None, tags=None, close_old_findings=False, group_by=None, engagement_name=None, product_name=None, product_type_name=None, auto_create_context=None, expected_http_status_code=201, test_title=None, scan_date=None, service=None, forceActive=True, forceVerified=True): - payload = { - "minimum_severity": minimum_severity, - "active": active, - "verified": verified, - "scan_type": scan_type, - "file": open(get_unit_tests_path() + '/' + filename), - "version": "1.0.1", - "close_old_findings": close_old_findings, - } - if engagement: - payload['engagement'] = engagement + with open(get_unit_tests_path() + '/' + filename) as testfile: + payload = { + "minimum_severity": minimum_severity, + "active": active, + "verified": verified, + "scan_type": scan_type, + "file": testfile, + "version": "1.0.1", + "close_old_findings": close_old_findings, + } - if engagement_name: - payload['engagement_name'] = engagement_name + if engagement: + payload['engagement'] = engagement - if product_name: - payload['product_name'] = product_name + if engagement_name: + payload['engagement_name'] = engagement_name - if product_type_name: - payload['product_type_name'] = product_type_name + if product_name: + payload['product_name'] = product_name - if auto_create_context: - payload['auto_create_context'] = auto_create_context + if product_type_name: + payload['product_type_name'] = product_type_name - if push_to_jira is not None: - payload['push_to_jira'] = push_to_jira + if auto_create_context: + payload['auto_create_context'] = auto_create_context + + if push_to_jira is not None: + payload['push_to_jira'] = push_to_jira - if endpoint_to_add is not None: - payload['endpoint_to_add'] = endpoint_to_add + if endpoint_to_add is not None: + payload['endpoint_to_add'] = endpoint_to_add - if tags is not None: - payload['tags'] = tags + if tags is not None: + payload['tags'] = tags - if group_by is not None: - payload['group_by'] = group_by + if group_by is not None: + payload['group_by'] = group_by - if test_title is not None: - payload['test_title'] = test_title + if test_title is not None: + payload['test_title'] = test_title - if scan_date is not None: - payload['scan_date'] = scan_date + if scan_date is not None: + payload['scan_date'] = scan_date - if service is not None: - payload['service'] = service + if service is not None: + payload['service'] = service - return self.import_scan(payload, expected_http_status_code) + return self.import_scan(payload, expected_http_status_code) def reimport_scan_with_params(self, test_id, filename, scan_type='ZAP Scan', engagement=1, minimum_severity='Low', active=True, verified=False, push_to_jira=None, tags=None, close_old_findings=True, group_by=None, engagement_name=None, scan_date=None, product_name=None, product_type_name=None, auto_create_context=None, expected_http_status_code=201, test_title=None): - payload = { - "minimum_severity": minimum_severity, - "active": active, - "verified": verified, - "scan_type": scan_type, - "file": open(get_unit_tests_path() + '/' + filename), - "version": "1.0.1", - "close_old_findings": close_old_findings, - } + with open(get_unit_tests_path() + '/' + filename) as testfile: + payload = { + "minimum_severity": minimum_severity, + "active": active, + "verified": verified, + "scan_type": scan_type, + "file": testfile, + "version": "1.0.1", + "close_old_findings": close_old_findings, + } - if test_id is not None: - payload['test'] = test_id + if test_id is not None: + payload['test'] = test_id - if engagement: - payload['engagement'] = engagement + if engagement: + payload['engagement'] = engagement - if engagement_name: - payload['engagement_name'] = engagement_name + if engagement_name: + payload['engagement_name'] = engagement_name - if product_name: - payload['product_name'] = product_name + if product_name: + payload['product_name'] = product_name - if product_type_name: - payload['product_type_name'] = product_type_name + if product_type_name: + payload['product_type_name'] = product_type_name - if auto_create_context: - payload['auto_create_context'] = auto_create_context + if auto_create_context: + payload['auto_create_context'] = auto_create_context - if push_to_jira is not None: - payload['push_to_jira'] = push_to_jira + if push_to_jira is not None: + payload['push_to_jira'] = push_to_jira - if tags is not None: - payload['tags'] = tags + if tags is not None: + payload['tags'] = tags - if group_by is not None: - payload['group_by'] = group_by + if group_by is not None: + payload['group_by'] = group_by - if test_title is not None: - payload['test_title'] = test_title + if test_title is not None: + payload['test_title'] = test_title - if scan_date is not None: - payload['scan_date'] = scan_date + if scan_date is not None: + payload['scan_date'] = scan_date - return self.reimport_scan(payload, expected_http_status_code=expected_http_status_code) + return self.reimport_scan(payload, expected_http_status_code=expected_http_status_code) def endpoint_meta_import_scan_with_params(self, filename, product=1, product_name=None, create_endpoints=True, create_tags=True, create_dojo_meta=True, expected_http_status_code=201): - payload = { - "create_endpoints": create_endpoints, - "create_tags": create_tags, - "create_dojo_meta": create_dojo_meta, - "file": open(get_unit_tests_path() + '/' + filename), - } + with open(get_unit_tests_path() + '/' + filename) as testfile: + payload = { + "create_endpoints": create_endpoints, + "create_tags": create_tags, + "create_dojo_meta": create_dojo_meta, + "file": testfile, + } - if product: - payload['product'] = product + if product: + payload['product'] = product - if product_name: - payload['product_name'] = product_name + if product_name: + payload['product_name'] = product_name - return self.endpoint_meta_import_scan(payload, expected_http_status_code) + return self.endpoint_meta_import_scan(payload, expected_http_status_code) def get_finding_api(self, finding_id): response = self.client.get(reverse('finding-list') + '%s/' % finding_id, format='json') diff --git a/unittests/test_apiv2_scan_import_options.py b/unittests/test_apiv2_scan_import_options.py index 6e62f460d9..5a16a7887e 100644 --- a/unittests/test_apiv2_scan_import_options.py +++ b/unittests/test_apiv2_scan_import_options.py @@ -16,6 +16,9 @@ class ScanImportOptionsTest(APITestCase): """ + def __del__(self): + self.payload['file'].close() + def setUp(self): token = Token.objects.get(user__username='admin') self.client = APIClient() @@ -26,19 +29,20 @@ def setUp(self): test.save() def import_zap_scan(self, upload_empty_scan=False): - if upload_empty_scan: - file = SimpleUploadedFile('zap_sample.xml', self.EMPTY_ZAP_SCAN.encode('utf-8')) - else: - file = open('tests/zap_sample.xml') - payload = { - 'engagement': 1, - 'scan_type': 'ZAP Scan', - 'file': file, - } - test_ids = list(Test.objects.values_list('id', flat=True)) - r = self.client.post(reverse('importscan-list'), payload) - self.assertEqual(201, r.status_code) - return Test.objects.exclude(id__in=test_ids).get() + with open('tests/zap_sample.xml') as file: + if upload_empty_scan: + file = SimpleUploadedFile('zap_sample.xml', self.EMPTY_ZAP_SCAN.encode('utf-8')) + + self.payload = { + 'engagement': 1, + 'scan_type': 'ZAP Scan', + 'file': file, + } + test_ids = list(Test.objects.values_list('id', flat=True)) + r = self.client.post(reverse('importscan-list'), self.payload) + self.assertEqual(201, r.status_code) + + return Test.objects.exclude(id__in=test_ids).get() def get_all_finding_ids(self, **kwargs): return set(Finding.objects.filter(test__engagement_id=1, **kwargs) diff --git a/unittests/test_endpoint_meta_import.py b/unittests/test_endpoint_meta_import.py index 23981ab0b7..118ceefa80 100644 --- a/unittests/test_endpoint_meta_import.py +++ b/unittests/test_endpoint_meta_import.py @@ -204,11 +204,12 @@ def endpoint_meta_import_ui(self, product, payload): def endpoint_meta_import_scan_with_params_ui(self, filename, product=1, create_endpoints=True, create_tags=True, create_dojo_meta=True, expected_http_status_code=201): - payload = { - "create_endpoints": create_endpoints, - "create_tags": create_tags, - "create_dojo_meta": create_dojo_meta, - "file": open(get_unit_tests_path() + '/' + filename), - } - - return self.endpoint_meta_import_ui(product, payload) + with open(get_unit_tests_path() + '/' + filename) as testfile: + payload = { + "create_endpoints": create_endpoints, + "create_tags": create_tags, + "create_dojo_meta": create_dojo_meta, + "file": testfile, + } + + return self.endpoint_meta_import_ui(product, payload) diff --git a/unittests/test_import_reimport.py b/unittests/test_import_reimport.py index 79524465f4..a3a9b72d30 100644 --- a/unittests/test_import_reimport.py +++ b/unittests/test_import_reimport.py @@ -1786,33 +1786,36 @@ def import_scan_with_params_ui(self, filename, scan_type='ZAP Scan', engagement= elif not verified: verifiedPayload = "force_to_false" - payload = { - "minimum_severity": minimum_severity, - "active": activePayload, - "verified": verifiedPayload, - "scan_type": scan_type, - "file": open(get_unit_tests_path() + filename), - "environment": 1, - "version": "1.0.1", - "close_old_findings": close_old_findings, - } + with open(get_unit_tests_path() + filename) as testfile: + payload = { + "minimum_severity": minimum_severity, + "active": activePayload, + "verified": verifiedPayload, + "scan_type": scan_type, + "file": testfile, + "environment": 1, + "version": "1.0.1", + "close_old_findings": close_old_findings, + } + + if push_to_jira is not None: + payload['push_to_jira'] = push_to_jira - if push_to_jira is not None: - payload['push_to_jira'] = push_to_jira + if endpoint_to_add is not None: + payload['endpoints'] = [endpoint_to_add] - if endpoint_to_add is not None: - payload['endpoints'] = [endpoint_to_add] + if tags is not None: + payload['tags'] = tags - if tags is not None: - payload['tags'] = tags + if scan_date is not None: + payload['scan_date'] = scan_date - if scan_date is not None: - payload['scan_date'] = scan_date + if service is not None: + payload['service'] = service - if service is not None: - payload['service'] = service + result = self.import_scan_ui(engagement, payload) - return self.import_scan_ui(engagement, payload) + return result def reimport_scan_with_params_ui(self, test_id, filename, scan_type='ZAP Scan', minimum_severity='Low', active=True, verified=False, push_to_jira=None, tags=None, close_old_findings=True, scan_date=None): # Mimic old functionality for active/verified to avoid breaking tests @@ -1823,26 +1826,28 @@ def reimport_scan_with_params_ui(self, test_id, filename, scan_type='ZAP Scan', if not verified: verifiedPayload = "force_to_false" - payload = { - "minimum_severity": minimum_severity, - "active": activePayload, - "verified": verifiedPayload, - "scan_type": scan_type, - "file": open(get_unit_tests_path() + filename), - "version": "1.0.1", - "close_old_findings": close_old_findings, - } + with open(get_unit_tests_path() + filename) as testfile: + payload = { + "minimum_severity": minimum_severity, + "active": activePayload, + "verified": verifiedPayload, + "scan_type": scan_type, + "file": testfile, + "version": "1.0.1", + "close_old_findings": close_old_findings, + } - if push_to_jira is not None: - payload['push_to_jira'] = push_to_jira + if push_to_jira is not None: + payload['push_to_jira'] = push_to_jira - if tags is not None: - payload['tags'] = tags + if tags is not None: + payload['tags'] = tags - if scan_date is not None: - payload['scan_date'] = scan_date + if scan_date is not None: + payload['scan_date'] = scan_date - return self.reimport_scan_ui(test_id, payload) + result = self.reimport_scan_ui(test_id, payload) + return result # Observations: # - When reopening a mitigated finding, almost no fields are updated such as title, description, severity, impact, references, .... diff --git a/unittests/test_importers_closeold.py b/unittests/test_importers_closeold.py index 5d9092751c..2792ec025c 100644 --- a/unittests/test_importers_closeold.py +++ b/unittests/test_importers_closeold.py @@ -47,15 +47,15 @@ def test_close_old_same_engagement(self): self.assertEqual(4, len_new_findings) self.assertEqual(0, len_closed_findings) # Import test with only one finding. Remaining findings should close - scan = open(get_unit_tests_path() + "/scans/acunetix/one_finding.xml") - _test, len_new_findings, len_closed_findings, _ = importer.import_scan(scan, scan_type, engagement, lead=None, environment=environment, - active=True, verified=False, tags=None, minimum_severity=None, - user=user, endpoints_to_add=None, scan_date=scan_date, version=None, branch_tag=None, build_id=None, - commit_hash=None, push_to_jira=None, close_old_findings=True, group_by=None, api_scan_configuration=None) - self.assertEqual(1, len_new_findings) - # Dedupe is off and close old findings does not close old findings if they are the same finding. - # If this behaviour changes, or dedupe is on, the number of closed findings will be 4 - self.assertEqual(8, len_closed_findings) + with open(get_unit_tests_path() + "/scans/acunetix/one_finding.xml") as scan: + _test, len_new_findings, len_closed_findings, _ = importer.import_scan(scan, scan_type, engagement, lead=None, environment=environment, + active=True, verified=False, tags=None, minimum_severity=None, + user=user, endpoints_to_add=None, scan_date=scan_date, version=None, branch_tag=None, build_id=None, + commit_hash=None, push_to_jira=None, close_old_findings=True, group_by=None, api_scan_configuration=None) + self.assertEqual(1, len_new_findings) + # Dedupe is off and close old findings does not close old findings if they are the same finding. + # If this behaviour changes, or dedupe is on, the number of closed findings will be 4 + self.assertEqual(8, len_closed_findings) def test_close_old_same_product_scan(self): scan = get_unit_tests_path() + "/scans/acunetix/many_findings.xml" @@ -107,12 +107,12 @@ def test_close_old_same_product_scan(self): self.assertEqual(4, len_new_findings) self.assertEqual(0, len_closed_findings) # Import test with only one finding. Remaining findings should close - scan = open(get_unit_tests_path() + "/scans/acunetix/one_finding.xml") - _test, len_new_findings, len_closed_findings, _ = importer.import_scan(scan, scan_type, engagement3, lead=None, environment=environment, - active=True, verified=False, tags=None, minimum_severity=None, - user=user, endpoints_to_add=None, scan_date=scan_date, version=None, branch_tag=None, build_id=None, - commit_hash=None, push_to_jira=None, close_old_findings=True, close_old_findings_product_scope=True, group_by=None, api_scan_configuration=None) - self.assertEqual(1, len_new_findings) - # Dedupe is off, and close old findings does not close old findings if they are the same finding. - # If this behaviour changes, or dedupe is on, the number of closed findings will be 4 - self.assertEqual(8, len_closed_findings) + with open(get_unit_tests_path() + "/scans/acunetix/one_finding.xml") as scan: + _test, len_new_findings, len_closed_findings, _ = importer.import_scan(scan, scan_type, engagement3, lead=None, environment=environment, + active=True, verified=False, tags=None, minimum_severity=None, + user=user, endpoints_to_add=None, scan_date=scan_date, version=None, branch_tag=None, build_id=None, + commit_hash=None, push_to_jira=None, close_old_findings=True, close_old_findings_product_scope=True, group_by=None, api_scan_configuration=None) + self.assertEqual(1, len_new_findings) + # Dedupe is off, and close old findings does not close old findings if they are the same finding. + # If this behaviour changes, or dedupe is on, the number of closed findings will be 4 + self.assertEqual(8, len_closed_findings) diff --git a/unittests/test_importers_importer.py b/unittests/test_importers_importer.py index a51b21e456..c997327a9f 100644 --- a/unittests/test_importers_importer.py +++ b/unittests/test_importers_importer.py @@ -42,120 +42,120 @@ class TestDojoDefaultImporter(DojoTestCase): def test_parse_findings(self): scan_type = "Acunetix Scan" - scan = open(get_unit_tests_path() + "/scans/acunetix/one_finding.xml") - - user, _created = User.objects.get_or_create(username="admin") - - product_type, _created = Product_Type.objects.get_or_create(name="test") - product, _created = Product.objects.get_or_create( - name="TestDojoDefaultImporter", - prod_type=product_type, - ) - - engagement_name = "Test Create Engagement" - engagement, _created = Engagement.objects.get_or_create( - name=engagement_name, - product=product, - target_start=timezone.now(), - target_end=timezone.now(), - ) - lead, _ = User.objects.get_or_create(username="admin") - environment, _ = Development_Environment.objects.get_or_create(name="Development") - - # boot - importer = Importer() - - # create the test - # by defaut test_type == scan_type - test = importer.create_test(scan_type, scan_type, engagement, lead, environment) - - # parse the findings - parser = get_parser(scan_type) - parsed_findings = parser.get_findings(scan, test) - - # process - minimum_severity = "Info" - active = True - verified = True - scan_date = None - new_findings = importer.process_parsed_findings( - test, - parsed_findings, - scan_type, - user, - active, - verified, - minimum_severity=minimum_severity, - scan_date=scan_date, - sync=True - ) - - for finding in new_findings: - self.assertIn(finding.numerical_severity, ["S0", "S1", "S2", "S3", "S4"]) + with open(get_unit_tests_path() + "/scans/acunetix/one_finding.xml") as scan: + + user, _created = User.objects.get_or_create(username="admin") + + product_type, _created = Product_Type.objects.get_or_create(name="test") + product, _created = Product.objects.get_or_create( + name="TestDojoDefaultImporter", + prod_type=product_type, + ) + + engagement_name = "Test Create Engagement" + engagement, _created = Engagement.objects.get_or_create( + name=engagement_name, + product=product, + target_start=timezone.now(), + target_end=timezone.now(), + ) + lead, _ = User.objects.get_or_create(username="admin") + environment, _ = Development_Environment.objects.get_or_create(name="Development") + + # boot + importer = Importer() + + # create the test + # by defaut test_type == scan_type + test = importer.create_test(scan_type, scan_type, engagement, lead, environment) + + # parse the findings + parser = get_parser(scan_type) + parsed_findings = parser.get_findings(scan, test) + + # process + minimum_severity = "Info" + active = True + verified = True + scan_date = None + new_findings = importer.process_parsed_findings( + test, + parsed_findings, + scan_type, + user, + active, + verified, + minimum_severity=minimum_severity, + scan_date=scan_date, + sync=True + ) + + for finding in new_findings: + self.assertIn(finding.numerical_severity, ["S0", "S1", "S2", "S3", "S4"]) def test_import_scan(self): - scan = open(get_unit_tests_path() + "/scans/sarif/spotbugs.sarif") - scan_type = SarifParser().get_scan_types()[0] # SARIF format implement the new method - - user, _ = User.objects.get_or_create(username="admin") - _user_reporter, _ = User.objects.get_or_create(username="user_reporter") - - product_type, _ = Product_Type.objects.get_or_create(name="test2") - product, _ = Product.objects.get_or_create( - name="TestDojoDefaultImporter2", - prod_type=product_type, - ) - - engagement, _ = Engagement.objects.get_or_create( - name="Test Create Engagement2", - product=product, - target_start=timezone.now(), - target_end=timezone.now(), - ) - importer = Importer() - scan_date = None - environment, _ = Development_Environment.objects.get_or_create(name="Development") - test, len_new_findings, len_closed_findings, _ = importer.import_scan(scan, scan_type, engagement, lead=None, environment=environment, - active=True, verified=True, tags=None, minimum_severity=None, - user=user, endpoints_to_add=None, scan_date=scan_date, version=None, branch_tag=None, build_id=None, - commit_hash=None, push_to_jira=None, close_old_findings=False, group_by=None, api_scan_configuration=None) - - self.assertEqual(f"SpotBugs Scan ({scan_type})", test.test_type.name) - self.assertEqual(56, len_new_findings) - self.assertEqual(0, len_closed_findings) + with open(get_unit_tests_path() + "/scans/sarif/spotbugs.sarif") as scan: + scan_type = SarifParser().get_scan_types()[0] # SARIF format implement the new method + + user, _ = User.objects.get_or_create(username="admin") + _user_reporter, _ = User.objects.get_or_create(username="user_reporter") + + product_type, _ = Product_Type.objects.get_or_create(name="test2") + product, _ = Product.objects.get_or_create( + name="TestDojoDefaultImporter2", + prod_type=product_type, + ) + + engagement, _ = Engagement.objects.get_or_create( + name="Test Create Engagement2", + product=product, + target_start=timezone.now(), + target_end=timezone.now(), + ) + importer = Importer() + scan_date = None + environment, _ = Development_Environment.objects.get_or_create(name="Development") + test, len_new_findings, len_closed_findings, _ = importer.import_scan(scan, scan_type, engagement, lead=None, environment=environment, + active=True, verified=True, tags=None, minimum_severity=None, + user=user, endpoints_to_add=None, scan_date=scan_date, version=None, branch_tag=None, build_id=None, + commit_hash=None, push_to_jira=None, close_old_findings=False, group_by=None, api_scan_configuration=None) + + self.assertEqual(f"SpotBugs Scan ({scan_type})", test.test_type.name) + self.assertEqual(56, len_new_findings) + self.assertEqual(0, len_closed_findings) def test_import_scan_without_test_scan_type(self): # GitLabSastParser implements get_tests but report has no scanner name - scan = open(f"{get_unit_tests_path()}/scans/gitlab_sast/gl-sast-report-1-vuln_v15.json") - scan_type = GitlabSastParser().get_scan_types()[0] - - user, _ = User.objects.get_or_create(username="admin") - _user_reporter, _ = User.objects.get_or_create(username="user_reporter") - - product_type, _ = Product_Type.objects.get_or_create(name="test2") - product, _ = Product.objects.get_or_create( - name="TestDojoDefaultImporter2", - prod_type=product_type, - ) - - engagement, _ = Engagement.objects.get_or_create( - name="Test Create Engagement2", - product=product, - target_start=timezone.now(), - target_end=timezone.now(), - ) - - importer = Importer() - scan_date = None - environment, _ = Development_Environment.objects.get_or_create(name="Development") - test, len_new_findings, len_closed_findings, _ = importer.import_scan(scan, scan_type, engagement, lead=None, environment=environment, - active=True, verified=True, tags=None, minimum_severity=None, - user=user, endpoints_to_add=None, scan_date=scan_date, version=None, branch_tag=None, build_id=None, - commit_hash=None, push_to_jira=None, close_old_findings=False, group_by=None, api_scan_configuration=None) - - self.assertEqual("GitLab SAST Report", test.test_type.name) - self.assertEqual(1, len_new_findings) - self.assertEqual(0, len_closed_findings) + with open(f"{get_unit_tests_path()}/scans/gitlab_sast/gl-sast-report-1-vuln_v15.json") as scan: + scan_type = GitlabSastParser().get_scan_types()[0] + + user, _ = User.objects.get_or_create(username="admin") + _user_reporter, _ = User.objects.get_or_create(username="user_reporter") + + product_type, _ = Product_Type.objects.get_or_create(name="test2") + product, _ = Product.objects.get_or_create( + name="TestDojoDefaultImporter2", + prod_type=product_type, + ) + + engagement, _ = Engagement.objects.get_or_create( + name="Test Create Engagement2", + product=product, + target_start=timezone.now(), + target_end=timezone.now(), + ) + + importer = Importer() + scan_date = None + environment, _ = Development_Environment.objects.get_or_create(name="Development") + test, len_new_findings, len_closed_findings, _ = importer.import_scan(scan, scan_type, engagement, lead=None, environment=environment, + active=True, verified=True, tags=None, minimum_severity=None, + user=user, endpoints_to_add=None, scan_date=scan_date, version=None, branch_tag=None, build_id=None, + commit_hash=None, push_to_jira=None, close_old_findings=False, group_by=None, api_scan_configuration=None) + + self.assertEqual("GitLab SAST Report", test.test_type.name) + self.assertEqual(1, len_new_findings) + self.assertEqual(0, len_closed_findings) class FlexibleImportTestAPI(DojoAPITestCase): diff --git a/unittests/test_parsers.py b/unittests/test_parsers.py index afd849aa7c..57ef61fa1d 100644 --- a/unittests/test_parsers.py +++ b/unittests/test_parsers.py @@ -29,20 +29,21 @@ def test_file_existence(self): f"Documentation file '{doc_file}' is missing or using different name" ) - content = open(doc_file).read() - self.assertTrue(re.search("title:", content), - f"Documentation file '{doc_file}' does not contain a title" - ) - self.assertTrue(re.search("toc_hide: true", content), - f"Documentation file '{doc_file}' does not contain toc_hide: true" - ) - if category == "file": - self.assertTrue(re.search("### Sample Scan Data", content), - f"Documentation file '{doc_file}' does not contain ### Sample Scan Data" + with open(doc_file) as file: + content = file.read() + self.assertTrue(re.search("title:", content), + f"Documentation file '{doc_file}' does not contain a title" ) - self.assertTrue(re.search("https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans", content), - f"Documentation file '{doc_file}' does not contain https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans" + self.assertTrue(re.search("toc_hide: true", content), + f"Documentation file '{doc_file}' does not contain toc_hide: true" ) + if category == "file": + self.assertTrue(re.search("### Sample Scan Data", content), + f"Documentation file '{doc_file}' does not contain ### Sample Scan Data" + ) + self.assertTrue(re.search("https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans", content), + f"Documentation file '{doc_file}' does not contain https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans" + ) if parser_dir.name not in [ # there is not exception for now @@ -79,20 +80,21 @@ def test_file_existence(self): if file.is_file() and file.name != '__pycache__' and file.name != "__init__.py": f = os.path.join(basedir, 'dojo', 'tools', parser_dir.name, file.name) read_true = False - for line in open(f).readlines(): - if read_true is True: - if ('"utf-8"' in str(line) or "'utf-8'" in str(line) or '"utf-8-sig"' in str(line) or "'utf-8-sig'" in str(line)) and i <= 4: - read_true = False - i = 0 - elif i > 4: - self.assertTrue(False, "In file " + str(os.path.join('dojo', 'tools', parser_dir.name, file.name)) + " the test is failing because you don't have utf-8 after .read()") + with open(f) as f: + for line in f.readlines(): + if read_true is True: + if ('"utf-8"' in str(line) or "'utf-8'" in str(line) or '"utf-8-sig"' in str(line) or "'utf-8-sig'" in str(line)) and i <= 4: + read_true = False + i = 0 + elif i > 4: + self.assertTrue(False, "In file " + str(os.path.join('dojo', 'tools', parser_dir.name, file.name)) + " the test is failing because you don't have utf-8 after .read()") + i = 0 + read_true = False + else: + i += 1 + if ".read()" in str(line): + read_true = True i = 0 - read_true = False - else: - i += 1 - if ".read()" in str(line): - read_true = True - i = 0 def test_parser_existence(self): for docs in os.scandir(os.path.join(basedir, 'docs', 'content', 'en', 'integrations', 'parsers', 'file')): diff --git a/unittests/test_rest_framework.py b/unittests/test_rest_framework.py index ca2604ad1a..dba925e70b 100644 --- a/unittests/test_rest_framework.py +++ b/unittests/test_rest_framework.py @@ -1041,15 +1041,17 @@ def test_request_response_post_and_download(self): # Test the creation for level in self.url_levels.keys(): length = FileUpload.objects.count() - payload = { - "title": level, - "file": open(f'{str(self.path)}/scans/acunetix/one_finding.xml') - } - response = self.client.post(f'/api/v2/{level}/files/', payload) - self.assertEqual(201, response.status_code, response.data) - self.assertEqual(FileUpload.objects.count(), length + 1) - # Save the ID of the newly created file object - self.url_levels[level] = response.data.get('id') + with open(f'{str(self.path)}/scans/acunetix/one_finding.xml') as testfile: + payload = { + "title": level, + "file": testfile + } + response = self.client.post(f'/api/v2/{level}/files/', payload) + self.assertEqual(201, response.status_code, response.data) + self.assertEqual(FileUpload.objects.count(), length + 1) + # Save the ID of the newly created file object + self.url_levels[level] = response.data.get('id') + # Test the download with open(f'{str(self.path)}/scans/acunetix/one_finding.xml') as file: file_data = file.read() @@ -1700,12 +1702,14 @@ def __init__(self, *args, **kwargs): self.endpoint_path = 'import-scan' self.viewname = 'importscan' self.viewset = ImportScanView + + testfile = open('tests/zap_sample.xml') self.payload = { "minimum_severity": 'Low', "active": False, "verified": True, "scan_type": 'ZAP Scan', - "file": open('tests/zap_sample.xml'), + "file": testfile, "engagement": 1, "lead": 2, "tags": ["ci/cd", "api"], @@ -1715,6 +1719,9 @@ def __init__(self, *args, **kwargs): self.permission_create = Permissions.Import_Scan_Result BaseClass.RESTEndpointTest.__init__(self, *args, **kwargs) + def __del__(self: object): + self.payload['file'].close() + @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') @patch('dojo.api_v2.permissions.user_has_permission') @@ -1723,26 +1730,27 @@ def test_create_not_authorized_product_name_engagement_name(self, mock, importer importer_mock.return_value = IMPORTER_MOCK_RETURN_VALUE reimporter_mock.return_value = REIMPORTER_MOCK_RETURN_VALUE - payload = { - "minimum_severity": 'Low', - "active": False, - "verified": True, - "scan_type": 'ZAP Scan', - "file": open('tests/zap_sample.xml'), - "product_name": 'Python How-to', - "engagement_name": 'April monthly engagement', - "lead": 2, - "tags": ["ci/cd", "api"], - "version": "1.0.0", - } + with open('tests/zap_sample.xml') as testfile: + payload = { + "minimum_severity": 'Low', + "active": False, + "verified": True, + "scan_type": 'ZAP Scan', + "file": testfile, + "product_name": 'Python How-to', + "engagement_name": 'April monthly engagement', + "lead": 2, + "tags": ["ci/cd", "api"], + "version": "1.0.0", + } - response = self.client.post(self.url, payload) - self.assertEqual(403, response.status_code, response.content[:1000]) - mock.assert_called_with(User.objects.get(username='admin'), - Engagement.objects.get(id=2), # engagement id found via product name and engagement name - Permissions.Import_Scan_Result) - importer_mock.assert_not_called() - reimporter_mock.assert_not_called() + response = self.client.post(self.url, payload) + self.assertEqual(403, response.status_code, response.content[:1000]) + mock.assert_called_with(User.objects.get(username='admin'), + Engagement.objects.get(id=2), # engagement id found via product name and engagement name + Permissions.Import_Scan_Result) + importer_mock.assert_not_called() + reimporter_mock.assert_not_called() @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') @@ -1752,27 +1760,28 @@ def test_create_not_authorized_product_name_engagement_name_auto_create_engageme importer_mock.return_value = IMPORTER_MOCK_RETURN_VALUE reimporter_mock.return_value = REIMPORTER_MOCK_RETURN_VALUE - payload = { - "minimum_severity": 'Low', - "active": False, - "verified": True, - "scan_type": 'ZAP Scan', - "file": open('tests/zap_sample.xml'), - "product_name": 'Python How-to', - "engagement_name": 'New engagement', - "lead": 2, - "tags": ["ci/cd", "api"], - "version": "1.0.0", - "auto_create_context": True - } + with open('tests/zap_sample.xml') as testfile: + payload = { + "minimum_severity": 'Low', + "active": False, + "verified": True, + "scan_type": 'ZAP Scan', + "file": testfile, + "product_name": 'Python How-to', + "engagement_name": 'New engagement', + "lead": 2, + "tags": ["ci/cd", "api"], + "version": "1.0.0", + "auto_create_context": True + } - response = self.client.post(self.url, payload) - self.assertEqual(403, response.status_code, response.content[:1000]) - mock.assert_called_with(User.objects.get(username='admin'), - Product.objects.get(id=1), - Permissions.Engagement_Add) - importer_mock.assert_not_called() - reimporter_mock.assert_not_called() + response = self.client.post(self.url, payload) + self.assertEqual(403, response.status_code, response.content[:1000]) + mock.assert_called_with(User.objects.get(username='admin'), + Product.objects.get(id=1), + Permissions.Engagement_Add) + importer_mock.assert_not_called() + reimporter_mock.assert_not_called() @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') @@ -1782,28 +1791,29 @@ def test_create_not_authorized_product_name_engagement_name_auto_create_product( importer_mock.return_value = IMPORTER_MOCK_RETURN_VALUE reimporter_mock.return_value = REIMPORTER_MOCK_RETURN_VALUE - payload = { - "minimum_severity": 'Low', - "active": False, - "verified": True, - "scan_type": 'ZAP Scan', - "file": open('tests/zap_sample.xml'), - "product_type_name": "books", - "product_name": 'New Product', - "engagement_name": 'New engagement', - "lead": 2, - "tags": ["ci/cd", "api"], - "version": "1.0.0", - "auto_create_context": True - } + with open('tests/zap_sample.xml') as testfile: + payload = { + "minimum_severity": 'Low', + "active": False, + "verified": True, + "scan_type": 'ZAP Scan', + "file": testfile, + "product_type_name": "books", + "product_name": 'New Product', + "engagement_name": 'New engagement', + "lead": 2, + "tags": ["ci/cd", "api"], + "version": "1.0.0", + "auto_create_context": True + } - response = self.client.post(self.url, payload) - self.assertEqual(403, response.status_code, response.content[:1000]) - mock.assert_called_with(User.objects.get(username='admin'), - Product_Type.objects.get(id=1), - Permissions.Product_Type_Add_Product) - importer_mock.assert_not_called() - reimporter_mock.assert_not_called() + response = self.client.post(self.url, payload) + self.assertEqual(403, response.status_code, response.content[:1000]) + mock.assert_called_with(User.objects.get(username='admin'), + Product_Type.objects.get(id=1), + Permissions.Product_Type_Add_Product) + importer_mock.assert_not_called() + reimporter_mock.assert_not_called() @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') @@ -1813,27 +1823,28 @@ def test_create_not_authorized_product_name_engagement_name_auto_create_product_ importer_mock.return_value = IMPORTER_MOCK_RETURN_VALUE reimporter_mock.return_value = REIMPORTER_MOCK_RETURN_VALUE - payload = { - "minimum_severity": 'Low', - "active": False, - "verified": True, - "scan_type": 'ZAP Scan', - "file": open('tests/zap_sample.xml'), - "product_type_name": "more books", - "product_name": 'New Product', - "engagement_name": 'New engagement', - "lead": 2, - "tags": ["ci/cd", "api"], - "version": "1.0.0", - "auto_create_context": True - } + with open('tests/zap_sample.xml') as testfile: + payload = { + "minimum_severity": 'Low', + "active": False, + "verified": True, + "scan_type": 'ZAP Scan', + "file": testfile, + "product_type_name": "more books", + "product_name": 'New Product', + "engagement_name": 'New engagement', + "lead": 2, + "tags": ["ci/cd", "api"], + "version": "1.0.0", + "auto_create_context": True + } - response = self.client.post(self.url, payload) - self.assertEqual(403, response.status_code, response.content[:1000]) - mock.assert_called_with(User.objects.get(username='admin'), - Permissions.Product_Type_Add) - importer_mock.assert_not_called() - reimporter_mock.assert_not_called() + response = self.client.post(self.url, payload) + self.assertEqual(403, response.status_code, response.content[:1000]) + mock.assert_called_with(User.objects.get(username='admin'), + Permissions.Product_Type_Add) + importer_mock.assert_not_called() + reimporter_mock.assert_not_called() @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') @@ -1846,32 +1857,33 @@ def test_create_authorized_product_name_engagement_name_auto_create_engagement(s importer_mock.return_value = IMPORTER_MOCK_RETURN_VALUE reimporter_mock.return_value = REIMPORTER_MOCK_RETURN_VALUE - payload = { - "minimum_severity": 'Low', - "active": False, - "verified": True, - "scan_type": 'ZAP Scan', - "file": open('tests/zap_sample.xml'), - "product_name": 'Python How-to', - "engagement_name": 'New engagement', - "lead": 2, - "tags": ["ci/cd", "api"], - "version": "1.0.0", - "auto_create_context": True - } + with open('tests/zap_sample.xml') as testfile: + payload = { + "minimum_severity": 'Low', + "active": False, + "verified": True, + "scan_type": 'ZAP Scan', + "file": testfile, + "product_name": 'Python How-to', + "engagement_name": 'New engagement', + "lead": 2, + "tags": ["ci/cd", "api"], + "version": "1.0.0", + "auto_create_context": True + } - response = self.client.post(self.url, payload) - self.assertEqual(201, response.status_code, response.content[:1000]) - mock.assert_has_calls([ - call(User.objects.get(username='admin'), - Product.objects.get(id=1), - Permissions.Engagement_Add), - call(User.objects.get(username='admin'), - Product.objects.get(id=1), - Permissions.Import_Scan_Result) - ]) - importer_mock.assert_called_once() - reimporter_mock.assert_not_called() + response = self.client.post(self.url, payload) + self.assertEqual(201, response.status_code, response.content[:1000]) + mock.assert_has_calls([ + call(User.objects.get(username='admin'), + Product.objects.get(id=1), + Permissions.Engagement_Add), + call(User.objects.get(username='admin'), + Product.objects.get(id=1), + Permissions.Import_Scan_Result) + ]) + importer_mock.assert_called_once() + reimporter_mock.assert_not_called() @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') @@ -1880,29 +1892,29 @@ def test_create_authorized_product_name_engagement_name_auto_create_product(self mock.return_value = True importer_mock.return_value = IMPORTER_MOCK_RETURN_VALUE reimporter_mock.return_value = REIMPORTER_MOCK_RETURN_VALUE + with open('tests/zap_sample.xml') as testfile: + payload = { + "minimum_severity": 'Low', + "active": False, + "verified": True, + "scan_type": 'ZAP Scan', + "file": testfile, + "product_type_name": "books", + "product_name": 'New Product', + "engagement_name": 'New engagement', + "lead": 2, + "tags": ["ci/cd", "api"], + "version": "1.0.0", + "auto_create_context": True + } - payload = { - "minimum_severity": 'Low', - "active": False, - "verified": True, - "scan_type": 'ZAP Scan', - "file": open('tests/zap_sample.xml'), - "product_type_name": "books", - "product_name": 'New Product', - "engagement_name": 'New engagement', - "lead": 2, - "tags": ["ci/cd", "api"], - "version": "1.0.0", - "auto_create_context": True - } - - response = self.client.post(self.url, payload) - self.assertEqual(201, response.status_code, response.content[:1000]) - mock.assert_called_with(User.objects.get(username='admin'), - Product_Type.objects.get(id=1), - Permissions.Product_Type_Add_Product) - importer_mock.assert_called_once() - reimporter_mock.assert_not_called() + response = self.client.post(self.url, payload) + self.assertEqual(201, response.status_code, response.content[:1000]) + mock.assert_called_with(User.objects.get(username='admin'), + Product_Type.objects.get(id=1), + Permissions.Product_Type_Add_Product) + importer_mock.assert_called_once() + reimporter_mock.assert_not_called() @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') @@ -1912,27 +1924,28 @@ def test_create_authorized_product_name_engagement_name_auto_create_product_type importer_mock.return_value = IMPORTER_MOCK_RETURN_VALUE reimporter_mock.return_value = REIMPORTER_MOCK_RETURN_VALUE - payload = { - "minimum_severity": 'Low', - "active": False, - "verified": True, - "scan_type": 'ZAP Scan', - "file": open('tests/zap_sample.xml'), - "product_type_name": "more books", - "product_name": 'New Product', - "engagement_name": 'New engagement', - "lead": 2, - "tags": ["ci/cd", "api"], - "version": "1.0.0", - "auto_create_context": True - } + with open('tests/zap_sample.xml') as testfile: + payload = { + "minimum_severity": 'Low', + "active": False, + "verified": True, + "scan_type": 'ZAP Scan', + "file": testfile, + "product_type_name": "more books", + "product_name": 'New Product', + "engagement_name": 'New engagement', + "lead": 2, + "tags": ["ci/cd", "api"], + "version": "1.0.0", + "auto_create_context": True + } - response = self.client.post(self.url, payload) - self.assertEqual(201, response.status_code, response.content[:1000]) - mock.assert_called_with(User.objects.get(username='admin'), - Permissions.Product_Type_Add) - importer_mock.assert_called_once() - reimporter_mock.assert_not_called() + response = self.client.post(self.url, payload) + self.assertEqual(201, response.status_code, response.content[:1000]) + mock.assert_called_with(User.objects.get(username='admin'), + Permissions.Product_Type_Add) + importer_mock.assert_called_once() + reimporter_mock.assert_not_called() class ReimportScanTest(DojoAPITestCase): @@ -1953,22 +1966,23 @@ def test_reimport_zap_xml(self, importer_mock, reimporter_mock): importer_mock.return_value = IMPORTER_MOCK_RETURN_VALUE reimporter_mock.return_value = REIMPORTER_MOCK_RETURN_VALUE - length = Test.objects.all().count() - response = self.client.post( - reverse('reimportscan-list'), { - "minimum_severity": 'Low', - "active": True, - "verified": True, - "scan_type": 'ZAP Scan', - "file": open('tests/zap_sample.xml'), - "test": 3, - "version": "1.0.1", - }) - self.assertEqual(length, Test.objects.all().count()) - self.assertEqual(201, response.status_code, response.content[:1000]) - # TODO add schema check - importer_mock.assert_not_called() - reimporter_mock.assert_called_once() + with open('tests/zap_sample.xml') as testfile: + length = Test.objects.all().count() + response = self.client.post( + reverse('reimportscan-list'), { + "minimum_severity": 'Low', + "active": True, + "verified": True, + "scan_type": 'ZAP Scan', + "file": testfile, + "test": 3, + "version": "1.0.1", + }) + self.assertEqual(length, Test.objects.all().count()) + self.assertEqual(201, response.status_code, response.content[:1000]) + # TODO add schema check + importer_mock.assert_not_called() + reimporter_mock.assert_called_once() @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') @@ -1978,26 +1992,27 @@ def test_create_not_authorized_product_name_engagement_name(self, mock, importer importer_mock.return_value = IMPORTER_MOCK_RETURN_VALUE reimporter_mock.return_value = REIMPORTER_MOCK_RETURN_VALUE - payload = { - "minimum_severity": 'Low', - "active": False, - "verified": True, - "scan_type": 'ZAP Scan', - "file": open('tests/zap_sample.xml'), - "product_name": 'Security How-to', - "engagement_name": 'April monthly engagement', - "lead": 2, - "tags": ["ci/cd", "api"], - "version": "1.0.0", - } + with open('tests/zap_sample.xml') as testfile: + payload = { + "minimum_severity": 'Low', + "active": False, + "verified": True, + "scan_type": 'ZAP Scan', + "file": testfile, + "product_name": 'Security How-to', + "engagement_name": 'April monthly engagement', + "lead": 2, + "tags": ["ci/cd", "api"], + "version": "1.0.0", + } - response = self.client.post(self.url, payload) - self.assertEqual(403, response.status_code, response.content[:1000]) - mock.assert_called_with(User.objects.get(username='admin'), - Test.objects.get(id=4), # test id found via product name and engagement name and scan_type - Permissions.Import_Scan_Result) - importer_mock.assert_not_called() - reimporter_mock.assert_not_called() + response = self.client.post(self.url, payload) + self.assertEqual(403, response.status_code, response.content[:1000]) + mock.assert_called_with(User.objects.get(username='admin'), + Test.objects.get(id=4), # test id found via product name and engagement name and scan_type + Permissions.Import_Scan_Result) + importer_mock.assert_not_called() + reimporter_mock.assert_not_called() @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') @@ -2007,26 +2022,27 @@ def test_create_authorized_product_name_engagement_name_scan_type_title_auto_cre importer_mock.return_value = IMPORTER_MOCK_RETURN_VALUE reimporter_mock.return_value = REIMPORTER_MOCK_RETURN_VALUE - payload = { - "minimum_severity": 'Low', - "active": False, - "verified": True, - "scan_type": 'ZAP Scan', - "file": open('tests/zap_sample.xml'), - "product_name": 'Security How-to', - "engagement_name": 'April monthly engagement', - "test_title": 'My ZAP Scan NEW', - "version": "1.0.0", - "auto_create_context": True, - } + with open('tests/zap_sample.xml') as testfile: + payload = { + "minimum_severity": 'Low', + "active": False, + "verified": True, + "scan_type": 'ZAP Scan', + "file": testfile, + "product_name": 'Security How-to', + "engagement_name": 'April monthly engagement', + "test_title": 'My ZAP Scan NEW', + "version": "1.0.0", + "auto_create_context": True, + } - response = self.client.post(self.url, payload) - self.assertEqual(201, response.status_code, response.content[:1000]) - mock.assert_called_with(User.objects.get(username='admin'), - Engagement.objects.get(id=4), - Permissions.Import_Scan_Result) - importer_mock.assert_called_once() - reimporter_mock.assert_not_called() + response = self.client.post(self.url, payload) + self.assertEqual(201, response.status_code, response.content[:1000]) + mock.assert_called_with(User.objects.get(username='admin'), + Engagement.objects.get(id=4), + Permissions.Import_Scan_Result) + importer_mock.assert_called_once() + reimporter_mock.assert_not_called() @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') @@ -2039,32 +2055,33 @@ def test_create_authorized_product_name_engagement_name_auto_create_engagement(s importer_mock.return_value = IMPORTER_MOCK_RETURN_VALUE reimporter_mock.return_value = REIMPORTER_MOCK_RETURN_VALUE - payload = { - "minimum_severity": 'Low', - "active": False, - "verified": True, - "scan_type": 'ZAP Scan', - "file": open('tests/zap_sample.xml'), - "product_name": 'Python How-to', - "engagement_name": 'New engagement', - "lead": 2, - "tags": ["ci/cd", "api"], - "version": "1.0.0", - "auto_create_context": True - } + with open('tests/zap_sample.xml') as testfile: + payload = { + "minimum_severity": 'Low', + "active": False, + "verified": True, + "scan_type": 'ZAP Scan', + "file": testfile, + "product_name": 'Python How-to', + "engagement_name": 'New engagement', + "lead": 2, + "tags": ["ci/cd", "api"], + "version": "1.0.0", + "auto_create_context": True + } - response = self.client.post(self.url, payload) - self.assertEqual(201, response.status_code, response.content[:1000]) - mock.assert_has_calls([ - call(User.objects.get(username='admin'), - Product.objects.get(id=1), - Permissions.Engagement_Add), - call(User.objects.get(username='admin'), - Product.objects.get(id=1), - Permissions.Import_Scan_Result) - ]) - importer_mock.assert_called_once() - reimporter_mock.assert_not_called() + response = self.client.post(self.url, payload) + self.assertEqual(201, response.status_code, response.content[:1000]) + mock.assert_has_calls([ + call(User.objects.get(username='admin'), + Product.objects.get(id=1), + Permissions.Engagement_Add), + call(User.objects.get(username='admin'), + Product.objects.get(id=1), + Permissions.Import_Scan_Result) + ]) + importer_mock.assert_called_once() + reimporter_mock.assert_not_called() @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') @@ -2074,28 +2091,29 @@ def test_create_authorized_product_name_engagement_name_auto_create_product(self importer_mock.return_value = IMPORTER_MOCK_RETURN_VALUE reimporter_mock.return_value = REIMPORTER_MOCK_RETURN_VALUE - payload = { - "minimum_severity": 'Low', - "active": False, - "verified": True, - "scan_type": 'ZAP Scan', - "file": open('tests/zap_sample.xml'), - "product_type_name": "books", - "product_name": 'New Product', - "engagement_name": 'New engagement', - "lead": 2, - "tags": ["ci/cd", "api"], - "version": "1.0.0", - "auto_create_context": True - } + with open('tests/zap_sample.xml') as testfile: + payload = { + "minimum_severity": 'Low', + "active": False, + "verified": True, + "scan_type": 'ZAP Scan', + "file": testfile, + "product_type_name": "books", + "product_name": 'New Product', + "engagement_name": 'New engagement', + "lead": 2, + "tags": ["ci/cd", "api"], + "version": "1.0.0", + "auto_create_context": True + } - response = self.client.post(self.url, payload) - self.assertEqual(201, response.status_code, response.content[:1000]) - mock.assert_called_with(User.objects.get(username='admin'), - Product_Type.objects.get(id=1), - Permissions.Product_Type_Add_Product) - importer_mock.assert_called_once() - reimporter_mock.assert_not_called() + response = self.client.post(self.url, payload) + self.assertEqual(201, response.status_code, response.content[:1000]) + mock.assert_called_with(User.objects.get(username='admin'), + Product_Type.objects.get(id=1), + Permissions.Product_Type_Add_Product) + importer_mock.assert_called_once() + reimporter_mock.assert_not_called() @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') @@ -2105,27 +2123,28 @@ def test_create_authorized_product_name_engagement_name_auto_create_product_type importer_mock.return_value = IMPORTER_MOCK_RETURN_VALUE reimporter_mock.return_value = REIMPORTER_MOCK_RETURN_VALUE - payload = { - "minimum_severity": 'Low', - "active": False, - "verified": True, - "scan_type": 'ZAP Scan', - "file": open('tests/zap_sample.xml'), - "product_type_name": "more books", - "product_name": 'New Product', - "engagement_name": 'New engagement', - "lead": 2, - "tags": ["ci/cd", "api"], - "version": "1.0.0", - "auto_create_context": True - } + with open('tests/zap_sample.xml') as testfile: + payload = { + "minimum_severity": 'Low', + "active": False, + "verified": True, + "scan_type": 'ZAP Scan', + "file": testfile, + "product_type_name": "more books", + "product_name": 'New Product', + "engagement_name": 'New engagement', + "lead": 2, + "tags": ["ci/cd", "api"], + "version": "1.0.0", + "auto_create_context": True + } - response = self.client.post(self.url, payload) - self.assertEqual(201, response.status_code, response.content[:1000]) - mock.assert_called_with(User.objects.get(username='admin'), - Permissions.Product_Type_Add) - importer_mock.assert_called_once() - reimporter_mock.assert_not_called() + response = self.client.post(self.url, payload) + self.assertEqual(201, response.status_code, response.content[:1000]) + mock.assert_called_with(User.objects.get(username='admin'), + Permissions.Product_Type_Add) + importer_mock.assert_called_once() + reimporter_mock.assert_not_called() @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') @@ -2135,22 +2154,23 @@ def test_create_not_authorized_test_id(self, mock, importer_mock, reimporter_moc importer_mock.return_value = IMPORTER_MOCK_RETURN_VALUE reimporter_mock.return_value = REIMPORTER_MOCK_RETURN_VALUE - payload = { - "minimum_severity": 'Low', - "active": True, - "verified": True, - "scan_type": 'ZAP Scan', - "file": open('tests/zap_sample.xml'), - "test": 3, - "version": "1.0.1" - } - response = self.client.post(self.url, payload) - self.assertEqual(403, response.status_code, response.content[:1000]) - mock.assert_called_with(User.objects.get(username='admin'), - Test.objects.get(id=3), - Permissions.Import_Scan_Result) - importer_mock.assert_not_called() - reimporter_mock.assert_not_called() + with open('tests/zap_sample.xml') as testfile: + payload = { + "minimum_severity": 'Low', + "active": True, + "verified": True, + "scan_type": 'ZAP Scan', + "file": testfile, + "test": 3, + "version": "1.0.1" + } + response = self.client.post(self.url, payload) + self.assertEqual(403, response.status_code, response.content[:1000]) + mock.assert_called_with(User.objects.get(username='admin'), + Test.objects.get(id=3), + Permissions.Import_Scan_Result) + importer_mock.assert_not_called() + reimporter_mock.assert_not_called() # copied tests from import, unsure how to use inheritance/mixins with test_ methods @@ -2162,27 +2182,28 @@ def test_create_not_authorized_product_name_engagement_name_auto_create_engageme importer_mock.return_value = IMPORTER_MOCK_RETURN_VALUE reimporter_mock.return_value = REIMPORTER_MOCK_RETURN_VALUE - payload = { - "minimum_severity": 'Low', - "active": False, - "verified": True, - "scan_type": 'ZAP Scan', - "file": open('tests/zap_sample.xml'), - "product_name": 'Python How-to', - "engagement_name": 'New engagement', - "lead": 2, - "tags": ["ci/cd", "api"], - "version": "1.0.0", - "auto_create_context": True - } + with open('tests/zap_sample.xml') as testfile: + payload = { + "minimum_severity": 'Low', + "active": False, + "verified": True, + "scan_type": 'ZAP Scan', + "file": testfile, + "product_name": 'Python How-to', + "engagement_name": 'New engagement', + "lead": 2, + "tags": ["ci/cd", "api"], + "version": "1.0.0", + "auto_create_context": True + } - response = self.client.post(self.url, payload) - self.assertEqual(403, response.status_code, response.content[:1000]) - mock.assert_called_with(User.objects.get(username='admin'), - Product.objects.get(id=1), - Permissions.Engagement_Add) - importer_mock.assert_not_called() - reimporter_mock.assert_not_called() + response = self.client.post(self.url, payload) + self.assertEqual(403, response.status_code, response.content[:1000]) + mock.assert_called_with(User.objects.get(username='admin'), + Product.objects.get(id=1), + Permissions.Engagement_Add) + importer_mock.assert_not_called() + reimporter_mock.assert_not_called() @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') @@ -2192,28 +2213,29 @@ def test_create_not_authorized_product_name_engagement_name_auto_create_product( importer_mock.return_value = IMPORTER_MOCK_RETURN_VALUE reimporter_mock.return_value = REIMPORTER_MOCK_RETURN_VALUE - payload = { - "minimum_severity": 'Low', - "active": False, - "verified": True, - "scan_type": 'ZAP Scan', - "file": open('tests/zap_sample.xml'), - "product_type_name": "books", - "product_name": 'New Product', - "engagement_name": 'New engagement', - "lead": 2, - "tags": ["ci/cd", "api"], - "version": "1.0.0", - "auto_create_context": True - } + with open('tests/zap_sample.xml') as testfile: + payload = { + "minimum_severity": 'Low', + "active": False, + "verified": True, + "scan_type": 'ZAP Scan', + "file": testfile, + "product_type_name": "books", + "product_name": 'New Product', + "engagement_name": 'New engagement', + "lead": 2, + "tags": ["ci/cd", "api"], + "version": "1.0.0", + "auto_create_context": True + } - response = self.client.post(self.url, payload) - self.assertEqual(403, response.status_code, response.content[:1000]) - mock.assert_called_with(User.objects.get(username='admin'), - Product_Type.objects.get(id=1), - Permissions.Product_Type_Add_Product) - importer_mock.assert_not_called() - reimporter_mock.assert_not_called() + response = self.client.post(self.url, payload) + self.assertEqual(403, response.status_code, response.content[:1000]) + mock.assert_called_with(User.objects.get(username='admin'), + Product_Type.objects.get(id=1), + Permissions.Product_Type_Add_Product) + importer_mock.assert_not_called() + reimporter_mock.assert_not_called() @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') @@ -2223,27 +2245,28 @@ def test_create_not_authorized_product_name_engagement_name_auto_create_product_ importer_mock.return_value = IMPORTER_MOCK_RETURN_VALUE reimporter_mock.return_value = REIMPORTER_MOCK_RETURN_VALUE - payload = { - "minimum_severity": 'Low', - "active": False, - "verified": True, - "scan_type": 'ZAP Scan', - "file": open('tests/zap_sample.xml'), - "product_type_name": "more books", - "product_name": 'New Product', - "engagement_name": 'New engagement', - "lead": 2, - "tags": ["ci/cd", "api"], - "version": "1.0.0", - "auto_create_context": True - } + with open('tests/zap_sample.xml') as testfile: + payload = { + "minimum_severity": 'Low', + "active": False, + "verified": True, + "scan_type": 'ZAP Scan', + "file": testfile, + "product_type_name": "more books", + "product_name": 'New Product', + "engagement_name": 'New engagement', + "lead": 2, + "tags": ["ci/cd", "api"], + "version": "1.0.0", + "auto_create_context": True + } - response = self.client.post(self.url, payload) - self.assertEqual(403, response.status_code, response.content[:1000]) - mock.assert_called_with(User.objects.get(username='admin'), - Permissions.Product_Type_Add) - importer_mock.assert_not_called() - reimporter_mock.assert_not_called() + response = self.client.post(self.url, payload) + self.assertEqual(403, response.status_code, response.content[:1000]) + mock.assert_called_with(User.objects.get(username='admin'), + Permissions.Product_Type_Add) + importer_mock.assert_not_called() + reimporter_mock.assert_not_called() @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') @@ -2253,24 +2276,25 @@ def test_create_not_authorized_product_name_engagement_name_scan_type(self, mock importer_mock.return_value = IMPORTER_MOCK_RETURN_VALUE reimporter_mock.return_value = REIMPORTER_MOCK_RETURN_VALUE - payload = { - "minimum_severity": 'Low', - "active": False, - "verified": True, - "scan_type": 'ZAP Scan', - "file": open('tests/zap_sample.xml'), - "product_name": 'Security How-to', - "engagement_name": 'April monthly engagement', - "version": "1.0.0", - } + with open('tests/zap_sample.xml') as testfile: + payload = { + "minimum_severity": 'Low', + "active": False, + "verified": True, + "scan_type": 'ZAP Scan', + "file": testfile, + "product_name": 'Security How-to', + "engagement_name": 'April monthly engagement', + "version": "1.0.0", + } - response = self.client.post(self.url, payload) - self.assertEqual(403, response.status_code, response.content[:1000]) - mock.assert_called_with(User.objects.get(username='admin'), - Test.objects.get(id=4), # engagement id found via product name and engagement name - Permissions.Import_Scan_Result) - importer_mock.assert_not_called() - reimporter_mock.assert_not_called() + response = self.client.post(self.url, payload) + self.assertEqual(403, response.status_code, response.content[:1000]) + mock.assert_called_with(User.objects.get(username='admin'), + Test.objects.get(id=4), # engagement id found via product name and engagement name + Permissions.Import_Scan_Result) + importer_mock.assert_not_called() + reimporter_mock.assert_not_called() @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') @@ -2280,25 +2304,26 @@ def test_create_not_authorized_product_name_engagement_name_scan_type_title(self importer_mock.return_value = IMPORTER_MOCK_RETURN_VALUE reimporter_mock.return_value = REIMPORTER_MOCK_RETURN_VALUE - payload = { - "minimum_severity": 'Low', - "active": False, - "verified": True, - "scan_type": 'ZAP Scan', - "file": open('tests/zap_sample.xml'), - "product_name": 'Security How-to', - "engagement_name": 'April monthly engagement', - "test_title": 'My ZAP Scan', - "version": "1.0.0", - } + with open('tests/zap_sample.xml') as testfile: + payload = { + "minimum_severity": 'Low', + "active": False, + "verified": True, + "scan_type": 'ZAP Scan', + "file": testfile, + "product_name": 'Security How-to', + "engagement_name": 'April monthly engagement', + "test_title": 'My ZAP Scan', + "version": "1.0.0", + } - response = self.client.post(self.url, payload) - self.assertEqual(403, response.status_code, response.content[:1000]) - mock.assert_called_with(User.objects.get(username='admin'), - Test.objects.get(id=4), # test id found via product name and engagement name and scan_type and test_title - Permissions.Import_Scan_Result) - importer_mock.assert_not_called() - reimporter_mock.assert_not_called() + response = self.client.post(self.url, payload) + self.assertEqual(403, response.status_code, response.content[:1000]) + mock.assert_called_with(User.objects.get(username='admin'), + Test.objects.get(id=4), # test id found via product name and engagement name and scan_type and test_title + Permissions.Import_Scan_Result) + importer_mock.assert_not_called() + reimporter_mock.assert_not_called() class ProductTypeTest(BaseClass.RESTEndpointTest): @@ -2618,6 +2643,9 @@ def __init__(self, *args, **kwargs): self.permission_create = Permissions.Language_Add BaseClass.RESTEndpointTest.__init__(self, *args, **kwargs) + def __del__(self: object): + self.payload['file'].close() + def test_create(self): BaseClass.RESTEndpointTest.test_create(self) diff --git a/unittests/tools/test_acunetix_parser.py b/unittests/tools/test_acunetix_parser.py index eedf73b159..7238f5693a 100644 --- a/unittests/tools/test_acunetix_parser.py +++ b/unittests/tools/test_acunetix_parser.py @@ -8,165 +8,193 @@ class TestAcunetixParser(DojoTestCase): def test_parse_file_with_one_finding(self): - testfile = open("unittests/scans/acunetix/one_finding.xml") - parser = AcunetixParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertEqual(352, finding.cwe) - self.assertEqual(datetime.date(2018, 9, 24), finding.date) - self.assertIsNotNone(finding.description) - self.assertGreater(len(finding.description), 0) - self.assertFalse(finding.false_p) - self.assertEqual("Vijay Test Imapact", finding.impact) - self.assertIsNotNone(finding.references) - self.assertGreater(len(finding.references), 0) - self.assertEqual(1, len(finding.unsaved_endpoints)) - # check endpoints - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual('https', endpoint.protocol) - self.assertEqual(443, endpoint.port) - self.assertEqual('vijaytest.com', endpoint.host) - self.assertEqual('some/path', endpoint.path) + with open("unittests/scans/acunetix/one_finding.xml") as testfile: + parser = AcunetixParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertEqual(352, finding.cwe) + self.assertEqual(datetime.date(2018, 9, 24), finding.date) + self.assertIsNotNone(finding.description) + self.assertGreater(len(finding.description), 0) + self.assertFalse(finding.false_p) + self.assertEqual("Vijay Test Imapact", finding.impact) + self.assertIsNotNone(finding.references) + self.assertGreater(len(finding.references), 0) + self.assertEqual(1, len(finding.unsaved_endpoints)) + # check endpoints + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual('https', endpoint.protocol) + self.assertEqual(443, endpoint.port) + self.assertEqual('vijaytest.com', endpoint.host) + self.assertEqual('some/path', endpoint.path) def test_parse_file_with_multiple_finding(self): - testfile = open("unittests/scans/acunetix/many_findings.xml") - parser = AcunetixParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(4, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertEqual(datetime.date(2020, 2, 27), finding.date) - self.assertIsNotNone(finding.description) - self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L", finding.cvssv3) - self.assertFalse(finding.false_p) - self.assertEqual("A single machine can take down another machine's web server with minimal bandwidth and side effects on unrelated services and ports.", finding.impact) - # check that this finding have references - self.assertIsNotNone(finding.references) - self.assertGreater(len(finding.references), 0) - # check endpoints - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertIsNone(endpoint.protocol) - self.assertIsNone(endpoint.port) - self.assertEqual('www.itsecgames.com', endpoint.host) - self.assertIsNone(endpoint.path) - # check req/resp - self.assertEqual(1, len(finding.unsaved_req_resp)) - req_resp = finding.unsaved_req_resp[0] - self.assertIn('req', req_resp) - self.assertIsNotNone(req_resp['req']) - self.assertIsInstance(req_resp['req'], str) - self.assertIn('resp', req_resp) - self.assertIsNotNone(req_resp['resp']) - self.assertIsInstance(req_resp['resp'], str) + with open("unittests/scans/acunetix/many_findings.xml") as testfile: + parser = AcunetixParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(4, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertEqual(datetime.date(2020, 2, 27), finding.date) + self.assertIsNotNone(finding.description) + self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L", finding.cvssv3) + self.assertFalse(finding.false_p) + self.assertEqual("A single machine can take down another machine's web server with minimal bandwidth and side effects on unrelated services and ports.", finding.impact) + # check that this finding have references + self.assertIsNotNone(finding.references) + self.assertGreater(len(finding.references), 0) + # check endpoints + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertIsNone(endpoint.protocol) + self.assertIsNone(endpoint.port) + self.assertEqual('www.itsecgames.com', endpoint.host) + self.assertIsNone(endpoint.path) + # check req/resp + self.assertEqual(1, len(finding.unsaved_req_resp)) + req_resp = finding.unsaved_req_resp[0] + self.assertIn('req', req_resp) + self.assertIsNotNone(req_resp['req']) + self.assertIsInstance(req_resp['req'], str) + self.assertIn('resp', req_resp) + self.assertIsNotNone(req_resp['resp']) + self.assertIsInstance(req_resp['resp'], str) - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("Possible virtual host found", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(200, finding.cwe) - self.assertEqual(datetime.date(2020, 2, 27), finding.date) - self.assertIsNotNone(finding.description) - self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N", finding.cvssv3) - self.assertFalse(finding.false_p) - self.assertEqual("Possible sensitive information disclosure.", finding.impact) - # check that this finding have references - self.assertIsNotNone(finding.references) - self.assertGreater(len(finding.references), 0) - # check endpoints - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertIsNone(endpoint.protocol) - self.assertIsNone(endpoint.port) - self.assertEqual('www.itsecgames.com', endpoint.host) - self.assertIsNone(endpoint.path) - # check req/resp - self.assertEqual(1, len(finding.unsaved_req_resp)) - req_resp = finding.unsaved_req_resp[0] - self.assertIn('req', req_resp) - self.assertIsNotNone(req_resp['req']) - self.assertIsInstance(req_resp['req'], str) - self.assertIn('resp', req_resp) - self.assertIsNotNone(req_resp['resp']) - self.assertIsInstance(req_resp['resp'], str) + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("Possible virtual host found", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(200, finding.cwe) + self.assertEqual(datetime.date(2020, 2, 27), finding.date) + self.assertIsNotNone(finding.description) + self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N", finding.cvssv3) + self.assertFalse(finding.false_p) + self.assertEqual("Possible sensitive information disclosure.", finding.impact) + # check that this finding have references + self.assertIsNotNone(finding.references) + self.assertGreater(len(finding.references), 0) + # check endpoints + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertIsNone(endpoint.protocol) + self.assertIsNone(endpoint.port) + self.assertEqual('www.itsecgames.com', endpoint.host) + self.assertIsNone(endpoint.path) + # check req/resp + self.assertEqual(1, len(finding.unsaved_req_resp)) + req_resp = finding.unsaved_req_resp[0] + self.assertIn('req', req_resp) + self.assertIsNotNone(req_resp['req']) + self.assertIsInstance(req_resp['req'], str) + self.assertIn('resp', req_resp) + self.assertIsNotNone(req_resp['resp']) + self.assertIsInstance(req_resp['resp'], str) - with self.subTest(i=2): - finding = findings[2] - self.assertEqual("Unencrypted connection (verified)", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(310, finding.cwe) - self.assertEqual(datetime.date(2020, 2, 27), finding.date) - self.assertIsNotNone(finding.description) - self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N", finding.cvssv3) - self.assertFalse(finding.false_p) - self.assertEqual("Possible information disclosure.", finding.impact) - # check that this finding have no references - self.assertIsNone(finding.references) - # check endpoints - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertIsNone(endpoint.protocol) - self.assertIsNone(endpoint.port) - self.assertEqual('www.itsecgames.com', endpoint.host) - self.assertIsNone(endpoint.path) - # check req/resp - self.assertEqual(1, len(finding.unsaved_req_resp)) - req_resp = finding.unsaved_req_resp[0] - self.assertIn('req', req_resp) - self.assertIsNotNone(req_resp['req']) - self.assertIsInstance(req_resp['req'], str) - self.assertIn('resp', req_resp) - self.assertIsNotNone(req_resp['resp']) - self.assertIsInstance(req_resp['resp'], str) + with self.subTest(i=2): + finding = findings[2] + self.assertEqual("Unencrypted connection (verified)", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(310, finding.cwe) + self.assertEqual(datetime.date(2020, 2, 27), finding.date) + self.assertIsNotNone(finding.description) + self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N", finding.cvssv3) + self.assertFalse(finding.false_p) + self.assertEqual("Possible information disclosure.", finding.impact) + # check that this finding have no references + self.assertIsNone(finding.references) + # check endpoints + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertIsNone(endpoint.protocol) + self.assertIsNone(endpoint.port) + self.assertEqual('www.itsecgames.com', endpoint.host) + self.assertIsNone(endpoint.path) + # check req/resp + self.assertEqual(1, len(finding.unsaved_req_resp)) + req_resp = finding.unsaved_req_resp[0] + self.assertIn('req', req_resp) + self.assertIsNotNone(req_resp['req']) + self.assertIsInstance(req_resp['req'], str) + self.assertIn('resp', req_resp) + self.assertIsNotNone(req_resp['resp']) + self.assertIsInstance(req_resp['resp'], str) def test_parse_file_with_example_com(self): - testfile = open("unittests/scans/acunetix/XML_http_example_co_id_.xml") - parser = AcunetixParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(7, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("HTML form without CSRF protection", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertEqual(datetime.date(2020, 4, 28), finding.date) - self.assertIsNotNone(finding.description) - self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N", finding.cvssv3) - self.assertFalse(finding.false_p) - self.assertIn("An attacker could use CSRF to trick a victim into accessing a website hosted by the attacker,", finding.impact) - # aggregated - self.assertEqual(3, finding.nb_occurences) - # check that this finding have references - self.assertIsNotNone(finding.references) - self.assertGreater(len(finding.references), 0) - # check endpoints - self.assertEqual(3, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertIsNone(endpoint.protocol) - self.assertIsNone(endpoint.port) - self.assertEqual('example.co.id', endpoint.host) - self.assertEqual('h/search', endpoint.path) - endpoint = finding.unsaved_endpoints[1] - self.assertIsNone(endpoint.protocol) - self.assertIsNone(endpoint.port) - self.assertEqual('example.co.id', endpoint.host) - self.assertEqual('m/zmain', endpoint.path) - # check req/resp - self.assertEqual(3, len(finding.unsaved_req_resp)) - for req_resp in finding.unsaved_req_resp: + with open("unittests/scans/acunetix/XML_http_example_co_id_.xml") as testfile: + parser = AcunetixParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(7, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("HTML form without CSRF protection", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertEqual(datetime.date(2020, 4, 28), finding.date) + self.assertIsNotNone(finding.description) + self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N", finding.cvssv3) + self.assertFalse(finding.false_p) + self.assertIn("An attacker could use CSRF to trick a victim into accessing a website hosted by the attacker,", finding.impact) + # aggregated + self.assertEqual(3, finding.nb_occurences) + # check that this finding have references + self.assertIsNotNone(finding.references) + self.assertGreater(len(finding.references), 0) + # check endpoints + self.assertEqual(3, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertIsNone(endpoint.protocol) + self.assertIsNone(endpoint.port) + self.assertEqual('example.co.id', endpoint.host) + self.assertEqual('h/search', endpoint.path) + endpoint = finding.unsaved_endpoints[1] + self.assertIsNone(endpoint.protocol) + self.assertIsNone(endpoint.port) + self.assertEqual('example.co.id', endpoint.host) + self.assertEqual('m/zmain', endpoint.path) + # check req/resp + self.assertEqual(3, len(finding.unsaved_req_resp)) + for req_resp in finding.unsaved_req_resp: + self.assertIn('req', req_resp) + self.assertIsNotNone(req_resp['req']) + self.assertIsInstance(req_resp['req'], str) + self.assertIn('resp', req_resp) + self.assertIsNotNone(req_resp['resp']) + self.assertIsInstance(req_resp['resp'], str) + + with self.subTest(i=6): + finding = findings[6] + self.assertEqual("Content Security Policy (CSP) not implemented", finding.title) + self.assertEqual("Info", finding.severity) + self.assertEqual(datetime.date(2020, 4, 28), finding.date) + self.assertIsNotNone(finding.description) + self.assertFalse(finding.false_p) + self.assertIn("CSP can be used to prevent and/or mitigate attacks that involve content/code injection,", finding.impact) + # check that this finding have references + self.assertIsNotNone(finding.references) + self.assertGreater(len(finding.references), 0) + # check endpoints + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertIsNone(endpoint.protocol) + self.assertIsNone(endpoint.port) + self.assertEqual('example.co.id', endpoint.host) + self.assertIsNone(endpoint.path) + # check req/resp + self.assertEqual(1, len(finding.unsaved_req_resp)) + req_resp = finding.unsaved_req_resp[0] self.assertIn('req', req_resp) self.assertIsNotNone(req_resp['req']) self.assertIsInstance(req_resp['req'], str) @@ -174,151 +202,123 @@ def test_parse_file_with_example_com(self): self.assertIsNotNone(req_resp['resp']) self.assertIsInstance(req_resp['resp'], str) - with self.subTest(i=6): - finding = findings[6] - self.assertEqual("Content Security Policy (CSP) not implemented", finding.title) - self.assertEqual("Info", finding.severity) - self.assertEqual(datetime.date(2020, 4, 28), finding.date) - self.assertIsNotNone(finding.description) - self.assertFalse(finding.false_p) - self.assertIn("CSP can be used to prevent and/or mitigate attacks that involve content/code injection,", finding.impact) - # check that this finding have references - self.assertIsNotNone(finding.references) - self.assertGreater(len(finding.references), 0) - # check endpoints - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertIsNone(endpoint.protocol) - self.assertIsNone(endpoint.port) - self.assertEqual('example.co.id', endpoint.host) - self.assertIsNone(endpoint.path) - # check req/resp - self.assertEqual(1, len(finding.unsaved_req_resp)) - req_resp = finding.unsaved_req_resp[0] - self.assertIn('req', req_resp) - self.assertIsNotNone(req_resp['req']) - self.assertIsInstance(req_resp['req'], str) - self.assertIn('resp', req_resp) - self.assertIsNotNone(req_resp['resp']) - self.assertIsInstance(req_resp['resp'], str) - def test_parse_file_with_one_finding_acunetix360(self): - testfile = open("unittests/scans/acunetix/acunetix360_one_finding.json") - parser = AcunetixParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertEqual(16, finding.cwe) - self.assertIsNotNone(finding.description) - self.assertGreater(len(finding.description), 0) - self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N/E:H/RL:O/RC:C", finding.cvssv3) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(str(endpoint), "http://php.testsparker.com/auth/login.php") - self.assertEqual(finding.date, date(2021, 6, 16, 12, 30)) - self.assertIn("https://online.acunetix360.com/issues/detail/735f4503-e9eb-4b4c-4306-ad49020a4c4b", finding.references) + with open("unittests/scans/acunetix/acunetix360_one_finding.json") as testfile: + parser = AcunetixParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertEqual(16, finding.cwe) + self.assertIsNotNone(finding.description) + self.assertGreater(len(finding.description), 0) + self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N/E:H/RL:O/RC:C", finding.cvssv3) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(str(endpoint), "http://php.testsparker.com/auth/login.php") + self.assertEqual(finding.date, date(2021, 6, 16, 12, 30)) + self.assertIn("https://online.acunetix360.com/issues/detail/735f4503-e9eb-4b4c-4306-ad49020a4c4b", finding.references) def test_parse_file_with_one_finding_false_positive(self): - testfile = open("unittests/scans/acunetix/acunetix360_one_finding_false_positive.json") - parser = AcunetixParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertEqual(16, finding.cwe) - self.assertIsNotNone(finding.description) - self.assertGreater(len(finding.description), 0) - self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N/E:H/RL:O/RC:C", finding.cvssv3) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(str(endpoint), "http://php.testsparker.com/auth/login.php") - self.assertTrue(finding.false_p) + with open("unittests/scans/acunetix/acunetix360_one_finding_false_positive.json") as testfile: + parser = AcunetixParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertEqual(16, finding.cwe) + self.assertIsNotNone(finding.description) + self.assertGreater(len(finding.description), 0) + self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N/E:H/RL:O/RC:C", finding.cvssv3) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(str(endpoint), "http://php.testsparker.com/auth/login.php") + self.assertTrue(finding.false_p) def test_parse_file_with_one_finding_risk_accepted(self): - testfile = open("unittests/scans/acunetix/acunetix360_one_finding_accepted_risk.json") - parser = AcunetixParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertEqual(16, finding.cwe) - self.assertIsNotNone(finding.description) - self.assertGreater(len(finding.description), 0) - self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N/E:H/RL:O/RC:C", finding.cvssv3) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(str(endpoint), "http://php.testsparker.com/auth/login.php") - self.assertTrue(finding.risk_accepted) + with open("unittests/scans/acunetix/acunetix360_one_finding_accepted_risk.json") as testfile: + parser = AcunetixParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertEqual(16, finding.cwe) + self.assertIsNotNone(finding.description) + self.assertGreater(len(finding.description), 0) + self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N/E:H/RL:O/RC:C", finding.cvssv3) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(str(endpoint), "http://php.testsparker.com/auth/login.php") + self.assertTrue(finding.risk_accepted) def test_parse_file_with_multiple_finding_acunetix360(self): - testfile = open("unittests/scans/acunetix/acunetix360_many_findings.json") - parser = AcunetixParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(16, len(findings)) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertEqual(16, finding.cwe) - self.assertIsNotNone(finding.description) - self.assertGreater(len(finding.description), 0) - self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N/E:H/RL:O/RC:C", finding.cvssv3) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(str(endpoint), "http://php.testsparker.com/auth/login.php") + with open("unittests/scans/acunetix/acunetix360_many_findings.json") as testfile: + parser = AcunetixParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(16, len(findings)) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertEqual(16, finding.cwe) + self.assertIsNotNone(finding.description) + self.assertGreater(len(finding.description), 0) + self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N/E:H/RL:O/RC:C", finding.cvssv3) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(str(endpoint), "http://php.testsparker.com/auth/login.php") - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("Critical", finding.severity) - self.assertEqual(89, finding.cwe) - self.assertIsNotNone(finding.description) - self.assertGreater(len(finding.description), 0) - self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", finding.cvssv3) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(str(endpoint), "http://php.testsparker.com/artist.php?id=-1%20OR%2017-7=10") + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("Critical", finding.severity) + self.assertEqual(89, finding.cwe) + self.assertIsNotNone(finding.description) + self.assertGreater(len(finding.description), 0) + self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", finding.cvssv3) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(str(endpoint), "http://php.testsparker.com/artist.php?id=-1%20OR%2017-7=10") - with self.subTest(i=2): - finding = findings[2] - self.assertEqual("Medium", finding.severity) - self.assertEqual(205, finding.cwe) - self.assertIsNotNone(finding.description) - self.assertGreater(len(finding.description), 0) - self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N/E:H/RL:O/RC:C", finding.cvssv3) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(str(endpoint), "http://php.testsparker.com") + with self.subTest(i=2): + finding = findings[2] + self.assertEqual("Medium", finding.severity) + self.assertEqual(205, finding.cwe) + self.assertIsNotNone(finding.description) + self.assertGreater(len(finding.description), 0) + self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N/E:H/RL:O/RC:C", finding.cvssv3) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(str(endpoint), "http://php.testsparker.com") def test_parse_file_with_mulitple_cwe(self): - testfile = open("unittests/scans/acunetix/acunetix360_multiple_cwe.json") - parser = AcunetixParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertEqual(16, finding.cwe) - self.assertIsNotNone(finding.description) - self.assertGreater(len(finding.description), 0) - self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N/E:H/RL:O/RC:C", finding.cvssv3) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(str(endpoint), "http://php.testsparker.com/auth/login.php") + with open("unittests/scans/acunetix/acunetix360_multiple_cwe.json") as testfile: + parser = AcunetixParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertEqual(16, finding.cwe) + self.assertIsNotNone(finding.description) + self.assertGreater(len(finding.description), 0) + self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N/E:H/RL:O/RC:C", finding.cvssv3) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(str(endpoint), "http://php.testsparker.com/auth/login.php") diff --git a/unittests/tools/test_anchore_engine_parser.py b/unittests/tools/test_anchore_engine_parser.py index 3d21797b2c..9407ac2e8b 100644 --- a/unittests/tools/test_anchore_engine_parser.py +++ b/unittests/tools/test_anchore_engine_parser.py @@ -5,35 +5,32 @@ class TestAnchoreEngineParser(DojoTestCase): def test_anchore_engine_parser_has_no_finding(self): - testfile = open("unittests/scans/anchore_engine/no_vuln.json") - parser = AnchoreEngineParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/anchore_engine/no_vuln.json") as testfile: + parser = AnchoreEngineParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_anchore_engine_parser_has_one_finding(self): - testfile = open("unittests/scans/anchore_engine/one_vuln.json") - parser = AnchoreEngineParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1, len(findings)) + with open("unittests/scans/anchore_engine/one_vuln.json") as testfile: + parser = AnchoreEngineParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) def test_anchore_engine_parser_has_many_findings(self): - testfile = open("unittests/scans/anchore_engine/many_vulns.json") - parser = AnchoreEngineParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(23, len(findings)) + with open("unittests/scans/anchore_engine/many_vulns.json") as testfile: + parser = AnchoreEngineParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(23, len(findings)) def test_anchore_engine_parser_has_many_findings_2_4_1(self): - testfile = open("unittests/scans/anchore_engine/many_vulns_2.4.1.json") - parser = AnchoreEngineParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(51, len(findings)) - finding = findings[50] - self.assertEqual("CVE-2020-13776", finding.vuln_id_from_tool) - self.assertEqual('systemd-pam', finding.component_name) - self.assertEqual('239-41.el8_3.1', finding.component_version) - self.assertEqual(6.7, finding.cvssv3_score) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2020-13776", finding.unsaved_vulnerability_ids[0]) + with open("unittests/scans/anchore_engine/many_vulns_2.4.1.json") as testfile: + parser = AnchoreEngineParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(51, len(findings)) + finding = findings[50] + self.assertEqual("CVE-2020-13776", finding.vuln_id_from_tool) + self.assertEqual('systemd-pam', finding.component_name) + self.assertEqual('239-41.el8_3.1', finding.component_version) + self.assertEqual(6.7, finding.cvssv3_score) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2020-13776", finding.unsaved_vulnerability_ids[0]) diff --git a/unittests/tools/test_anchore_grype_parser.py b/unittests/tools/test_anchore_grype_parser.py index 668035b68c..67f1072d5b 100644 --- a/unittests/tools/test_anchore_grype_parser.py +++ b/unittests/tools/test_anchore_grype_parser.py @@ -7,125 +7,119 @@ class TestAnchoreGrypeParser(DojoTestCase): def test_parser_has_no_findings(self): - testfile = open("unittests/scans/anchore_grype/no_vuln.json") - parser = AnchoreGrypeParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(0, len(findings)) + with open("unittests/scans/anchore_grype/no_vuln.json") as testfile: + parser = AnchoreGrypeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parser_has_many_findings(self): found = False - testfile = open("unittests/scans/anchore_grype/many_vulns.json") - parser = AnchoreGrypeParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1509, len(findings)) - for finding in findings: - self.assertIn(finding.severity, Finding.SEVERITIES) - vulnerability_ids = finding.unsaved_vulnerability_ids - self.assertGreaterEqual(len(vulnerability_ids), 1) - if finding.vuln_id_from_tool == "CVE-2011-3389": + with open("unittests/scans/anchore_grype/many_vulns.json") as testfile: + parser = AnchoreGrypeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1509, len(findings)) + for finding in findings: + self.assertIn(finding.severity, Finding.SEVERITIES) vulnerability_ids = finding.unsaved_vulnerability_ids - self.assertEqual(1, len(vulnerability_ids)) - self.assertEqual('CVE-2011-3389', vulnerability_ids[0]) - self.assertEqual("Medium", finding.severity) - self.assertEqual("libgnutls-openssl27", finding.component_name) - self.assertEqual("3.6.7-4+deb10u5", finding.component_version) - self.assertEqual("/var/lib/dpkg/status", finding.file_path) - found = True - break - self.assertTrue(found) + self.assertGreaterEqual(len(vulnerability_ids), 1) + if finding.vuln_id_from_tool == "CVE-2011-3389": + vulnerability_ids = finding.unsaved_vulnerability_ids + self.assertEqual(1, len(vulnerability_ids)) + self.assertEqual('CVE-2011-3389', vulnerability_ids[0]) + self.assertEqual("Medium", finding.severity) + self.assertEqual("libgnutls-openssl27", finding.component_name) + self.assertEqual("3.6.7-4+deb10u5", finding.component_version) + self.assertEqual("/var/lib/dpkg/status", finding.file_path) + found = True + break + self.assertTrue(found) def test_grype_parser_with_one_criticle_vuln_has_one_findings(self): found = False - testfile = open("unittests/scans/anchore_grype/many_vulns2.json") - parser = AnchoreGrypeParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1567, len(findings)) - for finding in findings: - self.assertIn(finding.severity, Finding.SEVERITIES) - vulnerability_ids = finding.unsaved_vulnerability_ids - self.assertGreaterEqual(len(vulnerability_ids), 1) - if finding.vuln_id_from_tool == "CVE-2019-9192": + with open("unittests/scans/anchore_grype/many_vulns2.json") as testfile: + parser = AnchoreGrypeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1567, len(findings)) + for finding in findings: + self.assertIn(finding.severity, Finding.SEVERITIES) vulnerability_ids = finding.unsaved_vulnerability_ids - self.assertEqual(1, len(vulnerability_ids)) - self.assertEqual('CVE-2019-9192', vulnerability_ids[0]) - self.assertEqual("libc6-dev", finding.component_name) - self.assertEqual("2.28-10", finding.component_version) - self.assertEqual("Info", finding.severity) - found = True - break - self.assertTrue(found) + self.assertGreaterEqual(len(vulnerability_ids), 1) + if finding.vuln_id_from_tool == "CVE-2019-9192": + vulnerability_ids = finding.unsaved_vulnerability_ids + self.assertEqual(1, len(vulnerability_ids)) + self.assertEqual('CVE-2019-9192', vulnerability_ids[0]) + self.assertEqual("libc6-dev", finding.component_name) + self.assertEqual("2.28-10", finding.component_version) + self.assertEqual("Info", finding.severity) + found = True + break + self.assertTrue(found) def test_grype_parser_with_many_vulns3(self): found = False - testfile = open("unittests/scans/anchore_grype/many_vulns3.json") - parser = AnchoreGrypeParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(327, len(findings)) - for finding in findings: - self.assertIn(finding.severity, Finding.SEVERITIES) - vulnerability_ids = finding.unsaved_vulnerability_ids - self.assertGreaterEqual(len(vulnerability_ids), 1) - if finding.vuln_id_from_tool == "CVE-2011-3389": + with open("unittests/scans/anchore_grype/many_vulns3.json") as testfile: + parser = AnchoreGrypeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(327, len(findings)) + for finding in findings: + self.assertIn(finding.severity, Finding.SEVERITIES) vulnerability_ids = finding.unsaved_vulnerability_ids - self.assertEqual(1, len(vulnerability_ids)) - self.assertEqual('CVE-2011-3389', vulnerability_ids[0]) - self.assertEqual("Medium", finding.severity) - self.assertEqual("libgnutls30", finding.component_name) - self.assertEqual("3.6.7-4+deb10u5", finding.component_version) - found = True - break - self.assertTrue(found) + self.assertGreaterEqual(len(vulnerability_ids), 1) + if finding.vuln_id_from_tool == "CVE-2011-3389": + vulnerability_ids = finding.unsaved_vulnerability_ids + self.assertEqual(1, len(vulnerability_ids)) + self.assertEqual('CVE-2011-3389', vulnerability_ids[0]) + self.assertEqual("Medium", finding.severity) + self.assertEqual("libgnutls30", finding.component_name) + self.assertEqual("3.6.7-4+deb10u5", finding.component_version) + found = True + break + self.assertTrue(found) def test_grype_parser_with_new_matcher_list(self): found = False - testfile = open("unittests/scans/anchore_grype/many_vulns4.json") - parser = AnchoreGrypeParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(9, len(findings)) - for finding in findings: - self.assertIn(finding.severity, Finding.SEVERITIES) - vulnerability_ids = finding.unsaved_vulnerability_ids - self.assertGreaterEqual(len(vulnerability_ids), 1) - if finding.vuln_id_from_tool == "CVE-1999-1338": + with open("unittests/scans/anchore_grype/many_vulns4.json") as testfile: + parser = AnchoreGrypeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(9, len(findings)) + for finding in findings: + self.assertIn(finding.severity, Finding.SEVERITIES) vulnerability_ids = finding.unsaved_vulnerability_ids - self.assertEqual(1, len(vulnerability_ids)) - self.assertEqual('CVE-1999-1338', vulnerability_ids[0]) - self.assertEqual("Medium", finding.severity) - self.assertIn("javascript-matcher", finding.description) - self.assertEqual("delegate", finding.component_name) - self.assertEqual("3.2.0", finding.component_version) - found = True - self.assertTrue(found) + self.assertGreaterEqual(len(vulnerability_ids), 1) + if finding.vuln_id_from_tool == "CVE-1999-1338": + vulnerability_ids = finding.unsaved_vulnerability_ids + self.assertEqual(1, len(vulnerability_ids)) + self.assertEqual('CVE-1999-1338', vulnerability_ids[0]) + self.assertEqual("Medium", finding.severity) + self.assertIn("javascript-matcher", finding.description) + self.assertEqual("delegate", finding.component_name) + self.assertEqual("3.2.0", finding.component_version) + found = True + self.assertTrue(found) def test_check_all_fields(self): - testfile = open("unittests/scans/anchore_grype/check_all_fields.json") - parser = AnchoreGrypeParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(5, len(findings)) + with open("unittests/scans/anchore_grype/check_all_fields.json") as testfile: + parser = AnchoreGrypeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(5, len(findings)) - finding = findings[0] - self.assertEqual('CVE-2004-0971 in libgssapi-krb5-2:1.17-3+deb10u3', finding.title) - description = '''**Vulnerability Namespace:** debian:10 + finding = findings[0] + self.assertEqual('CVE-2004-0971 in libgssapi-krb5-2:1.17-3+deb10u3', finding.title) + description = '''**Vulnerability Namespace:** debian:10 **Related Vulnerability Description:** The krb5-send-pr script in the kerberos5 (krb5) package in Trustix Secure Linux 1.5 through 2.1, and possibly other operating systems, allows local users to overwrite files via a symlink attack on temporary files. **Matcher:** dpkg-matcher **Package URL:** pkg:deb/debian/libgssapi-krb5-2@1.17-3+deb10u3?arch=amd64''' - self.assertEqual(description, finding.description) - vulnerability_ids = finding.unsaved_vulnerability_ids - self.assertEqual(2, len(vulnerability_ids)) - self.assertEqual('CVE-2004-0971', vulnerability_ids[0]) - self.assertEqual('CVE-2004-0971', vulnerability_ids[1]) - self.assertEqual(1352, finding.cwe) - self.assertIsNone(finding.cvssv3) - self.assertIsNone(finding.cvssv3_score) - self.assertEqual('Info', finding.severity) - self.assertIsNone(finding.mitigation) - references = '''**Vulnerability Datasource:** https://security-tracker.debian.org/tracker/CVE-2004-0971 + self.assertEqual(description, finding.description) + vulnerability_ids = finding.unsaved_vulnerability_ids + self.assertEqual(2, len(vulnerability_ids)) + self.assertEqual('CVE-2004-0971', vulnerability_ids[0]) + self.assertEqual('CVE-2004-0971', vulnerability_ids[1]) + self.assertEqual(1352, finding.cwe) + self.assertIsNone(finding.cvssv3) + self.assertIsNone(finding.cvssv3_score) + self.assertEqual('Info', finding.severity) + self.assertIsNone(finding.mitigation) + references = '''**Vulnerability Datasource:** https://security-tracker.debian.org/tracker/CVE-2004-0971 **Related Vulnerability Datasource:** https://nvd.nist.gov/vuln/detail/CVE-2004-0971 **Related Vulnerability URLs:** - http://www.securityfocus.com/bid/11289 @@ -136,33 +130,33 @@ def test_check_all_fields(self): - https://exchange.xforce.ibmcloud.com/vulnerabilities/17583 - https://oval.cisecurity.org/repository/search/definition/oval%3Aorg.mitre.oval%3Adef%3A10497 - https://lists.apache.org/thread.html/rc713534b10f9daeee2e0990239fa407e2118e4aa9e88a7041177497c@%3Cissues.guacamole.apache.org%3E''' - self.assertEqual(references, finding.references) - self.assertEqual('libgssapi-krb5-2', finding.component_name) - self.assertEqual('1.17-3+deb10u3', finding.component_version) - self.assertEqual('CVE-2004-0971', finding.vuln_id_from_tool) - self.assertEqual(['dpkg'], finding.tags) - self.assertEqual(1, finding.nb_occurences) + self.assertEqual(references, finding.references) + self.assertEqual('libgssapi-krb5-2', finding.component_name) + self.assertEqual('1.17-3+deb10u3', finding.component_version) + self.assertEqual('CVE-2004-0971', finding.vuln_id_from_tool) + self.assertEqual(['dpkg'], finding.tags) + self.assertEqual(1, finding.nb_occurences) - finding = findings[1] - self.assertEqual('CVE-2021-32626 in redis:4.0.2', finding.title) - description = '''**Vulnerability Namespace:** nvd + finding = findings[1] + self.assertEqual('CVE-2021-32626 in redis:4.0.2', finding.title) + description = '''**Vulnerability Namespace:** nvd **Vulnerability Description:** Redis is an open source, in-memory database that persists on disk. In affected versions specially crafted Lua scripts executing in Redis can cause the heap-based Lua stack to be overflowed, due to incomplete checks for this condition. This can result with heap corruption and potentially remote code execution. This problem exists in all versions of Redis with Lua scripting support, starting from 2.6. The problem is fixed in versions 6.2.6, 6.0.16 and 5.0.14. For users unable to update an additional workaround to mitigate the problem without patching the redis-server executable is to prevent users from executing Lua scripts. This can be done using ACL to restrict EVAL and EVALSHA commands. **Matchers:** - python-matcher - python2-matcher **Package URL:** pkg:pypi/redis@4.0.2''' - self.assertEqual(description, finding.description) - vulnerability_ids = finding.unsaved_vulnerability_ids - self.assertEqual(1, len(vulnerability_ids)) - self.assertEqual('CVE-2021-32626', vulnerability_ids[0]) - self.assertEqual(1352, finding.cwe) - self.assertEqual('CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H', finding.cvssv3) - self.assertEqual('High', finding.severity) - mitigation = '''Upgrade to version: + self.assertEqual(description, finding.description) + vulnerability_ids = finding.unsaved_vulnerability_ids + self.assertEqual(1, len(vulnerability_ids)) + self.assertEqual('CVE-2021-32626', vulnerability_ids[0]) + self.assertEqual(1352, finding.cwe) + self.assertEqual('CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H', finding.cvssv3) + self.assertEqual('High', finding.severity) + mitigation = '''Upgrade to version: - fix_1 - fix_2''' - self.assertEqual(mitigation, finding.mitigation) - references = '''**Vulnerability Datasource:** https://nvd.nist.gov/vuln/detail/CVE-2021-32626 + self.assertEqual(mitigation, finding.mitigation) + references = '''**Vulnerability Datasource:** https://nvd.nist.gov/vuln/detail/CVE-2021-32626 **Vulnerability URLs:** - https://github.com/redis/redis/commit/666ed7facf4524bf6d19b11b20faa2cf93fdf591 - https://github.com/redis/redis/security/advisories/GHSA-p486-xggp-782c @@ -172,29 +166,29 @@ def test_check_all_fields(self): - https://security.netapp.com/advisory/ntap-20211104-0003/ - https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/WR5WKJWXD4D6S3DJCZ56V74ESLTDQRAB/ - https://www.debian.org/security/2021/dsa-5001''' - self.assertEqual(references, finding.references) - self.assertEqual('redis', finding.component_name) - self.assertEqual('4.0.2', finding.component_version) - self.assertEqual('CVE-2021-32626', finding.vuln_id_from_tool) - self.assertEqual(['python', 'python2'], finding.tags) - self.assertEqual(1, finding.nb_occurences) + self.assertEqual(references, finding.references) + self.assertEqual('redis', finding.component_name) + self.assertEqual('4.0.2', finding.component_version) + self.assertEqual('CVE-2021-32626', finding.vuln_id_from_tool) + self.assertEqual(['python', 'python2'], finding.tags) + self.assertEqual(1, finding.nb_occurences) - finding = findings[2] - self.assertEqual('CVE-2021-33574 in libc-bin:2.28-10', finding.title) - description = '''**Vulnerability Namespace:** debian:10 + finding = findings[2] + self.assertEqual('CVE-2021-33574 in libc-bin:2.28-10', finding.title) + description = '''**Vulnerability Namespace:** debian:10 **Related Vulnerability Description:** The mq_notify function in the GNU C Library (aka glibc) versions 2.32 and 2.33 has a use-after-free. It may use the notification thread attributes object (passed through its struct sigevent parameter) after it has been freed by the caller, leading to a denial of service (application crash) or possibly unspecified other impact. **Matcher:** dpkg-matcher **Package URL:** pkg:deb/debian/libc-bin@2.28-10?arch=amd64''' - self.assertEqual(description, finding.description) - vulnerability_ids = finding.unsaved_vulnerability_ids - self.assertEqual(2, len(vulnerability_ids)) - self.assertEqual('CVE-2021-33574', vulnerability_ids[0]) - self.assertEqual('CVE-2021-33574', vulnerability_ids[1]) - self.assertEqual(1352, finding.cwe) - self.assertEqual('CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H', finding.cvssv3) - self.assertEqual('Critical', finding.severity) - self.assertIsNone(finding.mitigation) - references = '''**Vulnerability Datasource:** https://security-tracker.debian.org/tracker/CVE-2021-33574 + self.assertEqual(description, finding.description) + vulnerability_ids = finding.unsaved_vulnerability_ids + self.assertEqual(2, len(vulnerability_ids)) + self.assertEqual('CVE-2021-33574', vulnerability_ids[0]) + self.assertEqual('CVE-2021-33574', vulnerability_ids[1]) + self.assertEqual(1352, finding.cwe) + self.assertEqual('CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H', finding.cvssv3) + self.assertEqual('Critical', finding.severity) + self.assertIsNone(finding.mitigation) + references = '''**Vulnerability Datasource:** https://security-tracker.debian.org/tracker/CVE-2021-33574 **Related Vulnerability Datasource:** https://nvd.nist.gov/vuln/detail/CVE-2021-33574 **Related Vulnerability URLs:** - https://sourceware.org/bugzilla/show_bug.cgi?id=27896 @@ -203,29 +197,29 @@ def test_check_all_fields(self): - https://security.netapp.com/advisory/ntap-20210629-0005/ - https://security.gentoo.org/glsa/202107-07 - https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/KJYYIMDDYOHTP2PORLABTOHYQYYREZDD/''' - self.assertEqual(references, finding.references) - self.assertEqual('libc-bin', finding.component_name) - self.assertEqual('2.28-10', finding.component_version) - self.assertEqual('CVE-2021-33574', finding.vuln_id_from_tool) - self.assertEqual(['dpkg'], finding.tags) - self.assertEqual(1, finding.nb_occurences) + self.assertEqual(references, finding.references) + self.assertEqual('libc-bin', finding.component_name) + self.assertEqual('2.28-10', finding.component_version) + self.assertEqual('CVE-2021-33574', finding.vuln_id_from_tool) + self.assertEqual(['dpkg'], finding.tags) + self.assertEqual(1, finding.nb_occurences) - finding = findings[3] - self.assertEqual('CVE-2021-33574 in libc6:2.28-10', finding.title) - description = '''**Vulnerability Namespace:** debian:10 + finding = findings[3] + self.assertEqual('CVE-2021-33574 in libc6:2.28-10', finding.title) + description = '''**Vulnerability Namespace:** debian:10 **Related Vulnerability Description:** The mq_notify function in the GNU C Library (aka glibc) versions 2.32 and 2.33 has a use-after-free. It may use the notification thread attributes object (passed through its struct sigevent parameter) after it has been freed by the caller, leading to a denial of service (application crash) or possibly unspecified other impact. **Matcher:** dpkg-matcher **Package URL:** pkg:deb/debian/libc6@2.28-10?arch=amd64''' - self.assertEqual(description, finding.description) - vulnerability_ids = finding.unsaved_vulnerability_ids - self.assertEqual(2, len(vulnerability_ids)) - self.assertEqual('CVE-2021-33574', vulnerability_ids[0]) - self.assertEqual('CVE-2021-33574', vulnerability_ids[1]) - self.assertEqual(1352, finding.cwe) - self.assertEqual('CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H', finding.cvssv3) - self.assertEqual('Critical', finding.severity) - self.assertIsNone(finding.mitigation) - references = '''**Vulnerability Datasource:** https://security-tracker.debian.org/tracker/CVE-2021-33574 + self.assertEqual(description, finding.description) + vulnerability_ids = finding.unsaved_vulnerability_ids + self.assertEqual(2, len(vulnerability_ids)) + self.assertEqual('CVE-2021-33574', vulnerability_ids[0]) + self.assertEqual('CVE-2021-33574', vulnerability_ids[1]) + self.assertEqual(1352, finding.cwe) + self.assertEqual('CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H', finding.cvssv3) + self.assertEqual('Critical', finding.severity) + self.assertIsNone(finding.mitigation) + references = '''**Vulnerability Datasource:** https://security-tracker.debian.org/tracker/CVE-2021-33574 **Related Vulnerability Datasource:** https://nvd.nist.gov/vuln/detail/CVE-2021-33574 **Related Vulnerability URLs:** - https://sourceware.org/bugzilla/show_bug.cgi?id=27896 @@ -234,54 +228,52 @@ def test_check_all_fields(self): - https://security.netapp.com/advisory/ntap-20210629-0005/ - https://security.gentoo.org/glsa/202107-07 - https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/KJYYIMDDYOHTP2PORLABTOHYQYYREZDD/''' - self.assertEqual(references, finding.references) - self.assertEqual('libc6', finding.component_name) - self.assertEqual('2.28-10', finding.component_version) - self.assertEqual('CVE-2021-33574', finding.vuln_id_from_tool) - self.assertEqual(['dpkg'], finding.tags) - self.assertEqual(1, finding.nb_occurences) + self.assertEqual(references, finding.references) + self.assertEqual('libc6', finding.component_name) + self.assertEqual('2.28-10', finding.component_version) + self.assertEqual('CVE-2021-33574', finding.vuln_id_from_tool) + self.assertEqual(['dpkg'], finding.tags) + self.assertEqual(1, finding.nb_occurences) - finding = findings[4] - self.assertEqual('GHSA-v6rh-hp5x-86rv in Django:3.2.9', finding.title) - description = '''**Vulnerability Namespace:** github:python + finding = findings[4] + self.assertEqual('GHSA-v6rh-hp5x-86rv in Django:3.2.9', finding.title) + description = '''**Vulnerability Namespace:** github:python **Vulnerability Description:** Potential bypass of an upstream access control based on URL paths in Django **Related Vulnerability Description:** In Django 2.2 before 2.2.25, 3.1 before 3.1.14, and 3.2 before 3.2.10, HTTP requests for URLs with trailing newlines could bypass upstream access control based on URL paths. **Matcher:** python-matcher **Package URL:** pkg:pypi/Django@3.2.9''' - self.assertEqual(description, finding.description) - vulnerability_ids = finding.unsaved_vulnerability_ids - self.assertEqual(2, len(vulnerability_ids)) - self.assertEqual('GHSA-v6rh-hp5x-86rv', vulnerability_ids[0]) - self.assertEqual('CVE-2021-44420', vulnerability_ids[1]) - self.assertEqual(1352, finding.cwe) - self.assertEqual('CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L', finding.cvssv3) - self.assertEqual('High', finding.severity) - mitigation = 'Upgrade to version: 3.2.10' - self.assertEqual(mitigation, finding.mitigation) - references = '''**Vulnerability Datasource:** https://github.com/advisories/GHSA-v6rh-hp5x-86rv + self.assertEqual(description, finding.description) + vulnerability_ids = finding.unsaved_vulnerability_ids + self.assertEqual(2, len(vulnerability_ids)) + self.assertEqual('GHSA-v6rh-hp5x-86rv', vulnerability_ids[0]) + self.assertEqual('CVE-2021-44420', vulnerability_ids[1]) + self.assertEqual(1352, finding.cwe) + self.assertEqual('CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L', finding.cvssv3) + self.assertEqual('High', finding.severity) + mitigation = 'Upgrade to version: 3.2.10' + self.assertEqual(mitigation, finding.mitigation) + references = '''**Vulnerability Datasource:** https://github.com/advisories/GHSA-v6rh-hp5x-86rv **Related Vulnerability Datasource:** https://nvd.nist.gov/vuln/detail/CVE-2021-44420 **Related Vulnerability URLs:** - https://docs.djangoproject.com/en/3.2/releases/security/ - https://www.openwall.com/lists/oss-security/2021/12/07/1 - https://www.djangoproject.com/weblog/2021/dec/07/security-releases/ - https://groups.google.com/forum/#!forum/django-announce''' - self.assertEqual(references, finding.references) - self.assertEqual('Django', finding.component_name) - self.assertEqual('3.2.9', finding.component_version) - self.assertEqual('GHSA-v6rh-hp5x-86rv', finding.vuln_id_from_tool) - self.assertEqual(['python'], finding.tags) - self.assertEqual(2, finding.nb_occurences) + self.assertEqual(references, finding.references) + self.assertEqual('Django', finding.component_name) + self.assertEqual('3.2.9', finding.component_version) + self.assertEqual('GHSA-v6rh-hp5x-86rv', finding.vuln_id_from_tool) + self.assertEqual(['python'], finding.tags) + self.assertEqual(2, finding.nb_occurences) def test_grype_issue_9618(self): - testfile = open("unittests/scans/anchore_grype/issue_9618.json") - parser = AnchoreGrypeParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(35, len(findings)) + with open("unittests/scans/anchore_grype/issue_9618.json") as testfile: + parser = AnchoreGrypeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(35, len(findings)) def test_grype_issue_9942(self): - testfile = open("unittests/scans/anchore_grype/issue_9942.json") - parser = AnchoreGrypeParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1, len(findings)) + with open("unittests/scans/anchore_grype/issue_9942.json") as testfile: + parser = AnchoreGrypeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) diff --git a/unittests/tools/test_anchorectl_policies_parser.py b/unittests/tools/test_anchorectl_policies_parser.py index a420802fc2..570656aad2 100644 --- a/unittests/tools/test_anchorectl_policies_parser.py +++ b/unittests/tools/test_anchorectl_policies_parser.py @@ -5,25 +5,23 @@ class TestAnchoreCTLPoliciesParser(DojoTestCase): def test_anchore_engine_parser_has_no_finding(self): - testfile = open("unittests/scans/anchorectl_policies/no_violation.json") - parser = AnchoreCTLPoliciesParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/anchorectl_policies/no_violation.json") as testfile: + parser = AnchoreCTLPoliciesParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_anchore_engine_parser_has_one_finding_and_it_is_correctly_parsed(self): - testfile = open("unittests/scans/anchorectl_policies/one_violation.json") - parser = AnchoreCTLPoliciesParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1, len(findings)) - singleFinding = findings[0] - self.assertEqual(singleFinding.severity, 'Medium') - self.assertEqual(singleFinding.title, 'RootUser - gate|dockerfile - trigger|b2605c2ddbdb02b8e2365c9248dada5a') - self.assertEqual(singleFinding.description, 'User root found as effective user, which is not on the allowed list') + with open("unittests/scans/anchorectl_policies/one_violation.json") as testfile: + parser = AnchoreCTLPoliciesParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + singleFinding = findings[0] + self.assertEqual(singleFinding.severity, 'Medium') + self.assertEqual(singleFinding.title, 'RootUser - gate|dockerfile - trigger|b2605c2ddbdb02b8e2365c9248dada5a') + self.assertEqual(singleFinding.description, 'User root found as effective user, which is not on the allowed list') def test_anchore_engine_parser_has_many_findings(self): - testfile = open("unittests/scans/anchorectl_policies/many_violations.json") - parser = AnchoreCTLPoliciesParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(3, len(findings)) + with open("unittests/scans/anchorectl_policies/many_violations.json") as testfile: + parser = AnchoreCTLPoliciesParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(3, len(findings)) diff --git a/unittests/tools/test_anchorectl_vulns_parser.py b/unittests/tools/test_anchorectl_vulns_parser.py index 10b8a6dea8..19e28cbd3a 100644 --- a/unittests/tools/test_anchorectl_vulns_parser.py +++ b/unittests/tools/test_anchorectl_vulns_parser.py @@ -5,25 +5,23 @@ class TestAnchoreCTLVulnsParser(DojoTestCase): def test_anchore_engine_parser_has_no_finding(self): - testfile = open("unittests/scans/anchorectl_vulns/no_vuln.json") - parser = AnchoreCTLVulnsParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/anchorectl_vulns/no_vuln.json") as testfile: + parser = AnchoreCTLVulnsParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_anchore_engine_parser_has_one_finding_and_it_is_correctly_parsed(self): - testfile = open("unittests/scans/anchorectl_vulns/one_vuln.json") - parser = AnchoreCTLVulnsParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1, len(findings)) - singleFinding = findings[0] - self.assertEqual(singleFinding.title, 'CVE-2011-3389 - libgnutls30-3.5.8-5+deb9u4(dpkg)') - self.assertEqual(singleFinding.severity, 'Medium') - self.assertEqual(singleFinding.description, '**Image hash**: None\n\n**Package**: libgnutls30-3.5.8-5+deb9u4\n\n**Package path**: None\n\n**Package type**: dpkg\n\n**Feed**: vulnerabilities/debian:9\n\n**CPE**: None\n\n**Description**: That test description\n\n') + with open("unittests/scans/anchorectl_vulns/one_vuln.json") as testfile: + parser = AnchoreCTLVulnsParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + singleFinding = findings[0] + self.assertEqual(singleFinding.title, 'CVE-2011-3389 - libgnutls30-3.5.8-5+deb9u4(dpkg)') + self.assertEqual(singleFinding.severity, 'Medium') + self.assertEqual(singleFinding.description, '**Image hash**: None\n\n**Package**: libgnutls30-3.5.8-5+deb9u4\n\n**Package path**: None\n\n**Package type**: dpkg\n\n**Feed**: vulnerabilities/debian:9\n\n**CPE**: None\n\n**Description**: That test description\n\n') def test_anchore_engine_parser_has_many_findings(self): - testfile = open("unittests/scans/anchorectl_vulns/many_vulns.json") - parser = AnchoreCTLVulnsParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(23, len(findings)) + with open("unittests/scans/anchorectl_vulns/many_vulns.json") as testfile: + parser = AnchoreCTLVulnsParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(23, len(findings)) diff --git a/unittests/tools/test_api_blackduck_parser.py b/unittests/tools/test_api_blackduck_parser.py index f0365c0a0d..fc3c548d53 100644 --- a/unittests/tools/test_api_blackduck_parser.py +++ b/unittests/tools/test_api_blackduck_parser.py @@ -8,35 +8,34 @@ class TestApiBlackduckParser(DojoTestCase): def test_bandit_parser_has_many_findings(self): - testfile = open("unittests/scans/api_blackduck/many_vulns.json") - parser = ApiBlackduckParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - finding.clean() - self.assertIn(finding.severity, SEVERITIES) - self.assertEqual(43, len(findings)) - with self.subTest(i=0): - item = findings[0] - self.assertEqual("BDSA-2021-2909 in cdr/code-server:3.3.0-rc.27", item.title) - self.assertEqual("Medium", item.severity) - self.assertEqual("cdr/code-server", item.component_name) - self.assertEqual("3.3.0-rc.27", item.component_version) - self.assertEqual(400, item.cwe) - self.assertEqual("BDSA-2021-2909", item.unique_id_from_tool) - with self.subTest(i=20): - item = findings[20] - self.assertEqual("BDSA-2019-2252 in LibreOffice:6.0.0.3", item.title) - self.assertEqual("High", item.severity) - self.assertEqual("LibreOffice", item.component_name) - self.assertEqual("6.0.0.3", item.component_version) - self.assertEqual(749, item.cwe) - self.assertEqual("BDSA-2019-2252", item.unique_id_from_tool) - with self.subTest(i=42): - item = findings[42] - self.assertEqual("BDSA-2020-3620 in y18n:5.0.1", item.title) - self.assertEqual("Medium", item.severity) - self.assertEqual("y18n", item.component_name) - self.assertEqual("5.0.1", item.component_version) - self.assertEqual(668, item.cwe) - self.assertEqual("BDSA-2020-3620", item.unique_id_from_tool) + with open("unittests/scans/api_blackduck/many_vulns.json") as testfile: + parser = ApiBlackduckParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + finding.clean() + self.assertIn(finding.severity, SEVERITIES) + self.assertEqual(43, len(findings)) + with self.subTest(i=0): + item = findings[0] + self.assertEqual("BDSA-2021-2909 in cdr/code-server:3.3.0-rc.27", item.title) + self.assertEqual("Medium", item.severity) + self.assertEqual("cdr/code-server", item.component_name) + self.assertEqual("3.3.0-rc.27", item.component_version) + self.assertEqual(400, item.cwe) + self.assertEqual("BDSA-2021-2909", item.unique_id_from_tool) + with self.subTest(i=20): + item = findings[20] + self.assertEqual("BDSA-2019-2252 in LibreOffice:6.0.0.3", item.title) + self.assertEqual("High", item.severity) + self.assertEqual("LibreOffice", item.component_name) + self.assertEqual("6.0.0.3", item.component_version) + self.assertEqual(749, item.cwe) + self.assertEqual("BDSA-2019-2252", item.unique_id_from_tool) + with self.subTest(i=42): + item = findings[42] + self.assertEqual("BDSA-2020-3620 in y18n:5.0.1", item.title) + self.assertEqual("Medium", item.severity) + self.assertEqual("y18n", item.component_name) + self.assertEqual("5.0.1", item.component_version) + self.assertEqual(668, item.cwe) + self.assertEqual("BDSA-2020-3620", item.unique_id_from_tool) diff --git a/unittests/tools/test_api_cobalt_parser.py b/unittests/tools/test_api_cobalt_parser.py index f9c8ad64fb..6f4686ddc6 100644 --- a/unittests/tools/test_api_cobalt_parser.py +++ b/unittests/tools/test_api_cobalt_parser.py @@ -10,273 +10,262 @@ class TestApiCobaltParser(DojoTestCase): def test_cobalt_api_parser_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/api_cobalt/cobalt_api_zero_vul.json") - parser = ApiCobaltParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(0, len(findings)) + with open("unittests/scans/api_cobalt/cobalt_api_zero_vul.json") as testfile: + parser = ApiCobaltParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_cobalt_api_parser_with_many_vuln_has_many_findings(self): - testfile = open("unittests/scans/api_cobalt/cobalt_api_many_vul.json") - parser = ApiCobaltParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(3, len(findings)) + with open("unittests/scans/api_cobalt/cobalt_api_many_vul.json") as testfile: + parser = ApiCobaltParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(3, len(findings)) def test_cobalt_api_parser_with_carried_over_finding(self): - testfile = open("unittests/scans/api_cobalt/cobalt_api_one_vul_carried_over.json") - parser = ApiCobaltParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("Missing firewall", finding.title) - self.assertEqual("2021-06-03", finding.date) - self.assertEqual("Low", finding.severity) - self.assertIn("A firewall is...", finding.description) - self.assertEqual("Be sure to...", finding.mitigation) - self.assertEqual("Try this...", finding.steps_to_reproduce) - self.assertEqual("2021-06-05", finding.last_status_update) - self.assertEqual("vu_5wXY6bq", finding.unique_id_from_tool) - self.assertTrue(finding.active) - self.assertTrue(finding.verified) - self.assertFalse(finding.false_p) - self.assertFalse(finding.duplicate) - self.assertFalse(finding.out_of_scope) - self.assertFalse(finding.risk_accepted) - self.assertFalse(finding.is_mitigated) - self.assertFalse(finding.static_finding) - self.assertTrue(finding.dynamic_finding) + with open("unittests/scans/api_cobalt/cobalt_api_one_vul_carried_over.json") as testfile: + parser = ApiCobaltParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("Missing firewall", finding.title) + self.assertEqual("2021-06-03", finding.date) + self.assertEqual("Low", finding.severity) + self.assertIn("A firewall is...", finding.description) + self.assertEqual("Be sure to...", finding.mitigation) + self.assertEqual("Try this...", finding.steps_to_reproduce) + self.assertEqual("2021-06-05", finding.last_status_update) + self.assertEqual("vu_5wXY6bq", finding.unique_id_from_tool) + self.assertTrue(finding.active) + self.assertTrue(finding.verified) + self.assertFalse(finding.false_p) + self.assertFalse(finding.duplicate) + self.assertFalse(finding.out_of_scope) + self.assertFalse(finding.risk_accepted) + self.assertFalse(finding.is_mitigated) + self.assertFalse(finding.static_finding) + self.assertTrue(finding.dynamic_finding) def test_cobalt_api_parser_with_check_fix_finding(self): - testfile = open("unittests/scans/api_cobalt/cobalt_api_one_vul_check_fix.json") - parser = ApiCobaltParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("Cross Site Scripting", finding.title) - self.assertEqual("2021-05-11", finding.date) - self.assertEqual("Medium", finding.severity) - self.assertIn("A XSS injection attack...", finding.description) - self.assertEqual("Ensure that...", finding.mitigation) - self.assertEqual("Do this...", finding.steps_to_reproduce) - self.assertEqual("2021-05-12", finding.last_status_update) - self.assertEqual("vu_3wXY4bq", finding.unique_id_from_tool) - self.assertTrue(finding.active) - self.assertTrue(finding.verified) - self.assertFalse(finding.false_p) - self.assertFalse(finding.duplicate) - self.assertFalse(finding.out_of_scope) - self.assertFalse(finding.risk_accepted) - self.assertFalse(finding.is_mitigated) - self.assertFalse(finding.static_finding) - self.assertTrue(finding.dynamic_finding) + with open("unittests/scans/api_cobalt/cobalt_api_one_vul_check_fix.json") as testfile: + parser = ApiCobaltParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("Cross Site Scripting", finding.title) + self.assertEqual("2021-05-11", finding.date) + self.assertEqual("Medium", finding.severity) + self.assertIn("A XSS injection attack...", finding.description) + self.assertEqual("Ensure that...", finding.mitigation) + self.assertEqual("Do this...", finding.steps_to_reproduce) + self.assertEqual("2021-05-12", finding.last_status_update) + self.assertEqual("vu_3wXY4bq", finding.unique_id_from_tool) + self.assertTrue(finding.active) + self.assertTrue(finding.verified) + self.assertFalse(finding.false_p) + self.assertFalse(finding.duplicate) + self.assertFalse(finding.out_of_scope) + self.assertFalse(finding.risk_accepted) + self.assertFalse(finding.is_mitigated) + self.assertFalse(finding.static_finding) + self.assertTrue(finding.dynamic_finding) def test_cobalt_api_parser_with_invalid_finding(self): - testfile = open("unittests/scans/api_cobalt/cobalt_api_one_vul_invalid.json") - parser = ApiCobaltParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("SQL Injection", finding.title) - self.assertEqual("2021-01-01", finding.date) - self.assertEqual("Critical", finding.severity) - self.assertIn("A SQL injection attack...", finding.description) - self.assertEqual("Ensure this...", finding.mitigation) - self.assertEqual("Do this than that...", finding.steps_to_reproduce) - self.assertEqual("2021-01-02", finding.last_status_update) - self.assertEqual("vu_5wXY6bq", finding.unique_id_from_tool) - self.assertFalse(finding.active) - self.assertTrue(finding.verified) - self.assertTrue(finding.false_p) - self.assertFalse(finding.duplicate) - self.assertFalse(finding.out_of_scope) - self.assertFalse(finding.risk_accepted) - self.assertFalse(finding.is_mitigated) - self.assertFalse(finding.static_finding) - self.assertTrue(finding.dynamic_finding) + with open("unittests/scans/api_cobalt/cobalt_api_one_vul_invalid.json") as testfile: + parser = ApiCobaltParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("SQL Injection", finding.title) + self.assertEqual("2021-01-01", finding.date) + self.assertEqual("Critical", finding.severity) + self.assertIn("A SQL injection attack...", finding.description) + self.assertEqual("Ensure this...", finding.mitigation) + self.assertEqual("Do this than that...", finding.steps_to_reproduce) + self.assertEqual("2021-01-02", finding.last_status_update) + self.assertEqual("vu_5wXY6bq", finding.unique_id_from_tool) + self.assertFalse(finding.active) + self.assertTrue(finding.verified) + self.assertTrue(finding.false_p) + self.assertFalse(finding.duplicate) + self.assertFalse(finding.out_of_scope) + self.assertFalse(finding.risk_accepted) + self.assertFalse(finding.is_mitigated) + self.assertFalse(finding.static_finding) + self.assertTrue(finding.dynamic_finding) def test_cobalt_api_parser_with_need_fix_finding(self): - testfile = open("unittests/scans/api_cobalt/cobalt_api_one_vul_need_fix.json") - parser = ApiCobaltParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("SQL Injection", finding.title) - self.assertEqual("2021-04-01", finding.date) - self.assertEqual("High", finding.severity) - self.assertIn("A SQL injection attack...", finding.description) - self.assertEqual("Ensure this...", finding.mitigation) - self.assertEqual("Do this than that...", finding.steps_to_reproduce) - self.assertEqual("2021-04-05", finding.last_status_update) - self.assertEqual("vu_2wXY3bq", finding.unique_id_from_tool) - self.assertTrue(finding.active) - self.assertTrue(finding.verified) - self.assertFalse(finding.false_p) - self.assertFalse(finding.duplicate) - self.assertFalse(finding.out_of_scope) - self.assertFalse(finding.risk_accepted) - self.assertFalse(finding.is_mitigated) - self.assertFalse(finding.static_finding) - self.assertTrue(finding.dynamic_finding) + with open("unittests/scans/api_cobalt/cobalt_api_one_vul_need_fix.json") as testfile: + parser = ApiCobaltParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("SQL Injection", finding.title) + self.assertEqual("2021-04-01", finding.date) + self.assertEqual("High", finding.severity) + self.assertIn("A SQL injection attack...", finding.description) + self.assertEqual("Ensure this...", finding.mitigation) + self.assertEqual("Do this than that...", finding.steps_to_reproduce) + self.assertEqual("2021-04-05", finding.last_status_update) + self.assertEqual("vu_2wXY3bq", finding.unique_id_from_tool) + self.assertTrue(finding.active) + self.assertTrue(finding.verified) + self.assertFalse(finding.false_p) + self.assertFalse(finding.duplicate) + self.assertFalse(finding.out_of_scope) + self.assertFalse(finding.risk_accepted) + self.assertFalse(finding.is_mitigated) + self.assertFalse(finding.static_finding) + self.assertTrue(finding.dynamic_finding) def test_cobalt_api_parser_with_new_finding(self): - testfile = open("unittests/scans/api_cobalt/cobalt_api_one_vul_new.json") - parser = ApiCobaltParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("SQL Injection", finding.title) - self.assertEqual("2021-01-01", finding.date) - self.assertEqual("Info", finding.severity) - self.assertIn("A SQL injection attack...", finding.description) - self.assertEqual("Ensure this...", finding.mitigation) - self.assertEqual("Do this than that...", finding.steps_to_reproduce) - self.assertEqual("2021-01-01", finding.last_status_update) - self.assertEqual("vu_5wXY6bq", finding.unique_id_from_tool) - self.assertTrue(finding.active) - self.assertFalse(finding.verified) - self.assertFalse(finding.false_p) - self.assertFalse(finding.duplicate) - self.assertFalse(finding.out_of_scope) - self.assertFalse(finding.risk_accepted) - self.assertFalse(finding.is_mitigated) - self.assertFalse(finding.static_finding) - self.assertTrue(finding.dynamic_finding) + with open("unittests/scans/api_cobalt/cobalt_api_one_vul_new.json") as testfile: + parser = ApiCobaltParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("SQL Injection", finding.title) + self.assertEqual("2021-01-01", finding.date) + self.assertEqual("Info", finding.severity) + self.assertIn("A SQL injection attack...", finding.description) + self.assertEqual("Ensure this...", finding.mitigation) + self.assertEqual("Do this than that...", finding.steps_to_reproduce) + self.assertEqual("2021-01-01", finding.last_status_update) + self.assertEqual("vu_5wXY6bq", finding.unique_id_from_tool) + self.assertTrue(finding.active) + self.assertFalse(finding.verified) + self.assertFalse(finding.false_p) + self.assertFalse(finding.duplicate) + self.assertFalse(finding.out_of_scope) + self.assertFalse(finding.risk_accepted) + self.assertFalse(finding.is_mitigated) + self.assertFalse(finding.static_finding) + self.assertTrue(finding.dynamic_finding) def test_cobalt_api_parser_with_out_of_scope_finding(self): - testfile = open("unittests/scans/api_cobalt/cobalt_api_one_vul_out_of_scope.json") - parser = ApiCobaltParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("SQL Injection", finding.title) - self.assertEqual("2021-01-01", finding.date) - self.assertEqual("Info", finding.severity) - self.assertIn("A SQL injection attack...", finding.description) - self.assertEqual("Ensure this...", finding.mitigation) - self.assertEqual("Do this than that...", finding.steps_to_reproduce) - self.assertEqual("2021-01-02", finding.last_status_update) - self.assertEqual("vu_5wXY6bq", finding.unique_id_from_tool) - self.assertFalse(finding.active) - self.assertTrue(finding.verified) - self.assertFalse(finding.false_p) - self.assertFalse(finding.duplicate) - self.assertTrue(finding.out_of_scope) - self.assertFalse(finding.risk_accepted) - self.assertFalse(finding.is_mitigated) - self.assertFalse(finding.static_finding) - self.assertTrue(finding.dynamic_finding) + with open("unittests/scans/api_cobalt/cobalt_api_one_vul_out_of_scope.json") as testfile: + parser = ApiCobaltParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("SQL Injection", finding.title) + self.assertEqual("2021-01-01", finding.date) + self.assertEqual("Info", finding.severity) + self.assertIn("A SQL injection attack...", finding.description) + self.assertEqual("Ensure this...", finding.mitigation) + self.assertEqual("Do this than that...", finding.steps_to_reproduce) + self.assertEqual("2021-01-02", finding.last_status_update) + self.assertEqual("vu_5wXY6bq", finding.unique_id_from_tool) + self.assertFalse(finding.active) + self.assertTrue(finding.verified) + self.assertFalse(finding.false_p) + self.assertFalse(finding.duplicate) + self.assertTrue(finding.out_of_scope) + self.assertFalse(finding.risk_accepted) + self.assertFalse(finding.is_mitigated) + self.assertFalse(finding.static_finding) + self.assertTrue(finding.dynamic_finding) def test_cobalt_api_parser_with_triaging_finding(self): - testfile = open("unittests/scans/api_cobalt/cobalt_api_one_vul_triaging.json") - parser = ApiCobaltParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("SQL Injection", finding.title) - self.assertEqual("2021-01-01", finding.date) - self.assertEqual("Info", finding.severity) - self.assertIn("A SQL injection attack...", finding.description) - self.assertEqual("Ensure this...", finding.mitigation) - self.assertEqual("Do this than that...", finding.steps_to_reproduce) - self.assertEqual("2021-01-02", finding.last_status_update) - self.assertEqual("vu_5wXY6bq", finding.unique_id_from_tool) - self.assertTrue(finding.active) - self.assertFalse(finding.verified) - self.assertFalse(finding.false_p) - self.assertFalse(finding.duplicate) - self.assertFalse(finding.out_of_scope) - self.assertFalse(finding.risk_accepted) - self.assertFalse(finding.is_mitigated) - self.assertFalse(finding.static_finding) - self.assertTrue(finding.dynamic_finding) + with open("unittests/scans/api_cobalt/cobalt_api_one_vul_triaging.json") as testfile: + parser = ApiCobaltParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("SQL Injection", finding.title) + self.assertEqual("2021-01-01", finding.date) + self.assertEqual("Info", finding.severity) + self.assertIn("A SQL injection attack...", finding.description) + self.assertEqual("Ensure this...", finding.mitigation) + self.assertEqual("Do this than that...", finding.steps_to_reproduce) + self.assertEqual("2021-01-02", finding.last_status_update) + self.assertEqual("vu_5wXY6bq", finding.unique_id_from_tool) + self.assertTrue(finding.active) + self.assertFalse(finding.verified) + self.assertFalse(finding.false_p) + self.assertFalse(finding.duplicate) + self.assertFalse(finding.out_of_scope) + self.assertFalse(finding.risk_accepted) + self.assertFalse(finding.is_mitigated) + self.assertFalse(finding.static_finding) + self.assertTrue(finding.dynamic_finding) def test_cobalt_api_parser_with_valid_fix_finding(self): - testfile = open("unittests/scans/api_cobalt/cobalt_api_one_vul_valid_fix.json") - parser = ApiCobaltParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("SQL Injection", finding.title) - self.assertEqual("2021-01-01", finding.date) - self.assertEqual("Low", finding.severity) - self.assertIn("A SQL injection attack...", finding.description) - self.assertEqual("Ensure this...", finding.mitigation) - self.assertEqual("Do this than that...", finding.steps_to_reproduce) - self.assertEqual("2021-01-03", finding.last_status_update) - self.assertEqual("vu_5wXY6bq", finding.unique_id_from_tool) - self.assertFalse(finding.active) - self.assertTrue(finding.verified) - self.assertFalse(finding.false_p) - self.assertFalse(finding.duplicate) - self.assertFalse(finding.out_of_scope) - self.assertFalse(finding.risk_accepted) - self.assertTrue(finding.is_mitigated) - self.assertFalse(finding.static_finding) - self.assertTrue(finding.dynamic_finding) + with open("unittests/scans/api_cobalt/cobalt_api_one_vul_valid_fix.json") as testfile: + parser = ApiCobaltParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("SQL Injection", finding.title) + self.assertEqual("2021-01-01", finding.date) + self.assertEqual("Low", finding.severity) + self.assertIn("A SQL injection attack...", finding.description) + self.assertEqual("Ensure this...", finding.mitigation) + self.assertEqual("Do this than that...", finding.steps_to_reproduce) + self.assertEqual("2021-01-03", finding.last_status_update) + self.assertEqual("vu_5wXY6bq", finding.unique_id_from_tool) + self.assertFalse(finding.active) + self.assertTrue(finding.verified) + self.assertFalse(finding.false_p) + self.assertFalse(finding.duplicate) + self.assertFalse(finding.out_of_scope) + self.assertFalse(finding.risk_accepted) + self.assertTrue(finding.is_mitigated) + self.assertFalse(finding.static_finding) + self.assertTrue(finding.dynamic_finding) def test_cobalt_api_parser_with_wont_fix_finding(self): - testfile = open("unittests/scans/api_cobalt/cobalt_api_one_vul_wont_fix.json") - parser = ApiCobaltParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("SQL Injection", finding.title) - self.assertEqual("2021-01-01", finding.date) - self.assertEqual("Low", finding.severity) - self.assertIn("A SQL injection attack...", finding.description) - self.assertEqual("Ensure this...", finding.mitigation) - self.assertEqual("Do this than that...", finding.steps_to_reproduce) - self.assertEqual("2021-01-02", finding.last_status_update) - self.assertEqual("vu_5wXY6bq", finding.unique_id_from_tool) - self.assertTrue(finding.active) - self.assertTrue(finding.verified) - self.assertFalse(finding.false_p) - self.assertFalse(finding.duplicate) - self.assertFalse(finding.out_of_scope) - self.assertTrue(finding.risk_accepted) - self.assertFalse(finding.is_mitigated) - self.assertFalse(finding.static_finding) - self.assertTrue(finding.dynamic_finding) + with open("unittests/scans/api_cobalt/cobalt_api_one_vul_wont_fix.json") as testfile: + parser = ApiCobaltParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("SQL Injection", finding.title) + self.assertEqual("2021-01-01", finding.date) + self.assertEqual("Low", finding.severity) + self.assertIn("A SQL injection attack...", finding.description) + self.assertEqual("Ensure this...", finding.mitigation) + self.assertEqual("Do this than that...", finding.steps_to_reproduce) + self.assertEqual("2021-01-02", finding.last_status_update) + self.assertEqual("vu_5wXY6bq", finding.unique_id_from_tool) + self.assertTrue(finding.active) + self.assertTrue(finding.verified) + self.assertFalse(finding.false_p) + self.assertFalse(finding.duplicate) + self.assertFalse(finding.out_of_scope) + self.assertTrue(finding.risk_accepted) + self.assertFalse(finding.is_mitigated) + self.assertFalse(finding.static_finding) + self.assertTrue(finding.dynamic_finding) @patch('dojo.tools.api_cobalt.importer.CobaltApiImporter.get_findings') def test_cobalt_api_parser_with_api(self, mock): diff --git a/unittests/tools/test_api_vulners_parser.py b/unittests/tools/test_api_vulners_parser.py index 0f58c604f4..e555881be9 100644 --- a/unittests/tools/test_api_vulners_parser.py +++ b/unittests/tools/test_api_vulners_parser.py @@ -6,44 +6,44 @@ class TestApiVulnersParser(DojoTestCase): def test_parse_many_findings(self): - testfile = open("unittests/scans/api_vulners/report_many_vulns.json") - parser = ApiVulnersParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(3, len(findings)) - finding = findings[2] - self.assertEqual("High", finding.severity) - self.assertEqual("223.234.234.123", finding.unsaved_endpoints[0].host) - self.assertEqual("VNS/CESA-2021:0348", finding.vuln_id_from_tool) - self.assertEqual("**CentOS Errata and Security Advisory** CESA-2021:0348", finding.description) - self.assertEqual(4, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", finding.cvssv3) + with open("unittests/scans/api_vulners/report_many_vulns.json") as testfile: + parser = ApiVulnersParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(3, len(findings)) + finding = findings[2] + self.assertEqual("High", finding.severity) + self.assertEqual("223.234.234.123", finding.unsaved_endpoints[0].host) + self.assertEqual("VNS/CESA-2021:0348", finding.vuln_id_from_tool) + self.assertEqual("**CentOS Errata and Security Advisory** CESA-2021:0348", finding.description) + self.assertEqual(4, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", finding.cvssv3) def test_parse_one_finding(self): - testfile = open("unittests/scans/api_vulners/report_one_vuln.json") - parser = ApiVulnersParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("Critical", finding.severity) - self.assertEqual("12.34.56.78", finding.unsaved_endpoints[0].host) - self.assertEqual("VNS/RHSA-2018:2285", finding.vuln_id_from_tool) - self.assertEqual(2, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H", finding.cvssv3) + with open("unittests/scans/api_vulners/report_one_vuln.json") as testfile: + parser = ApiVulnersParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("Critical", finding.severity) + self.assertEqual("12.34.56.78", finding.unsaved_endpoints[0].host) + self.assertEqual("VNS/RHSA-2018:2285", finding.vuln_id_from_tool) + self.assertEqual(2, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H", finding.cvssv3) def test_parse_no_finding(self): - testfile = open("unittests/scans/api_vulners/report_no_vulns.json") - parser = ApiVulnersParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/api_vulners/report_no_vulns.json") as testfile: + parser = ApiVulnersParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_no_description(self): - testfile = open("unittests/scans/api_vulners/report_no_description.json") - parser = ApiVulnersParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("Critical", finding.severity) - self.assertEqual("12.34.56.78", finding.unsaved_endpoints[0].host) - self.assertEqual("VNS/RHSA-2018:2285", finding.vuln_id_from_tool) - self.assertEqual(finding.title, finding.description) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + with open("unittests/scans/api_vulners/report_no_description.json") as testfile: + parser = ApiVulnersParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("Critical", finding.severity) + self.assertEqual("12.34.56.78", finding.unsaved_endpoints[0].host) + self.assertEqual("VNS/RHSA-2018:2285", finding.vuln_id_from_tool) + self.assertEqual(finding.title, finding.description) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) diff --git a/unittests/tools/test_aqua_parser.py b/unittests/tools/test_aqua_parser.py index ad2ea81781..f9168258ce 100644 --- a/unittests/tools/test_aqua_parser.py +++ b/unittests/tools/test_aqua_parser.py @@ -6,35 +6,33 @@ class TestAquaParser(DojoTestCase): def test_aqua_parser_has_no_finding(self): - testfile = open("unittests/scans/aqua/no_vuln.json") - parser = AquaParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/aqua/no_vuln.json") as testfile: + parser = AquaParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_aqua_parser_has_one_finding(self): - testfile = open("unittests/scans/aqua/one_vuln.json") - parser = AquaParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual('CVE-2019-14697 - musl (1.1.20-r4) ', finding.title) - self.assertEqual('High', finding.severity) - self.assertEqual('CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H', finding.cvssv3) - self.assertEqual('musl libc through 1.1.23 has an x87 floating-point stack adjustment imbalance, related to the math/i386/ directory. In some cases, use of this library could introduce out-of-bounds writes that are not present in an application\'s source code.', finding.description) - self.assertEqual('1.1.20-r5', finding.mitigation) - self.assertEqual('\nhttps://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2019-14697', finding.references) - self.assertEqual('musl', finding.component_name) - self.assertEqual('1.1.20-r4', finding.component_version) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual('CVE-2019-14697', finding.unsaved_vulnerability_ids[0]) + with open("unittests/scans/aqua/one_vuln.json") as testfile: + parser = AquaParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual('CVE-2019-14697 - musl (1.1.20-r4) ', finding.title) + self.assertEqual('High', finding.severity) + self.assertEqual('CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H', finding.cvssv3) + self.assertEqual('musl libc through 1.1.23 has an x87 floating-point stack adjustment imbalance, related to the math/i386/ directory. In some cases, use of this library could introduce out-of-bounds writes that are not present in an application\'s source code.', finding.description) + self.assertEqual('1.1.20-r5', finding.mitigation) + self.assertEqual('\nhttps://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2019-14697', finding.references) + self.assertEqual('musl', finding.component_name) + self.assertEqual('1.1.20-r4', finding.component_version) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual('CVE-2019-14697', finding.unsaved_vulnerability_ids[0]) def test_aqua_parser_has_many_findings(self): - testfile = open("unittests/scans/aqua/many_vulns.json") - parser = AquaParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(24, len(findings)) + with open("unittests/scans/aqua/many_vulns.json") as testfile: + parser = AquaParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(24, len(findings)) def test_aqua_parser_v2_has_one_finding(self): with open("unittests/scans/aqua/one_v2.json") as testfile: diff --git a/unittests/tools/test_auditjs_parser.py b/unittests/tools/test_auditjs_parser.py index 8d012aec61..fc95250276 100644 --- a/unittests/tools/test_auditjs_parser.py +++ b/unittests/tools/test_auditjs_parser.py @@ -6,74 +6,71 @@ class TestAuditJSParser(DojoTestCase): def test_auditjs_parser_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/auditjs/auditjs_zero_vul.json") - parser = AuditJSParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(0, len(findings)) + with open("unittests/scans/auditjs/auditjs_zero_vul.json") as testfile: + parser = AuditJSParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_auditjs_parser_with_one_criticle_vuln_has_one_findings(self): - testfile = open("unittests/scans/auditjs/auditjs_one_vul.json") - parser = AuditJSParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - self.assertEqual("mysql", findings[0].component_name) - self.assertEqual("2.0.0", findings[0].component_version) - self.assertEqual(9.6, findings[0].cvssv3_score) - self.assertEqual("Critical", findings[0].severity) - self.assertEqual("CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", findings[0].cvssv3) - self.assertEqual("da5a3b11-c75b-48e7-9c28-1123f0a492bf", findings[0].unique_id_from_tool) - self.assertEqual("Unverified Certificate", findings[0].title) - self.assertEqual("> When using SSL to connect to a MySQL server, the SSL procedure implemented does not actually check if the remote server has a trusted certificate or not.\n> \n> -- [github.com](https://github.com/mysqljs/mysql/issues/816)", - findings[0].description) - self.assertEqual("https://ossindex.sonatype.org/vulnerability/da5a3b11-c75b-48e7-9c28-1123f0a492bf?component-type=npm&component-name=mysql&utm_source=auditjs&utm_medium=integration&utm_content=4.0.25", - findings[0].references) + with open("unittests/scans/auditjs/auditjs_one_vul.json") as testfile: + parser = AuditJSParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + self.assertEqual("mysql", findings[0].component_name) + self.assertEqual("2.0.0", findings[0].component_version) + self.assertEqual(9.6, findings[0].cvssv3_score) + self.assertEqual("Critical", findings[0].severity) + self.assertEqual("CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", findings[0].cvssv3) + self.assertEqual("da5a3b11-c75b-48e7-9c28-1123f0a492bf", findings[0].unique_id_from_tool) + self.assertEqual("Unverified Certificate", findings[0].title) + self.assertEqual("> When using SSL to connect to a MySQL server, the SSL procedure implemented does not actually check if the remote server has a trusted certificate or not.\n> \n> -- [github.com](https://github.com/mysqljs/mysql/issues/816)", + findings[0].description) + self.assertEqual("https://ossindex.sonatype.org/vulnerability/da5a3b11-c75b-48e7-9c28-1123f0a492bf?component-type=npm&component-name=mysql&utm_source=auditjs&utm_medium=integration&utm_content=4.0.25", + findings[0].references) def test_auditjs_parser_with_many_vuln_has_many_findings(self): - testfile = open("unittests/scans/auditjs/auditjs_many_vul.json") - parser = AuditJSParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - # Notice that there are 13 vulnerabilities but 1 duplicate in this report - self.assertEqual(12, len(findings)) - self.assertEqual("connect", findings[0].component_name) - self.assertEqual("2.6.0", findings[0].component_version) - self.assertEqual(5.4, findings[0].cvssv3_score) - self.assertEqual("Medium", findings[0].severity) - self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N", findings[0].cvssv3) - self.assertEqual("7df31426-09a2-4b5f-a0ab-acc699023c57", findings[0].unique_id_from_tool) - self.assertEqual("connect node module before 2.14.0 suffers from a Cross-Site Scripting (XSS) vulnerability due to a lack of validation of file in directory.js middleware.", - findings[0].description) - self.assertEqual("[CVE-2018-3717] connect node module before 2.14.0 suffers from a Cross-Site Scripting (XSS) vuln...", - findings[0].title) - self.assertEqual(1, len(findings[0].unsaved_vulnerability_ids)) - self.assertEqual("CVE-2018-3717", findings[0].unsaved_vulnerability_ids[0]) - self.assertEqual("https://ossindex.sonatype.org/vulnerability/7df31426-09a2-4b5f-a0ab-acc699023c57?component-type=npm&component-name=connect&utm_source=auditjs&utm_medium=integration&utm_content=4.0.25", - findings[0].references) - self.assertEqual(400, findings[4].cwe) + with open("unittests/scans/auditjs/auditjs_many_vul.json") as testfile: + parser = AuditJSParser() + findings = parser.get_findings(testfile, Test()) + testfile.close() + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + # Notice that there are 13 vulnerabilities but 1 duplicate in this report + self.assertEqual(12, len(findings)) + self.assertEqual("connect", findings[0].component_name) + self.assertEqual("2.6.0", findings[0].component_version) + self.assertEqual(5.4, findings[0].cvssv3_score) + self.assertEqual("Medium", findings[0].severity) + self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N", findings[0].cvssv3) + self.assertEqual("7df31426-09a2-4b5f-a0ab-acc699023c57", findings[0].unique_id_from_tool) + self.assertEqual("connect node module before 2.14.0 suffers from a Cross-Site Scripting (XSS) vulnerability due to a lack of validation of file in directory.js middleware.", + findings[0].description) + self.assertEqual("[CVE-2018-3717] connect node module before 2.14.0 suffers from a Cross-Site Scripting (XSS) vuln...", + findings[0].title) + self.assertEqual(1, len(findings[0].unsaved_vulnerability_ids)) + self.assertEqual("CVE-2018-3717", findings[0].unsaved_vulnerability_ids[0]) + self.assertEqual("https://ossindex.sonatype.org/vulnerability/7df31426-09a2-4b5f-a0ab-acc699023c57?component-type=npm&component-name=connect&utm_source=auditjs&utm_medium=integration&utm_content=4.0.25", + findings[0].references) + self.assertEqual(400, findings[4].cwe) def test_auditjs_parser_empty_with_error(self): with self.assertRaises(ValueError) as context: - testfile = open("unittests/scans/auditjs/empty_with_error.json") - parser = AuditJSParser() - parser.get_findings(testfile, Test()) - testfile.close() + with open("unittests/scans/auditjs/empty_with_error.json") as testfile: + parser = AuditJSParser() + parser.get_findings(testfile, Test()) + self.assertTrue( "Invalid JSON format. Are you sure you used --json option ?" in str(context.exception) ) def test_auditjs_parser_with_package_name_has_namespace(self): - testfile = open("unittests/scans/auditjs/auditjs_with_package_namespace.json") - parser = AuditJSParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() + with open("unittests/scans/auditjs/auditjs_with_package_namespace.json") as testfile: + parser = AuditJSParser() + findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - self.assertEqual("%40next/env", findings[0].component_name) + self.assertEqual(1, len(findings)) + self.assertEqual("%40next/env", findings[0].component_name) diff --git a/unittests/tools/test_azure_security_center_recommendations_parser.py b/unittests/tools/test_azure_security_center_recommendations_parser.py index 3f4a4c4a97..5b863009f0 100644 --- a/unittests/tools/test_azure_security_center_recommendations_parser.py +++ b/unittests/tools/test_azure_security_center_recommendations_parser.py @@ -7,24 +7,24 @@ class TestAzureSecurityCenterRecommendationsParser(DojoTestCase): def test_parse_file_with_no_findings(self): - testfile = open("unittests/scans/azure_security_center_recommendations/zero_vulns.csv") - parser = AzureSecurityCenterRecommendationsParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/azure_security_center_recommendations/zero_vulns.csv") as testfile: + parser = AzureSecurityCenterRecommendationsParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_multiple_findings(self): - testfile = open("unittests/scans/azure_security_center_recommendations/many_vulns.csv") - parser = AzureSecurityCenterRecommendationsParser() - findings = parser.get_findings(testfile, Test()) + with open("unittests/scans/azure_security_center_recommendations/many_vulns.csv") as testfile: + parser = AzureSecurityCenterRecommendationsParser() + findings = parser.get_findings(testfile, Test()) - self.assertEqual(3, len(findings)) + self.assertEqual(3, len(findings)) - finding = findings[0] - self.assertEqual('my_virtual_network - Virtual networks should be protected by Azure Firewall', finding.title) - self.assertEqual(date.fromisoformat('2021-09-28'), finding.date) - self.assertEqual(1032, finding.cwe) - self.assertEqual('Low', finding.severity) - description = '''**Recommendation:** Virtual networks should be protected by Azure Firewall + finding = findings[0] + self.assertEqual('my_virtual_network - Virtual networks should be protected by Azure Firewall', finding.title) + self.assertEqual(date.fromisoformat('2021-09-28'), finding.date) + self.assertEqual(1032, finding.cwe) + self.assertEqual('Low', finding.severity) + description = '''**Recommendation:** Virtual networks should be protected by Azure Firewall **Resource Name:** my_virtual_network **Resource Type:** virtualnetworks **Resource Group:** my_resource_group @@ -32,23 +32,23 @@ def test_parse_file_with_multiple_findings(self): **Controls:** Restrict unauthorized network access **Subscription:** My first subscription **Subscription Id:** 9cfbad7a-7369-42e4-bcce-7677c5b3a44b''' - self.assertEqual(description, finding.description) - mitigation = 'To protect your virtual networks with Azure Firewall: 1. From the list below, select a network. Or select Take action if you\'ve arrived here from a specific virtual network page. 2. Follow the Azure Firewall deployment instructions. Make sure to configure all default routes properly.Important: Azure Firewall is billed separately from Azure Security Center. Learn more about Azure Firewall pricing.' - self.assertEqual(mitigation, finding.mitigation) - references = 'https://portal.azure.com/#blade/Microsoft_Azure_Security/RecommendationsBlade/assessmentKey/f67fb4ed-d481-44d7-91e5-efadf504f74a/resourceId/%2fsubscriptions%2f9cfbad7a-7369-42e4-bcce-7677c5b3a44b%2fresourcegroups%2fmy_resource_group%2fproviders%2fmicrosoft.network%2fvirtualnetworks%2fmy_virtual_network' - self.assertEqual(references, finding.references) - self.assertTrue(finding.static_finding) - self.assertFalse(finding.dynamic_finding) - unique_id_from_tool = '/subscriptions/9cfbad7a-7369-42e4-bcce-7677c5b3a44b/resourcegroups/my_resource_group/providers/microsoft.network/virtualnetworks/my_virtual_network/providers/Microsoft.Security/assessments/f67fb4ed-d481-44d7-91e5-efadf504f74a' - self.assertEqual(unique_id_from_tool, finding.unique_id_from_tool) - self.assertEqual('f67fb4ed-d481-44d7-91e5-efadf504f74a', finding.vuln_id_from_tool) + self.assertEqual(description, finding.description) + mitigation = 'To protect your virtual networks with Azure Firewall: 1. From the list below, select a network. Or select Take action if you\'ve arrived here from a specific virtual network page. 2. Follow the Azure Firewall deployment instructions. Make sure to configure all default routes properly.Important: Azure Firewall is billed separately from Azure Security Center. Learn more about Azure Firewall pricing.' + self.assertEqual(mitigation, finding.mitigation) + references = 'https://portal.azure.com/#blade/Microsoft_Azure_Security/RecommendationsBlade/assessmentKey/f67fb4ed-d481-44d7-91e5-efadf504f74a/resourceId/%2fsubscriptions%2f9cfbad7a-7369-42e4-bcce-7677c5b3a44b%2fresourcegroups%2fmy_resource_group%2fproviders%2fmicrosoft.network%2fvirtualnetworks%2fmy_virtual_network' + self.assertEqual(references, finding.references) + self.assertTrue(finding.static_finding) + self.assertFalse(finding.dynamic_finding) + unique_id_from_tool = '/subscriptions/9cfbad7a-7369-42e4-bcce-7677c5b3a44b/resourcegroups/my_resource_group/providers/microsoft.network/virtualnetworks/my_virtual_network/providers/Microsoft.Security/assessments/f67fb4ed-d481-44d7-91e5-efadf504f74a' + self.assertEqual(unique_id_from_tool, finding.unique_id_from_tool) + self.assertEqual('f67fb4ed-d481-44d7-91e5-efadf504f74a', finding.vuln_id_from_tool) - finding = findings[1] - self.assertEqual('My first subscription - Azure Defender for Resource Manager should be enabled', finding.title) - self.assertEqual(date.fromisoformat('2021-09-28'), finding.date) - self.assertEqual(1032, finding.cwe) - self.assertEqual('High', finding.severity) - description = '''**Recommendation:** Azure Defender for Resource Manager should be enabled + finding = findings[1] + self.assertEqual('My first subscription - Azure Defender for Resource Manager should be enabled', finding.title) + self.assertEqual(date.fromisoformat('2021-09-28'), finding.date) + self.assertEqual(1032, finding.cwe) + self.assertEqual('High', finding.severity) + description = '''**Recommendation:** Azure Defender for Resource Manager should be enabled **Resource Name:** My first subscription **Resource Type:** Subscription **Description:** Azure Defender for Resource Manager automatically monitors the resource management operations in your organization. Azure Defender detects threats and alerts you about suspicious activity. Learn more about the capabilities of Azure Defender for Resource Manager at https://aka.ms/defender-for-resource-manager . Enabling this Azure Defender plan results in charges. Learn about the pricing details per region on Security Center's pricing page: https://aka.ms/pricing-security-center . @@ -56,23 +56,23 @@ def test_parse_file_with_multiple_findings(self): **Subscription:** My first subscription **Subscription Id:** 9cfbad7a-7369-42e4-bcce-7677c5b3a44b **Native Cloud Account Id:** my_native_cloud_id''' - self.assertEqual(description, finding.description) - mitigation = 'To enable Azure Defender for Resource Manager on your subscription: 1. Open Security Center\'s Pricing & settings page. 2. Select the subscription on which you want to enable Azure Defender. 3. Under "Select Azure Defender plan by resource type", set "Resource Manager" to "On".' - self.assertEqual(mitigation, finding.mitigation) - references = 'https://portal.azure.com/#blade/Microsoft_Azure_Security/RecommendationsBlade/assessmentKey/f0fb2a7e-16d5-849f-be57-86db712e9bd0/resourceId/%2fsubscriptions%2f9cfbad7a-7369-42e4-bcce-7677c5b3a44b' - self.assertEqual(references, finding.references) - self.assertTrue(finding.static_finding) - self.assertFalse(finding.dynamic_finding) - unique_id_from_tool = '/subscriptions/9cfbad7a-7369-42e4-bcce-7677c5b3a44b/providers/Microsoft.Security/assessments/f0fb2a7e-16d5-849f-be57-86db712e9bd0' - self.assertEqual(unique_id_from_tool, finding.unique_id_from_tool) - self.assertEqual('f0fb2a7e-16d5-849f-be57-86db712e9bd0', finding.vuln_id_from_tool) + self.assertEqual(description, finding.description) + mitigation = 'To enable Azure Defender for Resource Manager on your subscription: 1. Open Security Center\'s Pricing & settings page. 2. Select the subscription on which you want to enable Azure Defender. 3. Under "Select Azure Defender plan by resource type", set "Resource Manager" to "On".' + self.assertEqual(mitigation, finding.mitigation) + references = 'https://portal.azure.com/#blade/Microsoft_Azure_Security/RecommendationsBlade/assessmentKey/f0fb2a7e-16d5-849f-be57-86db712e9bd0/resourceId/%2fsubscriptions%2f9cfbad7a-7369-42e4-bcce-7677c5b3a44b' + self.assertEqual(references, finding.references) + self.assertTrue(finding.static_finding) + self.assertFalse(finding.dynamic_finding) + unique_id_from_tool = '/subscriptions/9cfbad7a-7369-42e4-bcce-7677c5b3a44b/providers/Microsoft.Security/assessments/f0fb2a7e-16d5-849f-be57-86db712e9bd0' + self.assertEqual(unique_id_from_tool, finding.unique_id_from_tool) + self.assertEqual('f0fb2a7e-16d5-849f-be57-86db712e9bd0', finding.vuln_id_from_tool) - finding = findings[2] - self.assertEqual('swe10032201245e263h - Storage account should use a private link connection', finding.title) - self.assertEqual(date.fromisoformat('2021-09-28'), finding.date) - self.assertEqual(1032, finding.cwe) - self.assertEqual('Medium', finding.severity) - description = '''**Recommendation:** Storage account should use a private link connection + finding = findings[2] + self.assertEqual('swe10032201245e263h - Storage account should use a private link connection', finding.title) + self.assertEqual(date.fromisoformat('2021-09-28'), finding.date) + self.assertEqual(1032, finding.cwe) + self.assertEqual('Medium', finding.severity) + description = '''**Recommendation:** Storage account should use a private link connection **Resource Name:** swe10032201245e263h **Resource Type:** storageaccounts **Resource Group:** storage-westeurope @@ -80,13 +80,13 @@ def test_parse_file_with_multiple_findings(self): **Controls:** Restrict unauthorized network access **Subscription:** My first subscription **Subscription Id:** 9cfbad7a-7369-42e4-bcce-7677c5b3a44b''' - self.assertEqual(description, finding.description) - mitigation = 'To enforce secure communications for your storage accounts, add a private endpoint as described here: https://aka.ms/connectprivatelytostorageaccount.' - self.assertEqual(mitigation, finding.mitigation) - references = 'https://portal.azure.com/#blade/Microsoft_Azure_Security/RecommendationsBlade/assessmentKey/cdc78c07-02b0-4af0-1cb2-cb7c672a8b0a/resourceId/%2fsubscriptions%2f9cfbad7a-7369-42e4-bcce-7677c5b3a44b%2fresourcegroups%2fcloud-shell-storage-westeurope%2fproviders%2fmicrosoft.storage%2fstorageaccounts%2fswe10032201245e263h' - self.assertEqual(references, finding.references) - self.assertTrue(finding.static_finding) - self.assertFalse(finding.dynamic_finding) - unique_id_from_tool = '/subscriptions/9cfbad7a-7369-42e4-bcce-7677c5b3a44b/resourcegroups/cloud-shell-storage-westeurope/providers/microsoft.storage/storageaccounts/swe10032201245e263h/providers/Microsoft.Security/assessments/cdc78c07-02b0-4af0-1cb2-cb7c672a8b0a' - self.assertEqual(unique_id_from_tool, finding.unique_id_from_tool) - self.assertEqual('cdc78c07-02b0-4af0-1cb2-cb7c672a8b0a', finding.vuln_id_from_tool) + self.assertEqual(description, finding.description) + mitigation = 'To enforce secure communications for your storage accounts, add a private endpoint as described here: https://aka.ms/connectprivatelytostorageaccount.' + self.assertEqual(mitigation, finding.mitigation) + references = 'https://portal.azure.com/#blade/Microsoft_Azure_Security/RecommendationsBlade/assessmentKey/cdc78c07-02b0-4af0-1cb2-cb7c672a8b0a/resourceId/%2fsubscriptions%2f9cfbad7a-7369-42e4-bcce-7677c5b3a44b%2fresourcegroups%2fcloud-shell-storage-westeurope%2fproviders%2fmicrosoft.storage%2fstorageaccounts%2fswe10032201245e263h' + self.assertEqual(references, finding.references) + self.assertTrue(finding.static_finding) + self.assertFalse(finding.dynamic_finding) + unique_id_from_tool = '/subscriptions/9cfbad7a-7369-42e4-bcce-7677c5b3a44b/resourcegroups/cloud-shell-storage-westeurope/providers/microsoft.storage/storageaccounts/swe10032201245e263h/providers/Microsoft.Security/assessments/cdc78c07-02b0-4af0-1cb2-cb7c672a8b0a' + self.assertEqual(unique_id_from_tool, finding.unique_id_from_tool) + self.assertEqual('cdc78c07-02b0-4af0-1cb2-cb7c672a8b0a', finding.vuln_id_from_tool) diff --git a/unittests/tools/test_bandit_parser.py b/unittests/tools/test_bandit_parser.py index 48813c9da5..4249d7beb9 100644 --- a/unittests/tools/test_bandit_parser.py +++ b/unittests/tools/test_bandit_parser.py @@ -8,98 +8,94 @@ class TestBanditParser(DojoTestCase): def test_bandit_parser_has_no_finding(self): - testfile = open("unittests/scans/bandit/no_vuln.json") - parser = BanditParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/bandit/no_vuln.json") as testfile: + parser = BanditParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_bandit_parser_has_one_finding(self): - testfile = open("unittests/scans/bandit/one_vuln.json") - parser = BanditParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1, len(findings)) - with self.subTest(i=0): - item = findings[0] - self.assertEqual( - "Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.", - item.title, - ) - self.assertEqual(datetime.datetime(2020, 12, 30, 10, 3, 39, tzinfo=tzlocal()), item.date) - self.assertEqual("Low", item.severity) - self.assertEqual("one/one.py", item.file_path) - self.assertEqual("assert_used:B101", item.vuln_id_from_tool) - self.assertEqual("Certain", item.get_scanner_confidence_text()) - self.assertIn("https://bandit.readthedocs.io/en/latest/plugins/b101_assert_used.html", item.references) + with open("unittests/scans/bandit/one_vuln.json") as testfile: + parser = BanditParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + with self.subTest(i=0): + item = findings[0] + self.assertEqual( + "Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.", + item.title, + ) + self.assertEqual(datetime.datetime(2020, 12, 30, 10, 3, 39, tzinfo=tzlocal()), item.date) + self.assertEqual("Low", item.severity) + self.assertEqual("one/one.py", item.file_path) + self.assertEqual("assert_used:B101", item.vuln_id_from_tool) + self.assertEqual("Certain", item.get_scanner_confidence_text()) + self.assertIn("https://bandit.readthedocs.io/en/latest/plugins/b101_assert_used.html", item.references) def test_bandit_parser_has_many_findings(self): - testfile = open("unittests/scans/bandit/many_vulns.json") - parser = BanditParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(214, len(findings)) - with self.subTest(i=0): - item = findings[0] - self.assertEqual("Try, Except, Pass detected.", item.title) - self.assertEqual(datetime.datetime(2020, 12, 30, 9, 35, 48, tzinfo=tzlocal()), item.date) - self.assertEqual("Low", item.severity) - self.assertEqual("dojo/benchmark\\views.py", item.file_path) - self.assertEqual("try_except_pass:B110", item.vuln_id_from_tool) - self.assertEqual("Certain", item.get_scanner_confidence_text()) - self.assertIn("https://bandit.readthedocs.io/en/latest/plugins/b110_try_except_pass.html", item.references) + with open("unittests/scans/bandit/many_vulns.json") as testfile: + parser = BanditParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(214, len(findings)) + with self.subTest(i=0): + item = findings[0] + self.assertEqual("Try, Except, Pass detected.", item.title) + self.assertEqual(datetime.datetime(2020, 12, 30, 9, 35, 48, tzinfo=tzlocal()), item.date) + self.assertEqual("Low", item.severity) + self.assertEqual("dojo/benchmark\\views.py", item.file_path) + self.assertEqual("try_except_pass:B110", item.vuln_id_from_tool) + self.assertEqual("Certain", item.get_scanner_confidence_text()) + self.assertIn("https://bandit.readthedocs.io/en/latest/plugins/b110_try_except_pass.html", item.references) def test_bandit_parser_has_many_findings_recent(self): - testfile = open("unittests/scans/bandit/dd.json") - parser = BanditParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(47, len(findings)) - with self.subTest(i=0): - item = findings[0] - self.assertEqual("Use of insecure MD2, MD4, MD5, or SHA1 hash function.", item.title) - self.assertEqual(datetime.datetime(2021, 3, 30, 18, 23, 12, tzinfo=tzlocal()), item.date) - self.assertEqual("Medium", item.severity) - self.assertEqual("dojo/tools/acunetix/parser.py", item.file_path) - self.assertEqual("blacklist:B303", item.vuln_id_from_tool) - self.assertEqual("Certain", item.get_scanner_confidence_text()) + with open("unittests/scans/bandit/dd.json") as testfile: + parser = BanditParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(47, len(findings)) + with self.subTest(i=0): + item = findings[0] + self.assertEqual("Use of insecure MD2, MD4, MD5, or SHA1 hash function.", item.title) + self.assertEqual(datetime.datetime(2021, 3, 30, 18, 23, 12, tzinfo=tzlocal()), item.date) + self.assertEqual("Medium", item.severity) + self.assertEqual("dojo/tools/acunetix/parser.py", item.file_path) + self.assertEqual("blacklist:B303", item.vuln_id_from_tool) + self.assertEqual("Certain", item.get_scanner_confidence_text()) def test_bandit_parser_has_many_findings_recent2(self): - testfile = open("unittests/scans/bandit/dd2.json") - parser = BanditParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(165, len(findings)) - with self.subTest(i=0): - item = findings[0] - self.assertEqual("Try, Except, Pass detected.", item.title) - self.assertEqual(datetime.datetime(2021, 10, 3, 12, 53, 18, tzinfo=tzlocal()), item.date) - self.assertEqual("Low", item.severity) - self.assertEqual("dojo/benchmark/views.py", item.file_path) - self.assertEqual("try_except_pass:B110", item.vuln_id_from_tool) - self.assertEqual("Certain", item.get_scanner_confidence_text()) - with self.subTest(i=50): - item = findings[50] - self.assertEqual( - "Use of mark_safe() may expose cross-site scripting vulnerabilities and should be reviewed.", item.title - ) - self.assertEqual(datetime.datetime(2021, 10, 3, 12, 53, 18, tzinfo=tzlocal()), item.date) - self.assertEqual("Medium", item.severity) - self.assertEqual("dojo/reports/widgets.py", item.file_path) - self.assertEqual("blacklist:B308", item.vuln_id_from_tool) - self.assertEqual("Certain", item.get_scanner_confidence_text()) - with self.subTest(i=100): - item = findings[100] - self.assertEqual("Potential XSS on mark_safe function.", item.title) - self.assertEqual(datetime.datetime(2021, 10, 3, 12, 53, 18, tzinfo=tzlocal()), item.date) - self.assertEqual("Medium", item.severity) - self.assertEqual("dojo/templatetags/display_tags.py", item.file_path) - self.assertEqual("django_mark_safe:B703", item.vuln_id_from_tool) - self.assertEqual("Certain", item.get_scanner_confidence_text()) - with self.subTest(i=164): - item = findings[164] - self.assertEqual("Possible binding to all interfaces.", item.title) - self.assertEqual(datetime.datetime(2021, 10, 3, 12, 53, 18, tzinfo=tzlocal()), item.date) - self.assertEqual("Medium", item.severity) - self.assertEqual("dojo/wsgi.py", item.file_path) - self.assertEqual("hardcoded_bind_all_interfaces:B104", item.vuln_id_from_tool) - self.assertEqual("Firm", item.get_scanner_confidence_text()) + with open("unittests/scans/bandit/dd2.json") as testfile: + parser = BanditParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(165, len(findings)) + with self.subTest(i=0): + item = findings[0] + self.assertEqual("Try, Except, Pass detected.", item.title) + self.assertEqual(datetime.datetime(2021, 10, 3, 12, 53, 18, tzinfo=tzlocal()), item.date) + self.assertEqual("Low", item.severity) + self.assertEqual("dojo/benchmark/views.py", item.file_path) + self.assertEqual("try_except_pass:B110", item.vuln_id_from_tool) + self.assertEqual("Certain", item.get_scanner_confidence_text()) + with self.subTest(i=50): + item = findings[50] + self.assertEqual( + "Use of mark_safe() may expose cross-site scripting vulnerabilities and should be reviewed.", item.title + ) + self.assertEqual(datetime.datetime(2021, 10, 3, 12, 53, 18, tzinfo=tzlocal()), item.date) + self.assertEqual("Medium", item.severity) + self.assertEqual("dojo/reports/widgets.py", item.file_path) + self.assertEqual("blacklist:B308", item.vuln_id_from_tool) + self.assertEqual("Certain", item.get_scanner_confidence_text()) + with self.subTest(i=100): + item = findings[100] + self.assertEqual("Potential XSS on mark_safe function.", item.title) + self.assertEqual(datetime.datetime(2021, 10, 3, 12, 53, 18, tzinfo=tzlocal()), item.date) + self.assertEqual("Medium", item.severity) + self.assertEqual("dojo/templatetags/display_tags.py", item.file_path) + self.assertEqual("django_mark_safe:B703", item.vuln_id_from_tool) + self.assertEqual("Certain", item.get_scanner_confidence_text()) + with self.subTest(i=164): + item = findings[164] + self.assertEqual("Possible binding to all interfaces.", item.title) + self.assertEqual(datetime.datetime(2021, 10, 3, 12, 53, 18, tzinfo=tzlocal()), item.date) + self.assertEqual("Medium", item.severity) + self.assertEqual("dojo/wsgi.py", item.file_path) + self.assertEqual("hardcoded_bind_all_interfaces:B104", item.vuln_id_from_tool) + self.assertEqual("Firm", item.get_scanner_confidence_text()) diff --git a/unittests/tools/test_brakeman_parser.py b/unittests/tools/test_brakeman_parser.py index c6510f9ac2..ca07945656 100644 --- a/unittests/tools/test_brakeman_parser.py +++ b/unittests/tools/test_brakeman_parser.py @@ -6,21 +6,19 @@ class TestBrakemanParser(DojoTestCase): def test_parse_file_no_finding(self): - testfile = open("unittests/scans/brakeman/no_finding.json") - parser = BrakemanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/brakeman/no_finding.json") as testfile: + parser = BrakemanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_has_two_findings(self): - testfile = open("unittests/scans/brakeman/two_findings.json") - parser = BrakemanParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(2, len(findings)) + with open("unittests/scans/brakeman/two_findings.json") as testfile: + parser = BrakemanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(2, len(findings)) def test_parse_file_has_many_findings(self): - testfile = open("unittests/scans/brakeman/many_findings.json") - parser = BrakemanParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(18, len(findings)) + with open("unittests/scans/brakeman/many_findings.json") as testfile: + parser = BrakemanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(18, len(findings)) diff --git a/unittests/tools/test_bugcrowd_parser.py b/unittests/tools/test_bugcrowd_parser.py index 16bd45b76c..ab5fce2027 100644 --- a/unittests/tools/test_bugcrowd_parser.py +++ b/unittests/tools/test_bugcrowd_parser.py @@ -7,29 +7,29 @@ class TestBugCrowdParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/bugcrowd/BugCrowd-zero.csv") - parser = BugCrowdParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(0, len(findings)) + with open("unittests/scans/bugcrowd/BugCrowd-zero.csv") as testfile: + parser = BugCrowdParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_findings(self): - testfile = open("unittests/scans/bugcrowd/BugCrowd-one.csv") - parser = BugCrowdParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - self.assertEqual(findings[0].date, datetime(2020, 3, 1, 6, 15, 6, tzinfo=timezone.utc)) + with open("unittests/scans/bugcrowd/BugCrowd-one.csv") as testfile: + parser = BugCrowdParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + self.assertEqual(findings[0].date, datetime(2020, 3, 1, 6, 15, 6, tzinfo=timezone.utc)) def test_parse_file_with_multiple_vuln_has_multiple_finding(self): - testfile = open("unittests/scans/bugcrowd/BugCrowd-many.csv") - parser = BugCrowdParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(5, len(findings)) + with open("unittests/scans/bugcrowd/BugCrowd-many.csv") as testfile: + parser = BugCrowdParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(5, len(findings)) diff --git a/unittests/tools/test_cargo_audit_parser.py b/unittests/tools/test_cargo_audit_parser.py index b180dc82ca..2b4fc2119a 100644 --- a/unittests/tools/test_cargo_audit_parser.py +++ b/unittests/tools/test_cargo_audit_parser.py @@ -6,73 +6,73 @@ class TestCargoAuditParser(DojoTestCase): def test_parse_no_findings(self): - testfile = open("unittests/scans/cargo_audit/no_findings.json") - parser = CargoAuditParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/cargo_audit/no_findings.json") as testfile: + parser = CargoAuditParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_many_findings(self): - testfile = open("unittests/scans/cargo_audit/many_findings.json") - parser = CargoAuditParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(4, len(findings)) + with open("unittests/scans/cargo_audit/many_findings.json") as testfile: + parser = CargoAuditParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(4, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("[arc-swap 0.4.7] Dangling reference in `access::Map` with Constant", finding.title) - self.assertEqual("High", finding.severity) - self.assertIsNotNone(finding.description) - self.assertEqual(["dangling reference"], finding.tags) - self.assertEqual("arc-swap", finding.component_name) - self.assertEqual("0.4.7", finding.component_version) - self.assertEqual("RUSTSEC-2020-0091", finding.vuln_id_from_tool) - self.assertEqual("2020-12-10", finding.publish_date) - self.assertEqual(1, finding.nb_occurences) - self.assertEqual(2, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("RUSTSEC-2020-0091", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("CVE-2020-35711", finding.unsaved_vulnerability_ids[1]) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("[arc-swap 0.4.7] Dangling reference in `access::Map` with Constant", finding.title) + self.assertEqual("High", finding.severity) + self.assertIsNotNone(finding.description) + self.assertEqual(["dangling reference"], finding.tags) + self.assertEqual("arc-swap", finding.component_name) + self.assertEqual("0.4.7", finding.component_version) + self.assertEqual("RUSTSEC-2020-0091", finding.vuln_id_from_tool) + self.assertEqual("2020-12-10", finding.publish_date) + self.assertEqual(1, finding.nb_occurences) + self.assertEqual(2, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("RUSTSEC-2020-0091", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("CVE-2020-35711", finding.unsaved_vulnerability_ids[1]) - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("[hyper 0.13.9] Multiple Transfer-Encoding headers misinterprets request payload", finding.title) - self.assertEqual("High", finding.severity) - self.assertIsNotNone(finding.description) - self.assertEqual(["http", "request-smuggling"], finding.tags) - self.assertEqual("hyper", finding.component_name) - self.assertEqual("0.13.9", finding.component_version) - self.assertEqual("RUSTSEC-2021-0020", finding.vuln_id_from_tool) - self.assertEqual("2021-02-05", finding.publish_date) - self.assertEqual(1, finding.nb_occurences) - self.assertEqual(2, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("RUSTSEC-2021-0020", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("CVE-2021-21299", finding.unsaved_vulnerability_ids[1]) + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("[hyper 0.13.9] Multiple Transfer-Encoding headers misinterprets request payload", finding.title) + self.assertEqual("High", finding.severity) + self.assertIsNotNone(finding.description) + self.assertEqual(["http", "request-smuggling"], finding.tags) + self.assertEqual("hyper", finding.component_name) + self.assertEqual("0.13.9", finding.component_version) + self.assertEqual("RUSTSEC-2021-0020", finding.vuln_id_from_tool) + self.assertEqual("2021-02-05", finding.publish_date) + self.assertEqual(1, finding.nb_occurences) + self.assertEqual(2, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("RUSTSEC-2021-0020", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("CVE-2021-21299", finding.unsaved_vulnerability_ids[1]) - with self.subTest(i=2): - finding = findings[2] - self.assertEqual("[smallvec 0.6.13] Buffer overflow in SmallVec::insert_many", finding.title) - self.assertEqual("High", finding.severity) - self.assertIsNotNone(finding.description) - self.assertEqual(["buffer-overflow", "heap-overflow", "unsound"], finding.tags) - self.assertEqual("smallvec", finding.component_name) - self.assertEqual("0.6.13", finding.component_version) - self.assertEqual("RUSTSEC-2021-0003", finding.vuln_id_from_tool) - self.assertEqual("2021-01-08", finding.publish_date) - self.assertEqual(1, finding.nb_occurences) - self.assertEqual(2, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("RUSTSEC-2021-0003", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("CVE-2021-25900", finding.unsaved_vulnerability_ids[1]) + with self.subTest(i=2): + finding = findings[2] + self.assertEqual("[smallvec 0.6.13] Buffer overflow in SmallVec::insert_many", finding.title) + self.assertEqual("High", finding.severity) + self.assertIsNotNone(finding.description) + self.assertEqual(["buffer-overflow", "heap-overflow", "unsound"], finding.tags) + self.assertEqual("smallvec", finding.component_name) + self.assertEqual("0.6.13", finding.component_version) + self.assertEqual("RUSTSEC-2021-0003", finding.vuln_id_from_tool) + self.assertEqual("2021-01-08", finding.publish_date) + self.assertEqual(1, finding.nb_occurences) + self.assertEqual(2, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("RUSTSEC-2021-0003", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("CVE-2021-25900", finding.unsaved_vulnerability_ids[1]) - with self.subTest(i=3): - finding = findings[3] - self.assertEqual("[smallvec 1.5.0] Buffer overflow in SmallVec::insert_many", finding.title) - self.assertEqual("High", finding.severity) - self.assertIsNotNone(finding.description) - self.assertEqual(["buffer-overflow", "heap-overflow", "unsound"], finding.tags) - self.assertEqual("smallvec", finding.component_name) - self.assertEqual("1.5.0", finding.component_version) - self.assertEqual("RUSTSEC-2021-0003", finding.vuln_id_from_tool) - self.assertEqual("2021-01-08", finding.publish_date) - self.assertEqual(1, finding.nb_occurences) - self.assertEqual(2, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("RUSTSEC-2021-0003", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("CVE-2021-25900", finding.unsaved_vulnerability_ids[1]) + with self.subTest(i=3): + finding = findings[3] + self.assertEqual("[smallvec 1.5.0] Buffer overflow in SmallVec::insert_many", finding.title) + self.assertEqual("High", finding.severity) + self.assertIsNotNone(finding.description) + self.assertEqual(["buffer-overflow", "heap-overflow", "unsound"], finding.tags) + self.assertEqual("smallvec", finding.component_name) + self.assertEqual("1.5.0", finding.component_version) + self.assertEqual("RUSTSEC-2021-0003", finding.vuln_id_from_tool) + self.assertEqual("2021-01-08", finding.publish_date) + self.assertEqual(1, finding.nb_occurences) + self.assertEqual(2, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("RUSTSEC-2021-0003", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("CVE-2021-25900", finding.unsaved_vulnerability_ids[1]) diff --git a/unittests/tools/test_checkmarx_osa_parser.py b/unittests/tools/test_checkmarx_osa_parser.py index 5fbf474ce2..6002e8da16 100644 --- a/unittests/tools/test_checkmarx_osa_parser.py +++ b/unittests/tools/test_checkmarx_osa_parser.py @@ -185,9 +185,10 @@ def test_checkmarx_osa_parse_file_with_no_libraryId_raises_ValueError( my_file_handle, _product, _engagement, test = self.init( get_unit_tests_path() + "/scans/checkmarx_osa/single_finding_no_libraryId.json" ) - parser = CheckmarxOsaParser() - parser.get_findings(my_file_handle, test) - self.teardown(my_file_handle) + with my_file_handle: + parser = CheckmarxOsaParser() + parser.get_findings(my_file_handle, test) + self.assertEqual( "Invalid format: missing mandatory field libraryId", str(context.exception) ) diff --git a/unittests/tools/test_checkov_parser.py b/unittests/tools/test_checkov_parser.py index 29585978e6..9cfdbf91e5 100644 --- a/unittests/tools/test_checkov_parser.py +++ b/unittests/tools/test_checkov_parser.py @@ -6,85 +6,85 @@ class TestCheckovParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/checkov/checkov-report-0-vuln.json") - parser = CheckovParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/checkov/checkov-report-0-vuln.json") as testfile: + parser = CheckovParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_no_vuln_has_no_findings_v2(self): - testfile = open("unittests/scans/checkov/checkov2-report-0-vuln.json") - parser = CheckovParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/checkov/checkov2-report-0-vuln.json") as testfile: + parser = CheckovParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_finding(self): - testfile = open("unittests/scans/checkov/checkov-report-1-vuln.json") - parser = CheckovParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) + with open("unittests/scans/checkov/checkov-report-1-vuln.json") as testfile: + parser = CheckovParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) def test_parse_file_with_multiple_vuln_has_multiple_findings(self): - testfile = open("unittests/scans/checkov/checkov-report-many-vuln.json") - parser = CheckovParser() - findings = parser.get_findings(testfile, Test()) - self.assertGreater(len(findings), 2) + with open("unittests/scans/checkov/checkov-report-many-vuln.json") as testfile: + parser = CheckovParser() + findings = parser.get_findings(testfile, Test()) + self.assertGreater(len(findings), 2) def test_parse_file_with_multiple_check_type_has_multiple_check_type(self): - testfile = open("unittests/scans/checkov/checkov-report-multiple-check_type.json") - parser = CheckovParser() - findings = parser.get_findings(testfile, Test()) + with open("unittests/scans/checkov/checkov-report-multiple-check_type.json") as testfile: + parser = CheckovParser() + findings = parser.get_findings(testfile, Test()) - # Number of findings - self.assertEqual(13, len(findings)) - terraform_findings_amount = 0 - dockerfile_findings_amount = 0 - for finding in findings: - if 'Check Type: terraform' in finding.description: - terraform_findings_amount += 1 - elif 'Check Type: dockerfile' in finding.description: - dockerfile_findings_amount += 1 - self.assertEqual(11, terraform_findings_amount) - self.assertEqual(2, dockerfile_findings_amount) + # Number of findings + self.assertEqual(13, len(findings)) + terraform_findings_amount = 0 + dockerfile_findings_amount = 0 + for finding in findings: + if 'Check Type: terraform' in finding.description: + terraform_findings_amount += 1 + elif 'Check Type: dockerfile' in finding.description: + dockerfile_findings_amount += 1 + self.assertEqual(11, terraform_findings_amount) + self.assertEqual(2, dockerfile_findings_amount) - # Terraform - first_terraform_finding = findings[0] - self.assertEqual('Medium', first_terraform_finding.severity) - self.assertEqual( - 'Check Type: terraform\n' - 'Check Id: CKV_AWS_161\n' - 'Ensure RDS database has IAM authentication enabled\n', - first_terraform_finding.description - ) - self.assertEqual('/aws/db-app.tf', first_terraform_finding.file_path) - self.assertEqual(1, first_terraform_finding.line) - self.assertEqual('aws_db_instance.default', first_terraform_finding.component_name) - self.assertEqual('', first_terraform_finding.mitigation) - self.assertEqual('', first_terraform_finding.references) + # Terraform + first_terraform_finding = findings[0] + self.assertEqual('Medium', first_terraform_finding.severity) + self.assertEqual( + 'Check Type: terraform\n' + 'Check Id: CKV_AWS_161\n' + 'Ensure RDS database has IAM authentication enabled\n', + first_terraform_finding.description + ) + self.assertEqual('/aws/db-app.tf', first_terraform_finding.file_path) + self.assertEqual(1, first_terraform_finding.line) + self.assertEqual('aws_db_instance.default', first_terraform_finding.component_name) + self.assertEqual('', first_terraform_finding.mitigation) + self.assertEqual('', first_terraform_finding.references) - # Dockerfile - first_dockerfile_finding = findings[11] - self.assertEqual('Medium', first_dockerfile_finding.severity) - self.assertEqual( - 'Check Type: dockerfile\n' - 'Check Id: CKV_DOCKER_3\n' - 'Ensure that a user for the container has been created\n', - first_dockerfile_finding.description - ) - self.assertEqual('/aws/resources/Dockerfile', first_dockerfile_finding.file_path) - self.assertEqual(0, first_dockerfile_finding.line) - self.assertEqual('/aws/resources/Dockerfile.', first_dockerfile_finding.component_name) - self.assertEqual('', first_dockerfile_finding.mitigation) - self.assertEqual( - 'https://docs.bridgecrew.io/docs/ensure-that-a-user-for-the-container-has-been-created', - first_dockerfile_finding.references - ) + # Dockerfile + first_dockerfile_finding = findings[11] + self.assertEqual('Medium', first_dockerfile_finding.severity) + self.assertEqual( + 'Check Type: dockerfile\n' + 'Check Id: CKV_DOCKER_3\n' + 'Ensure that a user for the container has been created\n', + first_dockerfile_finding.description + ) + self.assertEqual('/aws/resources/Dockerfile', first_dockerfile_finding.file_path) + self.assertEqual(0, first_dockerfile_finding.line) + self.assertEqual('/aws/resources/Dockerfile.', first_dockerfile_finding.component_name) + self.assertEqual('', first_dockerfile_finding.mitigation) + self.assertEqual( + 'https://docs.bridgecrew.io/docs/ensure-that-a-user-for-the-container-has-been-created', + first_dockerfile_finding.references + ) def test_parse_file_with_specified_severity(self): - testfile = open("unittests/scans/checkov/checkov-report-severity.json") - parser = CheckovParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(4, len(findings)) - self.assertEqual("Medium", findings[0].severity) - self.assertEqual("Medium", findings[1].severity) - self.assertEqual("Low", findings[2].severity) - self.assertEqual("High", findings[3].severity) + with open("unittests/scans/checkov/checkov-report-severity.json") as testfile: + parser = CheckovParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(4, len(findings)) + self.assertEqual("Medium", findings[0].severity) + self.assertEqual("Medium", findings[1].severity) + self.assertEqual("Low", findings[2].severity) + self.assertEqual("High", findings[3].severity) diff --git a/unittests/tools/test_chefinspect_parser.py b/unittests/tools/test_chefinspect_parser.py index 14a1bbb902..1dde5af4d9 100644 --- a/unittests/tools/test_chefinspect_parser.py +++ b/unittests/tools/test_chefinspect_parser.py @@ -6,19 +6,19 @@ class TestChefInspectParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/chefinspect/no_finding.log") - parser = ChefInspectParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/chefinspect/no_finding.log") as testfile: + parser = ChefInspectParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_finding(self): - testfile = open("unittests/scans/chefinspect/one_finding.log") - parser = ChefInspectParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) + with open("unittests/scans/chefinspect/one_finding.log") as testfile: + parser = ChefInspectParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) def test_parse_file_with_multiple_vuln_has_multiple_findings(self): - testfile = open("unittests/scans/chefinspect/many_findings.log") - parser = ChefInspectParser() - findings = parser.get_findings(testfile, Test()) - self.assertTrue(10, len(findings)) + with open("unittests/scans/chefinspect/many_findings.log") as testfile: + parser = ChefInspectParser() + findings = parser.get_findings(testfile, Test()) + self.assertTrue(10, len(findings)) diff --git a/unittests/tools/test_cobalt_parser.py b/unittests/tools/test_cobalt_parser.py index a32929f888..1a5235fada 100644 --- a/unittests/tools/test_cobalt_parser.py +++ b/unittests/tools/test_cobalt_parser.py @@ -7,19 +7,19 @@ class TestCobaltParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/cobalt/cobalt_no_vuln.csv") - parser = CobaltParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/cobalt/cobalt_no_vuln.csv") as testfile: + parser = CobaltParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_findings(self): - testfile = open("unittests/scans/cobalt/cobalt_one_vuln.csv") - parser = CobaltParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) + with open("unittests/scans/cobalt/cobalt_one_vuln.csv") as testfile: + parser = CobaltParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) def test_parse_file_with_multiple_vuln_has_multiple_finding(self): - testfile = open("unittests/scans/cobalt/cobalt_many_vuln.csv") - parser = CobaltParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(9, len(findings)) + with open("unittests/scans/cobalt/cobalt_many_vuln.csv") as testfile: + parser = CobaltParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(9, len(findings)) diff --git a/unittests/tools/test_codechecker_parser.py b/unittests/tools/test_codechecker_parser.py index 23094751aa..2aa53c51ae 100644 --- a/unittests/tools/test_codechecker_parser.py +++ b/unittests/tools/test_codechecker_parser.py @@ -6,94 +6,94 @@ class TestCodeCheckerParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/codechecker/cc-report-0-vuln.json" - ) - parser = CodeCheckerParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + ) as testfile: + parser = CodeCheckerParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_finding(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/codechecker/cc-report-1-vuln.json" - ) - parser = CodeCheckerParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("clang-diagnostic-sign-compare", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertEqual("/opt/_ga/openvpn/src/openvpn/push.c", finding.file_path) - self.assertEqual("/opt/_ga/openvpn/src/openvpn/push.c", finding.sast_source_file_path) - self.assertEqual(576, finding.line) - self.assertEqual(576, finding.sast_source_line) - self.assertFalse(finding.verified) - self.assertFalse(finding.false_p) - self.assertFalse(finding.risk_accepted) + ) as testfile: + parser = CodeCheckerParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("clang-diagnostic-sign-compare", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertEqual("/opt/_ga/openvpn/src/openvpn/push.c", finding.file_path) + self.assertEqual("/opt/_ga/openvpn/src/openvpn/push.c", finding.sast_source_file_path) + self.assertEqual(576, finding.line) + self.assertEqual(576, finding.sast_source_line) + self.assertFalse(finding.verified) + self.assertFalse(finding.false_p) + self.assertFalse(finding.risk_accepted) def test_parse_file_with_multiple_vuln_has_multiple_findings(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/codechecker/cc-report-many-vuln.json" - ) - parser = CodeCheckerParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(94, len(findings), str(len(findings))) + ) as testfile: + parser = CodeCheckerParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(94, len(findings), str(len(findings))) - self.assertEqual(sum(1 for f in findings if f.duplicate), 0) - self.assertEqual(sum(1 for f in findings if f.severity.upper() == 'HIGH'), 20) - self.assertEqual(sum(1 for f in findings if f.severity.upper() == 'INFO'), 6) - self.assertEqual(sum(1 for f in findings if f.severity.upper() == 'CRITICAL'), 0) - self.assertEqual(sum(1 for f in findings if f.severity.upper() == 'LOW'), 5) - self.assertEqual(sum(1 for f in findings if f.severity.upper() == 'MEDIUM'), 63) + self.assertEqual(sum(1 for f in findings if f.duplicate), 0) + self.assertEqual(sum(1 for f in findings if f.severity.upper() == 'HIGH'), 20) + self.assertEqual(sum(1 for f in findings if f.severity.upper() == 'INFO'), 6) + self.assertEqual(sum(1 for f in findings if f.severity.upper() == 'CRITICAL'), 0) + self.assertEqual(sum(1 for f in findings if f.severity.upper() == 'LOW'), 5) + self.assertEqual(sum(1 for f in findings if f.severity.upper() == 'MEDIUM'), 63) - finding = findings[0] - self.assertEqual("clang-diagnostic-sign-compare", finding.title) - self.assertEqual("Medium", finding.severity) + finding = findings[0] + self.assertEqual("clang-diagnostic-sign-compare", finding.title) + self.assertEqual("Medium", finding.severity) - finding = findings[22] - self.assertEqual("deadcode.DeadStores", finding.title) - self.assertEqual("Low", finding.severity) + finding = findings[22] + self.assertEqual("deadcode.DeadStores", finding.title) + self.assertEqual("Low", finding.severity) - finding = findings[93] - self.assertEqual("core.NullDereference", finding.title) - self.assertEqual("High", finding.severity) + finding = findings[93] + self.assertEqual("core.NullDereference", finding.title) + self.assertEqual("High", finding.severity) def test_parse_file_with_various_review_statuses(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/codechecker/cc-report-review-status.json" - ) - parser = CodeCheckerParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(len(findings), 4) + ) as testfile: + parser = CodeCheckerParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(len(findings), 4) - finding = findings[0] - self.assertTrue(finding.active) - self.assertFalse(finding.verified) - self.assertFalse(finding.risk_accepted) - self.assertFalse(finding.false_p) - self.assertEqual(576, finding.line) - self.assertEqual("/opt/_ga/openvpn/src/openvpn/push.c", finding.file_path) + finding = findings[0] + self.assertTrue(finding.active) + self.assertFalse(finding.verified) + self.assertFalse(finding.risk_accepted) + self.assertFalse(finding.false_p) + self.assertEqual(576, finding.line) + self.assertEqual("/opt/_ga/openvpn/src/openvpn/push.c", finding.file_path) - finding = findings[1] - self.assertTrue(finding.active) - self.assertTrue(finding.verified) - self.assertFalse(finding.risk_accepted) - self.assertFalse(finding.false_p) - self.assertEqual(679, finding.line) - self.assertEqual("/opt/_ga/openvpn/src/openvpn/push.c", finding.file_path) + finding = findings[1] + self.assertTrue(finding.active) + self.assertTrue(finding.verified) + self.assertFalse(finding.risk_accepted) + self.assertFalse(finding.false_p) + self.assertEqual(679, finding.line) + self.assertEqual("/opt/_ga/openvpn/src/openvpn/push.c", finding.file_path) - finding = findings[2] - self.assertFalse(finding.active) - self.assertFalse(finding.verified) - self.assertFalse(finding.risk_accepted) - self.assertTrue(finding.false_p) - self.assertEqual(402, finding.line) - self.assertEqual("/opt/_ga/openvpn/src/openvpn/multi.h", finding.file_path) + finding = findings[2] + self.assertFalse(finding.active) + self.assertFalse(finding.verified) + self.assertFalse(finding.risk_accepted) + self.assertTrue(finding.false_p) + self.assertEqual(402, finding.line) + self.assertEqual("/opt/_ga/openvpn/src/openvpn/multi.h", finding.file_path) - finding = findings[3] - self.assertFalse(finding.active) - self.assertFalse(finding.verified) - self.assertTrue(finding.risk_accepted) - self.assertFalse(finding.false_p) - self.assertEqual(91, finding.line) - self.assertEqual("/opt/_ga/openvpn/src/openvpn/vlan.c", finding.file_path) + finding = findings[3] + self.assertFalse(finding.active) + self.assertFalse(finding.verified) + self.assertTrue(finding.risk_accepted) + self.assertFalse(finding.false_p) + self.assertEqual(91, finding.line) + self.assertEqual("/opt/_ga/openvpn/src/openvpn/vlan.c", finding.file_path) diff --git a/unittests/tools/test_contrast_parser.py b/unittests/tools/test_contrast_parser.py index 26a57ba0ca..4e31c09e37 100644 --- a/unittests/tools/test_contrast_parser.py +++ b/unittests/tools/test_contrast_parser.py @@ -12,63 +12,63 @@ def test_example_report(self): test = Test() test.engagement = Engagement() test.engagement.product = Product() - testfile = open("unittests/scans/contrast/contrast-node-goat.csv") - parser = ContrastParser() - findings = parser.get_findings(testfile, test) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(18, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Info", finding.severity) - self.assertEqual("Forms Without Autocomplete Prevention on 2 pages", finding.title) - self.assertEqual("OMEC-Y0TI-FRLE-FJQQ", finding.unique_id_from_tool) - self.assertEqual(522, finding.cwe) - self.assertEqual(datetime.date(2018, 4, 23), finding.date.date()) - # endpoints - self.assertIsNotNone(finding.unsaved_endpoints) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual('http', endpoint.protocol) - self.assertEqual('0.0.0.0', endpoint.host) - self.assertEqual('WebGoat/login.mvc', endpoint.path) - with self.subTest(i=11): - finding = findings[11] - self.assertEqual(datetime.date(2018, 4, 23), finding.date.date()) - self.assertEqual("High", finding.severity) - self.assertEqual("path-traversal", finding.vuln_id_from_tool) - self.assertIsNone(finding.unique_id_from_tool) # aggregated finding - self.assertEqual(4, finding.nb_occurences) - self.assertEqual(22, finding.cwe) - # endpoints - self.assertIsNotNone(finding.unsaved_endpoints) - self.assertEqual(4, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual('http', endpoint.protocol) - self.assertEqual('0.0.0.0', endpoint.host) - self.assertEqual('WebGoat/services/SoapRequest', endpoint.path) - endpoint = finding.unsaved_endpoints[1] - self.assertEqual('http', endpoint.protocol) - self.assertEqual('0.0.0.0', endpoint.host) - self.assertEqual('WebGoat/attack', endpoint.path) + with open("unittests/scans/contrast/contrast-node-goat.csv") as testfile: + parser = ContrastParser() + findings = parser.get_findings(testfile, test) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(18, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Info", finding.severity) + self.assertEqual("Forms Without Autocomplete Prevention on 2 pages", finding.title) + self.assertEqual("OMEC-Y0TI-FRLE-FJQQ", finding.unique_id_from_tool) + self.assertEqual(522, finding.cwe) + self.assertEqual(datetime.date(2018, 4, 23), finding.date.date()) + # endpoints + self.assertIsNotNone(finding.unsaved_endpoints) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual('http', endpoint.protocol) + self.assertEqual('0.0.0.0', endpoint.host) + self.assertEqual('WebGoat/login.mvc', endpoint.path) + with self.subTest(i=11): + finding = findings[11] + self.assertEqual(datetime.date(2018, 4, 23), finding.date.date()) + self.assertEqual("High", finding.severity) + self.assertEqual("path-traversal", finding.vuln_id_from_tool) + self.assertIsNone(finding.unique_id_from_tool) # aggregated finding + self.assertEqual(4, finding.nb_occurences) + self.assertEqual(22, finding.cwe) + # endpoints + self.assertIsNotNone(finding.unsaved_endpoints) + self.assertEqual(4, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual('http', endpoint.protocol) + self.assertEqual('0.0.0.0', endpoint.host) + self.assertEqual('WebGoat/services/SoapRequest', endpoint.path) + endpoint = finding.unsaved_endpoints[1] + self.assertEqual('http', endpoint.protocol) + self.assertEqual('0.0.0.0', endpoint.host) + self.assertEqual('WebGoat/attack', endpoint.path) def test_example2_report(self): test = Test() test.engagement = Engagement() test.engagement.product = Product() - testfile = open("unittests/scans/contrast/vulnerabilities2020-09-21.csv") - parser = ContrastParser() - findings = parser.get_findings(testfile, test) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual(datetime.date(2020, 5, 22), finding.date.date()) - self.assertEqual("Medium", finding.severity) - self.assertEqual("crypto-bad-mac", finding.vuln_id_from_tool) - self.assertEqual("072U-8EYA-BNSH-PGN6", finding.unique_id_from_tool) - self.assertEqual(327, finding.cwe) - self.assertEqual(0, len(finding.unsaved_endpoints)) + with open("unittests/scans/contrast/vulnerabilities2020-09-21.csv") as testfile: + parser = ContrastParser() + findings = parser.get_findings(testfile, test) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual(datetime.date(2020, 5, 22), finding.date.date()) + self.assertEqual("Medium", finding.severity) + self.assertEqual("crypto-bad-mac", finding.vuln_id_from_tool) + self.assertEqual("072U-8EYA-BNSH-PGN6", finding.unique_id_from_tool) + self.assertEqual(327, finding.cwe) + self.assertEqual(0, len(finding.unsaved_endpoints)) diff --git a/unittests/tools/test_coverity_api_parser.py b/unittests/tools/test_coverity_api_parser.py index 3ec4423e62..2a2c148819 100644 --- a/unittests/tools/test_coverity_api_parser.py +++ b/unittests/tools/test_coverity_api_parser.py @@ -8,91 +8,91 @@ class TestZapParser(DojoTestCase): def test_parse_wrong_file(self): with self.assertRaises(ValueError): - testfile = open("unittests/scans/coverity_api/wrong.json") - parser = CoverityApiParser() - parser.get_findings(testfile, Test()) + with open("unittests/scans/coverity_api/wrong.json") as testfile: + parser = CoverityApiParser() + parser.get_findings(testfile, Test()) def test_parse_no_findings(self): - testfile = open("unittests/scans/coverity_api/empty.json") - parser = CoverityApiParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/coverity_api/empty.json") as testfile: + parser = CoverityApiParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_only_quality(self): """This report only have quality findings""" - testfile = open("unittests/scans/coverity_api/only_quality.json") - parser = CoverityApiParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/coverity_api/only_quality.json") as testfile: + parser = CoverityApiParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_some_findings(self): - testfile = open("unittests/scans/coverity_api/few_findings.json") - parser = CoverityApiParser() - findings = parser.get_findings(testfile, Test()) - self.assertIsInstance(findings, list) - self.assertEqual(1, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertTrue(finding.active) - self.assertFalse(finding.verified) # this one is marked as new ("status": "New") - self.assertEqual("Risky cryptographic hashing function", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertEqual(328, finding.cwe) - self.assertEqual("Ugmeekucai/Axoqomhsti/Ydyvpiogyn/Rpzlfzjvra.rs", finding.file_path) - self.assertEqual(datetime.date(2021, 3, 23), finding.date) - self.assertEqual(22463, finding.unique_id_from_tool) + with open("unittests/scans/coverity_api/few_findings.json") as testfile: + parser = CoverityApiParser() + findings = parser.get_findings(testfile, Test()) + self.assertIsInstance(findings, list) + self.assertEqual(1, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertTrue(finding.active) + self.assertFalse(finding.verified) # this one is marked as new ("status": "New") + self.assertEqual("Risky cryptographic hashing function", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertEqual(328, finding.cwe) + self.assertEqual("Ugmeekucai/Axoqomhsti/Ydyvpiogyn/Rpzlfzjvra.rs", finding.file_path) + self.assertEqual(datetime.date(2021, 3, 23), finding.date) + self.assertEqual(22463, finding.unique_id_from_tool) def test_parse_few_findings_triaged_as_bug(self): - testfile = open("unittests/scans/coverity_api/few_findings_triaged_as_bug.json") - parser = CoverityApiParser() - findings = parser.get_findings(testfile, Test()) - self.assertIsInstance(findings, list) - self.assertEqual(1, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertTrue(finding.active) - self.assertTrue(finding.verified) - self.assertEqual("HTTP header injection", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertEqual(610, finding.cwe) - self.assertEqual("Fhfzusraaf/Ktvntamjop/Azkpvexkuw/Mvibflzawx.rs", finding.file_path) - self.assertEqual(datetime.date(2020, 11, 19), finding.date) - self.assertEqual(22248, finding.unique_id_from_tool) + with open("unittests/scans/coverity_api/few_findings_triaged_as_bug.json") as testfile: + parser = CoverityApiParser() + findings = parser.get_findings(testfile, Test()) + self.assertIsInstance(findings, list) + self.assertEqual(1, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertTrue(finding.active) + self.assertTrue(finding.verified) + self.assertEqual("HTTP header injection", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertEqual(610, finding.cwe) + self.assertEqual("Fhfzusraaf/Ktvntamjop/Azkpvexkuw/Mvibflzawx.rs", finding.file_path) + self.assertEqual(datetime.date(2020, 11, 19), finding.date) + self.assertEqual(22248, finding.unique_id_from_tool) def test_parse_some_findings_mitigated(self): - testfile = open("unittests/scans/coverity_api/few_findings_mitigated.json") - parser = CoverityApiParser() - findings = parser.get_findings(testfile, Test()) - self.assertIsInstance(findings, list) - self.assertEqual(20, len(findings)) - with self.subTest(i=0): - finding = findings[0] # this one is dismissed as a false positive - self.assertFalse(finding.active) - self.assertTrue(finding.verified) - self.assertTrue(finding.false_p) - self.assertEqual("Cross-site scripting", finding.title) - self.assertEqual("High", finding.severity) - self.assertEqual(79, finding.cwe) - self.assertEqual("Pfozpmtueo/Vtoqmbvmzf/Noxacjclcz/Aymctwefbi.rs", finding.file_path) - self.assertEqual(datetime.date(2021, 3, 26), finding.date) - self.assertEqual(22486, finding.unique_id_from_tool) - with self.subTest(i=10): - finding = findings[10] - self.assertFalse(finding.active) - self.assertTrue(finding.verified) - self.assertEqual("Use of hard-coded password", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertEqual(259, finding.cwe) - self.assertEqual("Hvsilgzkwz/Lhmxrchybr/Edcoanzncg/Oowieyoxvn.rs", finding.file_path) - self.assertEqual(datetime.date(2021, 3, 15), finding.date) - self.assertEqual(22421, finding.unique_id_from_tool) - with self.subTest(i=19): - finding = findings[19] - self.assertFalse(finding.active) - self.assertTrue(finding.verified) - self.assertEqual("Cross-site scripting", finding.title) - self.assertEqual("High", finding.severity) - self.assertEqual(79, finding.cwe) - self.assertEqual("Pyqqbarxuc/Eiiecgivyo/Yurhlwgjpa/Fitpbdjidn.rs", finding.file_path) - self.assertEqual(datetime.date(2020, 1, 22), finding.date) - self.assertEqual(18828, finding.unique_id_from_tool) + with open("unittests/scans/coverity_api/few_findings_mitigated.json") as testfile: + parser = CoverityApiParser() + findings = parser.get_findings(testfile, Test()) + self.assertIsInstance(findings, list) + self.assertEqual(20, len(findings)) + with self.subTest(i=0): + finding = findings[0] # this one is dismissed as a false positive + self.assertFalse(finding.active) + self.assertTrue(finding.verified) + self.assertTrue(finding.false_p) + self.assertEqual("Cross-site scripting", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual(79, finding.cwe) + self.assertEqual("Pfozpmtueo/Vtoqmbvmzf/Noxacjclcz/Aymctwefbi.rs", finding.file_path) + self.assertEqual(datetime.date(2021, 3, 26), finding.date) + self.assertEqual(22486, finding.unique_id_from_tool) + with self.subTest(i=10): + finding = findings[10] + self.assertFalse(finding.active) + self.assertTrue(finding.verified) + self.assertEqual("Use of hard-coded password", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertEqual(259, finding.cwe) + self.assertEqual("Hvsilgzkwz/Lhmxrchybr/Edcoanzncg/Oowieyoxvn.rs", finding.file_path) + self.assertEqual(datetime.date(2021, 3, 15), finding.date) + self.assertEqual(22421, finding.unique_id_from_tool) + with self.subTest(i=19): + finding = findings[19] + self.assertFalse(finding.active) + self.assertTrue(finding.verified) + self.assertEqual("Cross-site scripting", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual(79, finding.cwe) + self.assertEqual("Pyqqbarxuc/Eiiecgivyo/Yurhlwgjpa/Fitpbdjidn.rs", finding.file_path) + self.assertEqual(datetime.date(2020, 1, 22), finding.date) + self.assertEqual(18828, finding.unique_id_from_tool) diff --git a/unittests/tools/test_cred_scan_parser.py b/unittests/tools/test_cred_scan_parser.py index 2095af6941..2bff8c559b 100644 --- a/unittests/tools/test_cred_scan_parser.py +++ b/unittests/tools/test_cred_scan_parser.py @@ -7,24 +7,24 @@ class TestCredScanParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/cred_scan/cred_scan_no_vuln.csv") - parser = CredScanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/cred_scan/cred_scan_no_vuln.csv") as testfile: + parser = CredScanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_findings(self): - testfile = open("unittests/scans/cred_scan/cred_scan_one_vuln.csv") - parser = CredScanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("10", finding.line) - self.assertEqual("E:sample/dir/first/App.config", finding.file_path) - self.assertEqual(datetime.date(2021, 4, 10), datetime.datetime.date(finding.date)) + with open("unittests/scans/cred_scan/cred_scan_one_vuln.csv") as testfile: + parser = CredScanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("10", finding.line) + self.assertEqual("E:sample/dir/first/App.config", finding.file_path) + self.assertEqual(datetime.date(2021, 4, 10), datetime.datetime.date(finding.date)) def test_parse_file_with_multiple_vuln_has_multiple_finding(self): - testfile = open("unittests/scans/cred_scan/cred_scan_many_vuln.csv") - parser = CredScanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(3, len(findings)) + with open("unittests/scans/cred_scan/cred_scan_many_vuln.csv") as testfile: + parser = CredScanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(3, len(findings)) diff --git a/unittests/tools/test_crunch42_parser.py b/unittests/tools/test_crunch42_parser.py index ea5188d303..512521808a 100644 --- a/unittests/tools/test_crunch42_parser.py +++ b/unittests/tools/test_crunch42_parser.py @@ -6,27 +6,25 @@ class TestCrunch42Parser(DojoTestCase): def test_crunch42parser_single_has_many_findings(self): - testfile = open("unittests/scans/crunch42/crunch42_many_findings.json") - parser = Crunch42Parser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(8, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("teephei0aes4ohxur7Atie6zuiCh9weeshue0kai", finding.unique_id_from_tool) - self.assertEqual("Info", finding.severity) - self.assertIsNotNone(finding.description) - self.assertGreater(len(finding.description), 0) + with open("unittests/scans/crunch42/crunch42_many_findings.json") as testfile: + parser = Crunch42Parser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(8, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("teephei0aes4ohxur7Atie6zuiCh9weeshue0kai", finding.unique_id_from_tool) + self.assertEqual("Info", finding.severity) + self.assertIsNotNone(finding.description) + self.assertGreater(len(finding.description), 0) def test_crunch42parser_single_has_many_findings2(self): - testfile = open("unittests/scans/crunch42/crunch42_many_findings2.json") - parser = Crunch42Parser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(5, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("auCh0yi8sheumohruegh7of4EiT0ahngooK1aeje", finding.unique_id_from_tool) - self.assertEqual("Info", finding.severity) - self.assertIsNotNone(finding.description) - self.assertGreater(len(finding.description), 0) + with open("unittests/scans/crunch42/crunch42_many_findings2.json") as testfile: + parser = Crunch42Parser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(5, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("auCh0yi8sheumohruegh7of4EiT0ahngooK1aeje", finding.unique_id_from_tool) + self.assertEqual("Info", finding.severity) + self.assertIsNotNone(finding.description) + self.assertGreater(len(finding.description), 0) diff --git a/unittests/tools/test_dependency_check_parser.py b/unittests/tools/test_dependency_check_parser.py index 0d22d7e1b0..0f6f9c4d96 100644 --- a/unittests/tools/test_dependency_check_parser.py +++ b/unittests/tools/test_dependency_check_parser.py @@ -19,236 +19,236 @@ def __init__(self, name, content): class TestDependencyCheckParser(DojoTestCase): def test_parse_empty_file(self): - testfile = open("unittests/scans/dependency_check/single_dependency_with_related_no_vulnerability.xml") - parser = DependencyCheckParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/dependency_check/single_dependency_with_related_no_vulnerability.xml") as testfile: + parser = DependencyCheckParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_single_vulnerability_has_single_finding(self): - testfile = open("unittests/scans/dependency_check/single_vuln.xml") - parser = DependencyCheckParser() - findings = parser.get_findings(testfile, Test()) - items = findings - self.assertEqual(1, len(items)) - i = 0 - with self.subTest(i=i): - self.assertEqual(items[i].title, "org.owasp:library:6.7.8 | CVE-0000-0001") - self.assertEqual(items[i].severity, "Medium") - self.assertEqual(items[i].component_name, "org.owasp:library") - self.assertEqual(items[i].component_version, "6.7.8") - self.assertEqual( - items[i].mitigation, - "Update org.owasp:library:6.7.8 to at least the version recommended in the description", - ) - self.assertEqual(items[i].date, datetime(2016, 11, 5, 14, 52, 15, 748000, tzinfo=tzoffset(None, -14400))) + with open("unittests/scans/dependency_check/single_vuln.xml") as testfile: + parser = DependencyCheckParser() + findings = parser.get_findings(testfile, Test()) + items = findings + self.assertEqual(1, len(items)) + i = 0 + with self.subTest(i=i): + self.assertEqual(items[i].title, "org.owasp:library:6.7.8 | CVE-0000-0001") + self.assertEqual(items[i].severity, "Medium") + self.assertEqual(items[i].component_name, "org.owasp:library") + self.assertEqual(items[i].component_version, "6.7.8") + self.assertEqual( + items[i].mitigation, + "Update org.owasp:library:6.7.8 to at least the version recommended in the description", + ) + self.assertEqual(items[i].date, datetime(2016, 11, 5, 14, 52, 15, 748000, tzinfo=tzoffset(None, -14400))) def test_parse_file_with_single_dependency_with_related_no_vulnerability(self): - testfile = open("unittests/scans/dependency_check/single_dependency_with_related_no_vulnerability.xml") - parser = DependencyCheckParser() - findings = parser.get_findings(testfile, Test()) - items = findings - self.assertEqual(0, len(items)) + with open("unittests/scans/dependency_check/single_dependency_with_related_no_vulnerability.xml") as testfile: + parser = DependencyCheckParser() + findings = parser.get_findings(testfile, Test()) + items = findings + self.assertEqual(0, len(items)) def test_parse_file_with_multiple_vulnerabilities_has_multiple_findings(self): - testfile = open("unittests/scans/dependency_check/multiple_vulnerabilities_has_multiple_findings.xml") - parser = DependencyCheckParser() - findings = parser.get_findings(testfile, Test()) - items = findings - self.assertEqual(11, len(items)) - # test also different component_name formats + with open("unittests/scans/dependency_check/multiple_vulnerabilities_has_multiple_findings.xml") as testfile: + parser = DependencyCheckParser() + findings = parser.get_findings(testfile, Test()) + items = findings + self.assertEqual(11, len(items)) + # test also different component_name formats - with self.subTest(i=0): - # identifier -> package url java + 2 relateddependencies - self.assertEqual(items[0].title, "org.dom4j:dom4j:2.1.1.redhat-00001 | CVE-0000-0001") - self.assertEqual(items[0].component_name, "org.dom4j:dom4j") - self.assertEqual(items[0].component_version, "2.1.1.redhat-00001") - self.assertIn( - "Description of a bad vulnerability.", - items[0].description, - ) - self.assertIn( - "/var/lib/adapter-ear1.ear/dom4j-2.1.1.jar", - items[0].description, - ) - self.assertEqual(items[0].severity, "High") - self.assertEqual(items[0].file_path, "adapter-ear1.ear: dom4j-2.1.1.jar") - self.assertEqual( - items[0].mitigation, - "Update org.dom4j:dom4j:2.1.1.redhat-00001 to at least the version recommended in the description", - ) - self.assertEqual( - items[0].date, datetime(2016, 11, 5, 14, 52, 15, 748000, tzinfo=tzoffset(None, -14400)) - ) # 2016-11-05T14:52:15.748-0400 - self.assertEqual(1, len(items[0].unsaved_vulnerability_ids)) - self.assertEqual('CVE-0000-0001', items[0].unsaved_vulnerability_ids[0]) + with self.subTest(i=0): + # identifier -> package url java + 2 relateddependencies + self.assertEqual(items[0].title, "org.dom4j:dom4j:2.1.1.redhat-00001 | CVE-0000-0001") + self.assertEqual(items[0].component_name, "org.dom4j:dom4j") + self.assertEqual(items[0].component_version, "2.1.1.redhat-00001") + self.assertIn( + "Description of a bad vulnerability.", + items[0].description, + ) + self.assertIn( + "/var/lib/adapter-ear1.ear/dom4j-2.1.1.jar", + items[0].description, + ) + self.assertEqual(items[0].severity, "High") + self.assertEqual(items[0].file_path, "adapter-ear1.ear: dom4j-2.1.1.jar") + self.assertEqual( + items[0].mitigation, + "Update org.dom4j:dom4j:2.1.1.redhat-00001 to at least the version recommended in the description", + ) + self.assertEqual( + items[0].date, datetime(2016, 11, 5, 14, 52, 15, 748000, tzinfo=tzoffset(None, -14400)) + ) # 2016-11-05T14:52:15.748-0400 + self.assertEqual(1, len(items[0].unsaved_vulnerability_ids)) + self.assertEqual('CVE-0000-0001', items[0].unsaved_vulnerability_ids[0]) - with self.subTest(i=1): - self.assertEqual(items[1].title, "org.dom4j:dom4j:2.1.1.redhat-00001 | CVE-0000-0001") - self.assertEqual(items[1].component_name, "org.dom4j:dom4j") - self.assertEqual(items[1].component_version, "2.1.1.redhat-00001") - self.assertIn( - "Description of a bad vulnerability.", - items[1].description, - ) - self.assertIn( - "/var/lib/adapter-ear8.ear/dom4j-2.1.1.jar", - items[1].description, - ) - self.assertEqual(items[1].severity, "High") - self.assertEqual(items[1].file_path, "adapter-ear8.ear: dom4j-2.1.1.jar") - self.assertEqual( - items[1].mitigation, - "Update org.dom4j:dom4j:2.1.1.redhat-00001 to at least the version recommended in the description", - ) - self.assertEqual(items[1].tags, "related") - self.assertEqual(1, len(items[1].unsaved_vulnerability_ids)) - self.assertEqual('CVE-0000-0001', items[1].unsaved_vulnerability_ids[0]) + with self.subTest(i=1): + self.assertEqual(items[1].title, "org.dom4j:dom4j:2.1.1.redhat-00001 | CVE-0000-0001") + self.assertEqual(items[1].component_name, "org.dom4j:dom4j") + self.assertEqual(items[1].component_version, "2.1.1.redhat-00001") + self.assertIn( + "Description of a bad vulnerability.", + items[1].description, + ) + self.assertIn( + "/var/lib/adapter-ear8.ear/dom4j-2.1.1.jar", + items[1].description, + ) + self.assertEqual(items[1].severity, "High") + self.assertEqual(items[1].file_path, "adapter-ear8.ear: dom4j-2.1.1.jar") + self.assertEqual( + items[1].mitigation, + "Update org.dom4j:dom4j:2.1.1.redhat-00001 to at least the version recommended in the description", + ) + self.assertEqual(items[1].tags, "related") + self.assertEqual(1, len(items[1].unsaved_vulnerability_ids)) + self.assertEqual('CVE-0000-0001', items[1].unsaved_vulnerability_ids[0]) - with self.subTest(i=2): - self.assertEqual(items[2].title, "org.dom4j:dom4j:2.1.1.redhat-00001 | CVE-0000-0001") - self.assertEqual(items[2].component_name, "org.dom4j:dom4j") - self.assertEqual(items[2].component_version, "2.1.1.redhat-00001") - self.assertIn( - "Description of a bad vulnerability.", - items[2].description, - ) - self.assertIn( - "/var/lib/adapter-ear1.ear/dom4j-extensions-2.1.1.jar", - items[2].description, - ) - self.assertEqual(items[2].severity, "High") - self.assertEqual(items[2].file_path, "adapter-ear1.ear: dom4j-extensions-2.1.1.jar") - self.assertEqual( - items[2].mitigation, - "Update org.dom4j:dom4j:2.1.1.redhat-00001 to at least the version recommended in the description", - ) - self.assertEqual(1, len(items[2].unsaved_vulnerability_ids)) - self.assertEqual('CVE-0000-0001', items[2].unsaved_vulnerability_ids[0]) + with self.subTest(i=2): + self.assertEqual(items[2].title, "org.dom4j:dom4j:2.1.1.redhat-00001 | CVE-0000-0001") + self.assertEqual(items[2].component_name, "org.dom4j:dom4j") + self.assertEqual(items[2].component_version, "2.1.1.redhat-00001") + self.assertIn( + "Description of a bad vulnerability.", + items[2].description, + ) + self.assertIn( + "/var/lib/adapter-ear1.ear/dom4j-extensions-2.1.1.jar", + items[2].description, + ) + self.assertEqual(items[2].severity, "High") + self.assertEqual(items[2].file_path, "adapter-ear1.ear: dom4j-extensions-2.1.1.jar") + self.assertEqual( + items[2].mitigation, + "Update org.dom4j:dom4j:2.1.1.redhat-00001 to at least the version recommended in the description", + ) + self.assertEqual(1, len(items[2].unsaved_vulnerability_ids)) + self.assertEqual('CVE-0000-0001', items[2].unsaved_vulnerability_ids[0]) - with self.subTest(i=3): - # identifier -> package url javascript, no vulnerabilitids, 3 vulnerabilities, relateddependencies without filename (pre v6.0.0) - self.assertEqual( - items[3].title, "yargs-parser:5.0.0 | 1500" - ) - self.assertEqual(items[3].component_name, "yargs-parser") - self.assertEqual(items[3].component_version, "5.0.0") - # assert fails due to special characters, not too important - # self.assertEqual(items[1].description, "Affected versions of `yargs-parser` are vulnerable to prototype pollution. Arguments are not properly sanitized, allowing an attacker to modify the prototype of `Object`, causing the addition or modification of an existing property that will exist on all objects.Parsing the argument `--foo.__proto__.bar baz'` adds a `bar` property with value `baz` to all objects. This is only exploitable if attackers have control over the arguments being passed to `yargs-parser`.") - self.assertEqual(items[3].severity, "Low") - self.assertEqual(items[3].file_path, "yargs-parser:5.0.0") - self.assertEqual( - items[3].mitigation, "Update yargs-parser:5.0.0 to at least the version recommended in the description" - ) - self.assertIn( - "**Source:** NPM", - items[3].description, - ) - self.assertIsNone(items[3].unsaved_vulnerability_ids) + with self.subTest(i=3): + # identifier -> package url javascript, no vulnerabilitids, 3 vulnerabilities, relateddependencies without filename (pre v6.0.0) + self.assertEqual( + items[3].title, "yargs-parser:5.0.0 | 1500" + ) + self.assertEqual(items[3].component_name, "yargs-parser") + self.assertEqual(items[3].component_version, "5.0.0") + # assert fails due to special characters, not too important + # self.assertEqual(items[1].description, "Affected versions of `yargs-parser` are vulnerable to prototype pollution. Arguments are not properly sanitized, allowing an attacker to modify the prototype of `Object`, causing the addition or modification of an existing property that will exist on all objects.Parsing the argument `--foo.__proto__.bar baz'` adds a `bar` property with value `baz` to all objects. This is only exploitable if attackers have control over the arguments being passed to `yargs-parser`.") + self.assertEqual(items[3].severity, "Low") + self.assertEqual(items[3].file_path, "yargs-parser:5.0.0") + self.assertEqual( + items[3].mitigation, "Update yargs-parser:5.0.0 to at least the version recommended in the description" + ) + self.assertIn( + "**Source:** NPM", + items[3].description, + ) + self.assertIsNone(items[3].unsaved_vulnerability_ids) - with self.subTest(i=4): - self.assertEqual( - items[4].title, - "yargs-parser:5.0.0 | CVE-2020-7608", - ) - self.assertEqual(items[4].component_name, "yargs-parser") - self.assertEqual(items[4].component_version, "5.0.0") - self.assertIn( - 'yargs-parser could be tricked into adding or modifying properties\n of Object.prototype using a "__proto__" payload.\n**Source:** OSSINDEX\n**Filepath:** \n /var/lib/jenkins/workspace/nl-selfservice_-_metrics_develop/package-lock.json?yargs-parser', - items[4].description, - ) - self.assertIn( - "/var/lib/jenkins/workspace/nl-selfservice_-_metrics_develop/package-lock.json?yargs-parser", - items[4].description, - ) - self.assertEqual(items[4].severity, "High") - self.assertEqual(items[4].file_path, "yargs-parser:5.0.0") - self.assertEqual( - items[4].mitigation, "Update yargs-parser:5.0.0 to at least the version recommended in the description" - ) - self.assertEqual(1, len(items[4].unsaved_vulnerability_ids)) - self.assertEqual('CVE-2020-7608', items[4].unsaved_vulnerability_ids[0]) + with self.subTest(i=4): + self.assertEqual( + items[4].title, + "yargs-parser:5.0.0 | CVE-2020-7608", + ) + self.assertEqual(items[4].component_name, "yargs-parser") + self.assertEqual(items[4].component_version, "5.0.0") + self.assertIn( + 'yargs-parser could be tricked into adding or modifying properties\n of Object.prototype using a "__proto__" payload.\n**Source:** OSSINDEX\n**Filepath:** \n /var/lib/jenkins/workspace/nl-selfservice_-_metrics_develop/package-lock.json?yargs-parser', + items[4].description, + ) + self.assertIn( + "/var/lib/jenkins/workspace/nl-selfservice_-_metrics_develop/package-lock.json?yargs-parser", + items[4].description, + ) + self.assertEqual(items[4].severity, "High") + self.assertEqual(items[4].file_path, "yargs-parser:5.0.0") + self.assertEqual( + items[4].mitigation, "Update yargs-parser:5.0.0 to at least the version recommended in the description" + ) + self.assertEqual(1, len(items[4].unsaved_vulnerability_ids)) + self.assertEqual('CVE-2020-7608', items[4].unsaved_vulnerability_ids[0]) - with self.subTest(i=5): - self.assertEqual( - items[5].title, - "yargs-parser:5.0.0 | CWE-400: Uncontrolled Resource Consumption ('Resource Exhaustion')", - ) - self.assertEqual(items[5].component_name, "yargs-parser") - self.assertEqual(items[5].component_version, "5.0.0") - self.assertIn( - "The software does not properly restrict the size or amount of resources that are requested or influenced by an actor, which can be used to consume more resources than intended.", - items[5].description, - ) - # check that the filepath is in the description - self.assertIn( - "/var/lib/jenkins/workspace/nl-selfservice_-_metrics_develop/package-lock.json?yargs-parser", - items[5].description, - ) - self.assertEqual(items[5].severity, "High") - self.assertEqual(items[5].file_path, "yargs-parser:5.0.0") - self.assertEqual( - items[5].mitigation, "Update yargs-parser:5.0.0 to at least the version recommended in the description" - ) - self.assertIsNone(items[5].unsaved_vulnerability_ids) + with self.subTest(i=5): + self.assertEqual( + items[5].title, + "yargs-parser:5.0.0 | CWE-400: Uncontrolled Resource Consumption ('Resource Exhaustion')", + ) + self.assertEqual(items[5].component_name, "yargs-parser") + self.assertEqual(items[5].component_version, "5.0.0") + self.assertIn( + "The software does not properly restrict the size or amount of resources that are requested or influenced by an actor, which can be used to consume more resources than intended.", + items[5].description, + ) + # check that the filepath is in the description + self.assertIn( + "/var/lib/jenkins/workspace/nl-selfservice_-_metrics_develop/package-lock.json?yargs-parser", + items[5].description, + ) + self.assertEqual(items[5].severity, "High") + self.assertEqual(items[5].file_path, "yargs-parser:5.0.0") + self.assertEqual( + items[5].mitigation, "Update yargs-parser:5.0.0 to at least the version recommended in the description" + ) + self.assertIsNone(items[5].unsaved_vulnerability_ids) - with self.subTest(i=6): - # identifier -> cpe java - self.assertEqual(items[6].title, "org.dom4j:dom4j:2.1.1.redhat-00001 | CVE-0000-0001") - self.assertEqual(items[6].component_name, "org.dom4j:dom4j") - self.assertEqual(items[6].component_version, "2.1.1.redhat-00001") - self.assertEqual(items[6].severity, "High") - self.assertEqual(items[6].file_path, "adapter-ear2.ear: dom4j-2.1.1.jar") - self.assertEqual( - items[6].mitigation, - "Update org.dom4j:dom4j:2.1.1.redhat-00001 to at least the version recommended in the description", - ) - self.assertEqual(1, len(items[6].unsaved_vulnerability_ids)) - self.assertEqual('CVE-0000-0001', items[6].unsaved_vulnerability_ids[0]) + with self.subTest(i=6): + # identifier -> cpe java + self.assertEqual(items[6].title, "org.dom4j:dom4j:2.1.1.redhat-00001 | CVE-0000-0001") + self.assertEqual(items[6].component_name, "org.dom4j:dom4j") + self.assertEqual(items[6].component_version, "2.1.1.redhat-00001") + self.assertEqual(items[6].severity, "High") + self.assertEqual(items[6].file_path, "adapter-ear2.ear: dom4j-2.1.1.jar") + self.assertEqual( + items[6].mitigation, + "Update org.dom4j:dom4j:2.1.1.redhat-00001 to at least the version recommended in the description", + ) + self.assertEqual(1, len(items[6].unsaved_vulnerability_ids)) + self.assertEqual('CVE-0000-0001', items[6].unsaved_vulnerability_ids[0]) - with self.subTest(i=7): - # identifier -> maven java - self.assertEqual(items[7].title, "dom4j:2.1.1 | CVE-0000-0001") - self.assertEqual(items[7].component_name, "dom4j") - self.assertEqual(items[7].component_version, "2.1.1") - self.assertEqual(items[7].severity, "High") - self.assertEqual( - items[7].mitigation, "Update dom4j:2.1.1 to at least the version recommended in the description" - ) + with self.subTest(i=7): + # identifier -> maven java + self.assertEqual(items[7].title, "dom4j:2.1.1 | CVE-0000-0001") + self.assertEqual(items[7].component_name, "dom4j") + self.assertEqual(items[7].component_version, "2.1.1") + self.assertEqual(items[7].severity, "High") + self.assertEqual( + items[7].mitigation, "Update dom4j:2.1.1 to at least the version recommended in the description" + ) - with self.subTest(i=8): - # evidencecollected -> single product + single verison javascript - self.assertEqual( - items[8].title, - "jquery:3.1.1 | CVE-0000-0001", - ) - self.assertEqual(items[8].component_name, "jquery") - self.assertEqual(items[8].component_version, "3.1.1") - self.assertEqual(items[8].severity, "High") - self.assertEqual( - items[8].mitigation, "Update jquery:3.1.1 to at least the version recommended in the description" - ) + with self.subTest(i=8): + # evidencecollected -> single product + single verison javascript + self.assertEqual( + items[8].title, + "jquery:3.1.1 | CVE-0000-0001", + ) + self.assertEqual(items[8].component_name, "jquery") + self.assertEqual(items[8].component_version, "3.1.1") + self.assertEqual(items[8].severity, "High") + self.assertEqual( + items[8].mitigation, "Update jquery:3.1.1 to at least the version recommended in the description" + ) - with self.subTest(i=9): - # Tests for two suppressed vulnerabilities, - # One for Suppressed with notes, the other is without. - self.assertEqual(items[9].active, False) - self.assertEqual( - items[9].mitigation, - "**This vulnerability is mitigated and/or suppressed:** Document on why we are suppressing this vulnerability is missing!\nUpdate jquery:3.1.1 to at least the version recommended in the description", - ) - self.assertEqual(items[9].tags, ["suppressed", "no_suppression_document"]) - self.assertEqual(items[10].severity, "Critical") - self.assertEqual(items[10].is_mitigated, True) + with self.subTest(i=9): + # Tests for two suppressed vulnerabilities, + # One for Suppressed with notes, the other is without. + self.assertEqual(items[9].active, False) + self.assertEqual( + items[9].mitigation, + "**This vulnerability is mitigated and/or suppressed:** Document on why we are suppressing this vulnerability is missing!\nUpdate jquery:3.1.1 to at least the version recommended in the description", + ) + self.assertEqual(items[9].tags, ["suppressed", "no_suppression_document"]) + self.assertEqual(items[10].severity, "Critical") + self.assertEqual(items[10].is_mitigated, True) - with self.subTest(i=10): - self.assertEqual(items[10].active, False) - self.assertEqual( - items[10].mitigation, - "**This vulnerability is mitigated and/or suppressed:** This is our reason for not to upgrade it.\nUpdate jquery:3.1.1 to at least the version recommended in the description", - ) - self.assertEqual(items[10].tags, "suppressed") - self.assertEqual(items[10].severity, "Critical") - self.assertEqual(items[10].is_mitigated, True) + with self.subTest(i=10): + self.assertEqual(items[10].active, False) + self.assertEqual( + items[10].mitigation, + "**This vulnerability is mitigated and/or suppressed:** This is our reason for not to upgrade it.\nUpdate jquery:3.1.1 to at least the version recommended in the description", + ) + self.assertEqual(items[10].tags, "suppressed") + self.assertEqual(items[10].severity, "Critical") + self.assertEqual(items[10].is_mitigated, True) def test_parse_java_6_5_3(self): """Test with version 6.5.3""" @@ -271,35 +271,35 @@ def test_parse_java_6_5_3(self): self.assertEqual(items[i].date, datetime(2022, 1, 15, 14, 31, 13, 42600, tzinfo=timezone.utc)) def test_parse_file_pr6439(self): - testfile = open("unittests/scans/dependency_check/PR6439.xml") - parser = DependencyCheckParser() - findings = parser.get_findings(testfile, Test()) - items = findings - self.assertEqual(37, len(items)) - # test also different component_name formats + with open("unittests/scans/dependency_check/PR6439.xml") as testfile: + parser = DependencyCheckParser() + findings = parser.get_findings(testfile, Test()) + items = findings + self.assertEqual(37, len(items)) + # test also different component_name formats - with self.subTest(i=0): - print(items[0]) - # identifier -> package url java + 2 relateddependencies - self.assertEqual(items[0].title, "org.apache.activemq:activemq-broker:5.16.5 | CVE-2015-3208") - self.assertEqual(items[0].component_name, "org.apache.activemq:activemq-broker") - self.assertEqual(items[0].component_version, "5.16.5") - self.assertIn( - "XML external entity (XXE) vulnerability in the XPath selector component in", - items[0].description, - ) - self.assertIn( - "**Source:** OSSINDEX", - items[0].description, - ) - self.assertEqual(items[0].severity, "Critical") - self.assertEqual(items[0].file_path, "activemq-broker-5.16.5.jar") - self.assertIn( - "**This vulnerability is mitigated and/or suppressed:** Ist eine Dependency vom CXF. Der im Finding erwähnte Bug ist seit Version 1.0", - items[0].mitigation, - ) - self.assertEqual( - items[0].date, datetime(2022, 12, 14, 1, 35, 43, 684166, tzinfo=tzlocal()) - ) # 2016-11-05T14:52:15.748-0400 - self.assertEqual(1, len(items[0].unsaved_vulnerability_ids)) - self.assertEqual('CVE-2015-3208', items[0].unsaved_vulnerability_ids[0]) + with self.subTest(i=0): + print(items[0]) + # identifier -> package url java + 2 relateddependencies + self.assertEqual(items[0].title, "org.apache.activemq:activemq-broker:5.16.5 | CVE-2015-3208") + self.assertEqual(items[0].component_name, "org.apache.activemq:activemq-broker") + self.assertEqual(items[0].component_version, "5.16.5") + self.assertIn( + "XML external entity (XXE) vulnerability in the XPath selector component in", + items[0].description, + ) + self.assertIn( + "**Source:** OSSINDEX", + items[0].description, + ) + self.assertEqual(items[0].severity, "Critical") + self.assertEqual(items[0].file_path, "activemq-broker-5.16.5.jar") + self.assertIn( + "**This vulnerability is mitigated and/or suppressed:** Ist eine Dependency vom CXF. Der im Finding erwähnte Bug ist seit Version 1.0", + items[0].mitigation, + ) + self.assertEqual( + items[0].date, datetime(2022, 12, 14, 1, 35, 43, 684166, tzinfo=tzlocal()) + ) # 2016-11-05T14:52:15.748-0400 + self.assertEqual(1, len(items[0].unsaved_vulnerability_ids)) + self.assertEqual('CVE-2015-3208', items[0].unsaved_vulnerability_ids[0]) diff --git a/unittests/tools/test_dependency_track_parser.py b/unittests/tools/test_dependency_track_parser.py index b12f5611f9..57b7c23530 100644 --- a/unittests/tools/test_dependency_track_parser.py +++ b/unittests/tools/test_dependency_track_parser.py @@ -5,97 +5,87 @@ class TestDependencyTrackParser(DojoTestCase): - def test_dependency_track_parser_with_empty_list_for_findings_key_has_no_findings( - self, - ): - testfile = open( + def test_dependency_track_parser_with_empty_list_for_findings_key_has_no_findings(self,): + with open( get_unit_tests_path() + "/scans/dependency_track/no_findings_because_findings_key_is_empty_list.json" - ) - parser = DependencyTrackParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(0, len(findings)) + ) as testfile: + parser = DependencyTrackParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_dependency_track_parser_with_missing_findings_key_has_no_findings(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/dependency_track/no_findings_because_findings_key_is_missing.json" - ) - parser = DependencyTrackParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(0, len(findings)) + ) as testfile: + parser = DependencyTrackParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_dependency_track_parser_with_null_findings_key_has_no_findings(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/dependency_track/no_findings_because_findings_key_is_null.json" - ) - parser = DependencyTrackParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(0, len(findings)) + ) as testfile: + parser = DependencyTrackParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_dependency_track_parser_has_many_findings(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/dependency_track/many_findings.json" - ) - parser = DependencyTrackParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(4, len(findings)) + ) as testfile: + parser = DependencyTrackParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(4, len(findings)) - self.assertIsNone(findings[0].unsaved_vulnerability_ids) - self.assertIsNone(findings[1].unsaved_vulnerability_ids) - self.assertEqual(1, len(findings[2].unsaved_vulnerability_ids)) - self.assertEqual('CVE-2016-2097', findings[2].unsaved_vulnerability_ids[0]) - self.assertTrue(findings[2].false_p) - self.assertTrue(findings[2].is_mitigated) - self.assertFalse(findings[2].active) - self.assertEqual(1, len(findings[3].unsaved_vulnerability_ids)) - self.assertEqual('CVE-2016-2097', findings[3].unsaved_vulnerability_ids[0]) + self.assertIsNone(findings[0].unsaved_vulnerability_ids) + self.assertIsNone(findings[1].unsaved_vulnerability_ids) + self.assertEqual(1, len(findings[2].unsaved_vulnerability_ids)) + self.assertEqual('CVE-2016-2097', findings[2].unsaved_vulnerability_ids[0]) + self.assertTrue(findings[2].false_p) + self.assertTrue(findings[2].is_mitigated) + self.assertFalse(findings[2].active) + self.assertEqual(1, len(findings[3].unsaved_vulnerability_ids)) + self.assertEqual('CVE-2016-2097', findings[3].unsaved_vulnerability_ids[0]) def test_dependency_track_parser_has_one_finding(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/dependency_track/one_finding.json" - ) - parser = DependencyTrackParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1, len(findings)) + ) as testfile: + parser = DependencyTrackParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) def test_dependency_track_parser_v3_8_0(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/dependency_track/dependency_track_3.8.0_2021-01-18.json" - ) - parser = DependencyTrackParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(9, len(findings)) - self.assertTrue(all(item.file_path is not None for item in findings)) - self.assertTrue(all(item.vuln_id_from_tool is not None for item in findings)) + ) as testfile: + parser = DependencyTrackParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(9, len(findings)) + self.assertTrue(all(item.file_path is not None for item in findings)) + self.assertTrue(all(item.vuln_id_from_tool is not None for item in findings)) def test_dependency_track_parser_findings_with_alias(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/dependency_track/many_findings_with_alias.json" - ) - parser = DependencyTrackParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() + ) as testfile: + parser = DependencyTrackParser() + findings = parser.get_findings(testfile, Test()) - self.assertEqual(12, len(findings)) - self.assertTrue(all(item.file_path is not None for item in findings)) - self.assertTrue(all(item.vuln_id_from_tool is not None for item in findings)) - self.assertIn('CVE-2022-42004', findings[0].unsaved_vulnerability_ids) + self.assertEqual(12, len(findings)) + self.assertTrue(all(item.file_path is not None for item in findings)) + self.assertTrue(all(item.vuln_id_from_tool is not None for item in findings)) + self.assertIn('CVE-2022-42004', findings[0].unsaved_vulnerability_ids) def test_dependency_track_parser_findings_with_empty_alias(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/dependency_track/many_findings_with_empty_alias.json" - ) - parser = DependencyTrackParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() + ) as testfile: + parser = DependencyTrackParser() + findings = parser.get_findings(testfile, Test()) - self.assertEqual(12, len(findings)) - self.assertIn('CVE-2022-2053', findings[11].unsaved_vulnerability_ids) + self.assertEqual(12, len(findings)) + self.assertIn('CVE-2022-2053', findings[11].unsaved_vulnerability_ids) def test_dependency_track_parser_findings_with_cvssV3_score(self): with open(f"{get_unit_tests_path()}/scans/dependency_track/many_findings_with_cvssV3_score.json") as testfile: diff --git a/unittests/tools/test_detect_secrets_parser.py b/unittests/tools/test_detect_secrets_parser.py index 9ea6173d4a..6d3f6dff0f 100644 --- a/unittests/tools/test_detect_secrets_parser.py +++ b/unittests/tools/test_detect_secrets_parser.py @@ -8,65 +8,65 @@ class TestDetectSecretsParser(DojoTestCase): def test_parse_no_findings(self): - testfile = open("unittests/scans/detect_secrets/no_findings.json") - parser = DetectSecretsParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/detect_secrets/no_findings.json") as testfile: + parser = DetectSecretsParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_many_findings(self): - testfile = open("unittests/scans/detect_secrets/many_findings.json") - parser = DetectSecretsParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(4, len(findings)) + with open("unittests/scans/detect_secrets/many_findings.json") as testfile: + parser = DetectSecretsParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(4, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Secret Keyword", finding.title) - self.assertEqual("High", finding.severity) - self.assertEqual(datetime.datetime(2021, 5, 19, 10, 40, 18, tzinfo=tzlocal()), finding.date) - self.assertFalse(finding.verified) - self.assertEqual("modules_images", finding.file_path) - self.assertEqual(151, finding.line) - self.assertEqual(1, finding.nb_occurences) - self.assertEqual(798, finding.cwe) - self.assertIsNotNone(finding.description) - self.assertFalse(finding.false_p) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Secret Keyword", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual(datetime.datetime(2021, 5, 19, 10, 40, 18, tzinfo=tzlocal()), finding.date) + self.assertFalse(finding.verified) + self.assertEqual("modules_images", finding.file_path) + self.assertEqual(151, finding.line) + self.assertEqual(1, finding.nb_occurences) + self.assertEqual(798, finding.cwe) + self.assertIsNotNone(finding.description) + self.assertFalse(finding.false_p) - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("Secret Keyword", finding.title) - self.assertEqual("High", finding.severity) - self.assertEqual(datetime.datetime(2021, 5, 19, 10, 40, 18, tzinfo=tzlocal()), finding.date) - self.assertFalse(finding.verified) - self.assertEqual("modules_images", finding.file_path) - self.assertEqual(156, finding.line) - self.assertEqual(1, finding.nb_occurences) - self.assertEqual(798, finding.cwe) - self.assertIsNotNone(finding.description) - self.assertFalse(finding.false_p) + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("Secret Keyword", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual(datetime.datetime(2021, 5, 19, 10, 40, 18, tzinfo=tzlocal()), finding.date) + self.assertFalse(finding.verified) + self.assertEqual("modules_images", finding.file_path) + self.assertEqual(156, finding.line) + self.assertEqual(1, finding.nb_occurences) + self.assertEqual(798, finding.cwe) + self.assertIsNotNone(finding.description) + self.assertFalse(finding.false_p) - with self.subTest(i=2): - finding = findings[2] - self.assertEqual("Secret Keyword", finding.title) - self.assertEqual("High", finding.severity) - self.assertEqual(datetime.datetime(2021, 5, 19, 10, 40, 18, tzinfo=tzlocal()), finding.date) - self.assertFalse(finding.verified) - self.assertEqual("example/pkg/docker_registry_watcher/docker_config.go", finding.file_path) - self.assertEqual(109, finding.line) - self.assertEqual(1, finding.nb_occurences) - self.assertEqual(798, finding.cwe) - self.assertIsNotNone(finding.description) - self.assertFalse(finding.false_p) + with self.subTest(i=2): + finding = findings[2] + self.assertEqual("Secret Keyword", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual(datetime.datetime(2021, 5, 19, 10, 40, 18, tzinfo=tzlocal()), finding.date) + self.assertFalse(finding.verified) + self.assertEqual("example/pkg/docker_registry_watcher/docker_config.go", finding.file_path) + self.assertEqual(109, finding.line) + self.assertEqual(1, finding.nb_occurences) + self.assertEqual(798, finding.cwe) + self.assertIsNotNone(finding.description) + self.assertFalse(finding.false_p) - with self.subTest(i=3): - finding = findings[3] - self.assertEqual("Secret Keyword", finding.title) - self.assertEqual("High", finding.severity) - self.assertEqual(datetime.datetime(2021, 5, 19, 10, 40, 18, tzinfo=tzlocal()), finding.date) - self.assertFalse(finding.verified) - self.assertEqual("example/pkg/docker_registry_watcher/docker_registry_watcher.go", finding.file_path) - self.assertEqual(112, finding.line) - self.assertEqual(1, finding.nb_occurences) - self.assertEqual(798, finding.cwe) - self.assertIsNotNone(finding.description) - self.assertTrue(finding.false_p) + with self.subTest(i=3): + finding = findings[3] + self.assertEqual("Secret Keyword", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual(datetime.datetime(2021, 5, 19, 10, 40, 18, tzinfo=tzlocal()), finding.date) + self.assertFalse(finding.verified) + self.assertEqual("example/pkg/docker_registry_watcher/docker_registry_watcher.go", finding.file_path) + self.assertEqual(112, finding.line) + self.assertEqual(1, finding.nb_occurences) + self.assertEqual(798, finding.cwe) + self.assertIsNotNone(finding.description) + self.assertTrue(finding.false_p) diff --git a/unittests/tools/test_dockerbench_parser.py b/unittests/tools/test_dockerbench_parser.py index 02466d04a8..0f10d41b46 100644 --- a/unittests/tools/test_dockerbench_parser.py +++ b/unittests/tools/test_dockerbench_parser.py @@ -6,61 +6,59 @@ class TestDockerBenchParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/dockerbench/docker-bench-report-zero-vulns.json" - ) - parser = DockerBenchParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(0, len(findings)) + ) as testfile: + parser = DockerBenchParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_finding(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/dockerbench/docker-bench-report-single-vuln.json" - ) - parser = DockerBenchParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("High", finding.severity) - self.assertEqual("2.11", finding.unique_id_from_tool) - self.assertIn("2.11 -", finding.title) - self.assertIn("some kind of remediation could be here", finding.mitigation) - self.assertIn("Ensure base device size is not changed until needed", finding.description) + ) as testfile: + parser = DockerBenchParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("High", finding.severity) + self.assertEqual("2.11", finding.unique_id_from_tool) + self.assertIn("2.11 -", finding.title) + self.assertIn("some kind of remediation could be here", finding.mitigation) + self.assertIn("Ensure base device size is not changed until needed", finding.description) def test_parse_file_with_multiple_vuln_has_multiple_findings(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/dockerbench/docker-bench-report-many-vulns.json" - ) - parser = DockerBenchParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(len(findings), 50) - self.assertEqual(sum(1 for f in findings if f.severity.upper() == 'CRITICAL'), 0) - self.assertEqual(sum(1 for f in findings if f.severity.upper() == 'HIGH'), 32) - self.assertEqual(sum(1 for f in findings if f.severity.upper() == 'LOW'), 16) - self.assertEqual(sum(1 for f in findings if f.severity.upper() == 'INFO'), 2) + ) as testfile: + parser = DockerBenchParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(len(findings), 50) + self.assertEqual(sum(1 for f in findings if f.severity.upper() == 'CRITICAL'), 0) + self.assertEqual(sum(1 for f in findings if f.severity.upper() == 'HIGH'), 32) + self.assertEqual(sum(1 for f in findings if f.severity.upper() == 'LOW'), 16) + self.assertEqual(sum(1 for f in findings if f.severity.upper() == 'INFO'), 2) - finding = findings[3] - self.assertEqual("High", finding.severity) - self.assertEqual("1.1.4", finding.unique_id_from_tool) - self.assertIn("1.1.4 -", finding.title) - self.assertIn("Ensure auditing is configured for Docker files and directories -/run/containerd (Automated)", finding.description) - self.assertIn("Install auditd. Add -a exit,always -F path=/run/containerd -F perm=war -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart.", finding.mitigation) - self.assertIn("Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions.", finding.mitigation) + finding = findings[3] + self.assertEqual("High", finding.severity) + self.assertEqual("1.1.4", finding.unique_id_from_tool) + self.assertIn("1.1.4 -", finding.title) + self.assertIn("Ensure auditing is configured for Docker files and directories -/run/containerd (Automated)", finding.description) + self.assertIn("Install auditd. Add -a exit,always -F path=/run/containerd -F perm=war -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart.", finding.mitigation) + self.assertIn("Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions.", finding.mitigation) - finding = findings[27] - self.assertEqual("Low", finding.severity) - self.assertEqual("2.18", finding.unique_id_from_tool) - self.assertIn("2.18 -", finding.title) - self.assertIn("Ensure that experimental features are not implemented in production (Scored)", finding.description) - self.assertIn("You should not pass --experimental as a runtime parameter to the Docker daemon on production systems.", finding.mitigation) - self.assertIn("mitigation impact: None.", finding.mitigation) + finding = findings[27] + self.assertEqual("Low", finding.severity) + self.assertEqual("2.18", finding.unique_id_from_tool) + self.assertIn("2.18 -", finding.title) + self.assertIn("Ensure that experimental features are not implemented in production (Scored)", finding.description) + self.assertIn("You should not pass --experimental as a runtime parameter to the Docker daemon on production systems.", finding.mitigation) + self.assertIn("mitigation impact: None.", finding.mitigation) - finding = findings[39] - self.assertEqual("Info", finding.severity) - self.assertEqual("4.5", finding.unique_id_from_tool) - self.assertIn("4.5 -", finding.title) - self.assertIn("Ensure Content trust for Docker is Enabled (Automated)", finding.description) - self.assertIn("Add DOCKER_CONTENT_TRUST variable to the /etc/environment file using command echo DOCKER_CONTENT_TRUST=1 | sudo tee -a /etc/environment.", finding.mitigation) - self.assertIn("This prevents users from working with tagged images unless they contain a signature.", finding.mitigation) + finding = findings[39] + self.assertEqual("Info", finding.severity) + self.assertEqual("4.5", finding.unique_id_from_tool) + self.assertIn("4.5 -", finding.title) + self.assertIn("Ensure Content trust for Docker is Enabled (Automated)", finding.description) + self.assertIn("Add DOCKER_CONTENT_TRUST variable to the /etc/environment file using command echo DOCKER_CONTENT_TRUST=1 | sudo tee -a /etc/environment.", finding.mitigation) + self.assertIn("This prevents users from working with tagged images unless they contain a signature.", finding.mitigation) diff --git a/unittests/tools/test_dockle_parser.py b/unittests/tools/test_dockle_parser.py index affa7b4ebc..77f9096594 100644 --- a/unittests/tools/test_dockle_parser.py +++ b/unittests/tools/test_dockle_parser.py @@ -6,43 +6,43 @@ class TestDockleParser(DojoTestCase): def test_parse_no_findings(self): - testfile = open("unittests/scans/dockle/no_findings.json") - parser = DockleParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/dockle/no_findings.json") as testfile: + parser = DockleParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_many_findings(self): - testfile = open("unittests/scans/dockle/many_findings.json") - parser = DockleParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(3, len(findings)) + with open("unittests/scans/dockle/many_findings.json") as testfile: + parser = DockleParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(3, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("CIS-DI-0001: Create a user for the container", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertIsNotNone(finding.description) - self.assertTrue(finding.static_finding) - self.assertFalse(finding.dynamic_finding) - self.assertEqual(1, finding.nb_occurences) - self.assertEqual("CIS-DI-0001", finding.vuln_id_from_tool) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("CIS-DI-0001: Create a user for the container", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertIsNotNone(finding.description) + self.assertTrue(finding.static_finding) + self.assertFalse(finding.dynamic_finding) + self.assertEqual(1, finding.nb_occurences) + self.assertEqual("CIS-DI-0001", finding.vuln_id_from_tool) - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("CIS-DI-0005: Enable Content trust for Docker", finding.title) - self.assertEqual("Low", finding.severity) - self.assertIsNotNone(finding.description) - self.assertTrue(finding.static_finding) - self.assertFalse(finding.dynamic_finding) - self.assertEqual(1, finding.nb_occurences) - self.assertEqual("CIS-DI-0005", finding.vuln_id_from_tool) + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("CIS-DI-0005: Enable Content trust for Docker", finding.title) + self.assertEqual("Low", finding.severity) + self.assertIsNotNone(finding.description) + self.assertTrue(finding.static_finding) + self.assertFalse(finding.dynamic_finding) + self.assertEqual(1, finding.nb_occurences) + self.assertEqual("CIS-DI-0005", finding.vuln_id_from_tool) - with self.subTest(i=2): - finding = findings[2] - self.assertEqual("CIS-DI-0008: Confirm safety of setuid/setgid files", finding.title) - self.assertEqual("Low", finding.severity) - self.assertIsNotNone(finding.description) - self.assertTrue(finding.static_finding) - self.assertFalse(finding.dynamic_finding) - self.assertEqual(1, finding.nb_occurences) - self.assertEqual("CIS-DI-0008", finding.vuln_id_from_tool) + with self.subTest(i=2): + finding = findings[2] + self.assertEqual("CIS-DI-0008: Confirm safety of setuid/setgid files", finding.title) + self.assertEqual("Low", finding.severity) + self.assertIsNotNone(finding.description) + self.assertTrue(finding.static_finding) + self.assertFalse(finding.dynamic_finding) + self.assertEqual(1, finding.nb_occurences) + self.assertEqual("CIS-DI-0008", finding.vuln_id_from_tool) diff --git a/unittests/tools/test_dsop_parser.py b/unittests/tools/test_dsop_parser.py index a266f9a255..4a89113cd8 100644 --- a/unittests/tools/test_dsop_parser.py +++ b/unittests/tools/test_dsop_parser.py @@ -6,17 +6,17 @@ class TestDsopParser(DojoTestCase): def test_zero_findings(self): - testfile = open("unittests/scans/dsop/zero_vuln.xlsx", "rb") - parser = DsopParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(len(findings), 0) + with open("unittests/scans/dsop/zero_vuln.xlsx", "rb") as testfile: + parser = DsopParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(len(findings), 0) def test_many_findings(self): - testfile = open("unittests/scans/dsop/many_vuln.xlsx", "rb") - parser = DsopParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(len(findings), 4) - finding = findings[0] - self.assertEqual("Low", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2019-15587", finding.unsaved_vulnerability_ids[0]) + with open("unittests/scans/dsop/many_vuln.xlsx", "rb") as testfile: + parser = DsopParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(len(findings), 4) + finding = findings[0] + self.assertEqual("Low", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2019-15587", finding.unsaved_vulnerability_ids[0]) diff --git a/unittests/tools/test_fortify_parser.py b/unittests/tools/test_fortify_parser.py index c0db182c2d..a9527fa6ee 100644 --- a/unittests/tools/test_fortify_parser.py +++ b/unittests/tools/test_fortify_parser.py @@ -5,85 +5,85 @@ class TestFortifyParser(DojoTestCase): def test_fortify_many_findings(self): - testfile = open("unittests/scans/fortify/fortify_many_findings.xml") - parser = FortifyParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(324, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Poor Logging Practice: Use of a System Output Stream - XXE.java: 81", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual("src/main/java/org/joychou/controller/XXE.java", finding.file_path) - self.assertEqual(81, finding.line) + with open("unittests/scans/fortify/fortify_many_findings.xml") as testfile: + parser = FortifyParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(324, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Poor Logging Practice: Use of a System Output Stream - XXE.java: 81", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual("src/main/java/org/joychou/controller/XXE.java", finding.file_path) + self.assertEqual(81, finding.line) def test_fortify_few_findings(self): - testfile = open("unittests/scans/fortify/fortify_few_findings.xml") - parser = FortifyParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(2, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Privilege Management: Unnecessary Permission - AndroidManifest.xml: 11", finding.title) - self.assertEqual("High", finding.severity) - self.assertEqual("app/build/intermediates/bundle_manifest/developDebug/processDevelopDebugManifest/bundle-manifest/AndroidManifest.xml", finding.file_path) - self.assertEqual(11, finding.line) - self.assertEqual('53C25D2FC6950554F16D3CEF9E41EF6F', finding.unique_id_from_tool) + with open("unittests/scans/fortify/fortify_few_findings.xml") as testfile: + parser = FortifyParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(2, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Privilege Management: Unnecessary Permission - AndroidManifest.xml: 11", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual("app/build/intermediates/bundle_manifest/developDebug/processDevelopDebugManifest/bundle-manifest/AndroidManifest.xml", finding.file_path) + self.assertEqual(11, finding.line) + self.assertEqual('53C25D2FC6950554F16D3CEF9E41EF6F', finding.unique_id_from_tool) def test_fortify_few_findings_count_chart(self): - testfile = open("unittests/scans/fortify/fortify_few_findings_count_chart.xml") - parser = FortifyParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(3, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Privilege Management: Unnecessary Permission - AndroidManifest.xml: 11", finding.title) - self.assertEqual("High", finding.severity) - self.assertEqual("app/build/intermediates/bundle_manifest/developDebug/processDevelopDebugManifest/bundle-manifest/AndroidManifest.xml", finding.file_path) - self.assertEqual(11, finding.line) - self.assertEqual('53C25D2FC6950554F16D3CEF9E41EF6F', finding.unique_id_from_tool) + with open("unittests/scans/fortify/fortify_few_findings_count_chart.xml") as testfile: + parser = FortifyParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(3, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Privilege Management: Unnecessary Permission - AndroidManifest.xml: 11", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual("app/build/intermediates/bundle_manifest/developDebug/processDevelopDebugManifest/bundle-manifest/AndroidManifest.xml", finding.file_path) + self.assertEqual(11, finding.line) + self.assertEqual('53C25D2FC6950554F16D3CEF9E41EF6F', finding.unique_id_from_tool) def test_fortify_issue6260(self): - testfile = open("unittests/scans/fortify/issue6260.xml") - parser = FortifyParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(16, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Command Injection - command.java: 40", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual("src/main/java/command.java", finding.file_path) - self.assertEqual(40, finding.line) - self.assertEqual('7A2F1C728BDDBB17C7CB31CEDF5D8F85', finding.unique_id_from_tool) + with open("unittests/scans/fortify/issue6260.xml") as testfile: + parser = FortifyParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(16, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Command Injection - command.java: 40", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual("src/main/java/command.java", finding.file_path) + self.assertEqual(40, finding.line) + self.assertEqual('7A2F1C728BDDBB17C7CB31CEDF5D8F85', finding.unique_id_from_tool) def test_fortify_issue6082(self): - testfile = open("unittests/scans/fortify/issue6082.xml") - parser = FortifyParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(2, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Privacy Violation: Autocomplete - login.html: 19", finding.title) - self.assertEqual("High", finding.severity) - self.assertEqual("login.html", finding.file_path) - self.assertEqual(19, finding.line) - self.assertEqual('F46C9EF7203D77D83D3486BCDC78565F', finding.unique_id_from_tool) - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("Unreleased Resource: Database - MyContextListener.java: 28", finding.title) - self.assertEqual("High", finding.severity) - self.assertEqual("src/adrui/MyContextListener.java", finding.file_path) - self.assertEqual(28, finding.line) - self.assertEqual('B5B15F27E10F4D7799BD0ED1E6D34C5D', finding.unique_id_from_tool) + with open("unittests/scans/fortify/issue6082.xml") as testfile: + parser = FortifyParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(2, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Privacy Violation: Autocomplete - login.html: 19", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual("login.html", finding.file_path) + self.assertEqual(19, finding.line) + self.assertEqual('F46C9EF7203D77D83D3486BCDC78565F', finding.unique_id_from_tool) + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("Unreleased Resource: Database - MyContextListener.java: 28", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual("src/adrui/MyContextListener.java", finding.file_path) + self.assertEqual(28, finding.line) + self.assertEqual('B5B15F27E10F4D7799BD0ED1E6D34C5D', finding.unique_id_from_tool) def test_fortify_many_fdr_findings(self): - testfile = open("unittests/scans/fortify/many_findings.fpr") - parser = FortifyParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(61, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Cross-Site Request Forgery 114E5A67-3446-4DD5-B578-D0E6FDBB304E", finding.title) - self.assertEqual("High", finding.severity) - self.assertEqual('114E5A67-3446-4DD5-B578-D0E6FDBB304E', finding.unique_id_from_tool) - finding = findings[12] - self.assertEqual("Critical", finding.severity) + with open("unittests/scans/fortify/many_findings.fpr") as testfile: + parser = FortifyParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(61, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Cross-Site Request Forgery 114E5A67-3446-4DD5-B578-D0E6FDBB304E", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual('114E5A67-3446-4DD5-B578-D0E6FDBB304E', finding.unique_id_from_tool) + finding = findings[12] + self.assertEqual("Critical", finding.severity) diff --git a/unittests/tools/test_generic_parser.py b/unittests/tools/test_generic_parser.py index fd10079b07..677b5bf13b 100644 --- a/unittests/tools/test_generic_parser.py +++ b/unittests/tools/test_generic_parser.py @@ -24,24 +24,24 @@ def setUp(self): self.test = Test(engagement=self.engagement) def test_parse_report1(self): - file = open("unittests/scans/generic/generic_report1.csv") - parser = GenericParser() - findings = parser.get_findings(file, self.test) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual(5, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual("vulnerable.endpoint.com", endpoint.host) - self.assertEqual(443, endpoint.port) - self.assertEqual("resource1/asdf", endpoint.path) - endpoint = finding.unsaved_endpoints[1] - self.assertEqual("vulnerable.endpoint.com", endpoint.host) - self.assertEqual(443, endpoint.port) - self.assertEqual("resource2/qwerty", endpoint.path) - self.assertEqual("https", endpoint.protocol) + with open("unittests/scans/generic/generic_report1.csv") as file: + parser = GenericParser() + findings = parser.get_findings(file, self.test) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual(5, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual("vulnerable.endpoint.com", endpoint.host) + self.assertEqual(443, endpoint.port) + self.assertEqual("resource1/asdf", endpoint.path) + endpoint = finding.unsaved_endpoints[1] + self.assertEqual("vulnerable.endpoint.com", endpoint.host) + self.assertEqual(443, endpoint.port) + self.assertEqual("resource2/qwerty", endpoint.path) + self.assertEqual("https", endpoint.protocol) def test_parse_no_csv_content_no_findings(self): findings = "" @@ -433,218 +433,218 @@ def test_column_order_is_flexible(self): self.assertEqual(fields1, fields2) def test_parse_json(self): - file = open("unittests/scans/generic/generic_report1.json") - parser = GenericParser() - findings = parser.get_findings(file, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(2, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("test title", finding.title) - self.assertEqual(True, finding.active) - self.assertEqual(True, finding.verified) - self.assertEqual(False, finding.duplicate) - self.assertIn(finding.severity, Finding.SEVERITIES) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2020-36234", finding.unsaved_vulnerability_ids[0]) - self.assertEqual(261, finding.cwe) - self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N", finding.cvssv3) - self.assertIn("security", finding.tags) - self.assertIn("network", finding.tags) - self.assertEqual("3287f2d0-554f-491b-8516-3c349ead8ee5", finding.unique_id_from_tool) - self.assertEqual("TEST1", finding.vuln_id_from_tool) - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("test title2", finding.title) - self.assertEqual(True, finding.active) - self.assertEqual(False, finding.verified) - self.assertEqual(False, finding.duplicate) - self.assertIn(finding.severity, Finding.SEVERITIES) + with open("unittests/scans/generic/generic_report1.json") as file: + parser = GenericParser() + findings = parser.get_findings(file, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(2, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("test title", finding.title) + self.assertEqual(True, finding.active) + self.assertEqual(True, finding.verified) + self.assertEqual(False, finding.duplicate) + self.assertIn(finding.severity, Finding.SEVERITIES) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2020-36234", finding.unsaved_vulnerability_ids[0]) + self.assertEqual(261, finding.cwe) + self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N", finding.cvssv3) + self.assertIn("security", finding.tags) + self.assertIn("network", finding.tags) + self.assertEqual("3287f2d0-554f-491b-8516-3c349ead8ee5", finding.unique_id_from_tool) + self.assertEqual("TEST1", finding.vuln_id_from_tool) + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("test title2", finding.title) + self.assertEqual(True, finding.active) + self.assertEqual(False, finding.verified) + self.assertEqual(False, finding.duplicate) + self.assertIn(finding.severity, Finding.SEVERITIES) def test_parse_json2(self): - file = open("unittests/scans/generic/generic_report2.json") - parser = GenericParser() - findings = parser.get_findings(file, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(2, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("test title3", finding.title) - self.assertIn(finding.severity, Finding.SEVERITIES) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2020-36234", finding.unsaved_vulnerability_ids[0]) - self.assertEqual(261, finding.cwe) - self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N", finding.cvssv3) - self.assertEqual("Some mitigation", finding.mitigation) - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("test title4", finding.title) - self.assertIn(finding.severity, Finding.SEVERITIES) - self.assertEqual("Some mitigation", finding.mitigation) + with open("unittests/scans/generic/generic_report2.json") as file: + parser = GenericParser() + findings = parser.get_findings(file, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(2, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("test title3", finding.title) + self.assertIn(finding.severity, Finding.SEVERITIES) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2020-36234", finding.unsaved_vulnerability_ids[0]) + self.assertEqual(261, finding.cwe) + self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N", finding.cvssv3) + self.assertEqual("Some mitigation", finding.mitigation) + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("test title4", finding.title) + self.assertIn(finding.severity, Finding.SEVERITIES) + self.assertEqual("Some mitigation", finding.mitigation) def test_parse_json3(self): - file = open("unittests/scans/generic/generic_report3.json") - parser = GenericParser() - findings = parser.get_findings(file, Test()) - self.assertEqual(3, len(findings)) - with self.subTest(i=0): + with open("unittests/scans/generic/generic_report3.json") as file: + parser = GenericParser() + findings = parser.get_findings(file, Test()) + self.assertEqual(3, len(findings)) + with self.subTest(i=0): + finding = findings[0] + finding.clean() + self.assertEqual("test title with endpoints as dict", finding.title) + self.assertIn(finding.severity, Finding.SEVERITIES) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2020-36234", finding.unsaved_vulnerability_ids[0]) + self.assertEqual(261, finding.cwe) + self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N", finding.cvssv3) + self.assertEqual("Some mitigation", finding.mitigation) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + endpoint.clean() + self.assertEqual("exemple.com", endpoint.host) + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("test title with endpoints as strings", finding.title) + self.assertIn(finding.severity, Finding.SEVERITIES) + self.assertEqual("Some mitigation", finding.mitigation) + self.assertEqual(2, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + endpoint.clean() + self.assertEqual("http", endpoint.protocol) + self.assertEqual("urlfiltering.paloaltonetworks.com", endpoint.host) + self.assertEqual(80, endpoint.port) + self.assertEqual("test-command-and-control", endpoint.path) + endpoint = finding.unsaved_endpoints[1] + endpoint.clean() + self.assertEqual("https", endpoint.protocol) + self.assertEqual("urlfiltering.paloaltonetworks.com", endpoint.host) + self.assertEqual(2345, endpoint.port) + self.assertEqual("test-pest", endpoint.path) + + def test_parse_endpoints_and_vulnerability_ids_json(self): + with open("unittests/scans/generic/generic_report4.json") as file: + parser = GenericParser() + findings = parser.get_findings(file, Test()) + self.assertEqual(1, len(findings)) finding = findings[0] finding.clean() - self.assertEqual("test title with endpoints as dict", finding.title) - self.assertIn(finding.severity, Finding.SEVERITIES) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2020-36234", finding.unsaved_vulnerability_ids[0]) - self.assertEqual(261, finding.cwe) - self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N", finding.cvssv3) - self.assertEqual("Some mitigation", finding.mitigation) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - endpoint.clean() - self.assertEqual("exemple.com", endpoint.host) - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("test title with endpoints as strings", finding.title) - self.assertIn(finding.severity, Finding.SEVERITIES) - self.assertEqual("Some mitigation", finding.mitigation) - self.assertEqual(2, len(finding.unsaved_endpoints)) + self.assertEqual(4, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] endpoint.clean() - self.assertEqual("http", endpoint.protocol) - self.assertEqual("urlfiltering.paloaltonetworks.com", endpoint.host) - self.assertEqual(80, endpoint.port) - self.assertEqual("test-command-and-control", endpoint.path) + self.assertEqual("www.example.com", endpoint.host) + endpoint = finding.unsaved_endpoints[1] endpoint.clean() - self.assertEqual("https", endpoint.protocol) - self.assertEqual("urlfiltering.paloaltonetworks.com", endpoint.host) - self.assertEqual(2345, endpoint.port) - self.assertEqual("test-pest", endpoint.path) - - def test_parse_endpoints_and_vulnerability_ids_json(self): - file = open("unittests/scans/generic/generic_report4.json") - parser = GenericParser() - findings = parser.get_findings(file, Test()) - self.assertEqual(1, len(findings)) - finding = findings[0] - finding.clean() - self.assertEqual(4, len(finding.unsaved_endpoints)) - - endpoint = finding.unsaved_endpoints[0] - endpoint.clean() - self.assertEqual("www.example.com", endpoint.host) + self.assertEqual("localhost", endpoint.host) - endpoint = finding.unsaved_endpoints[1] - endpoint.clean() - self.assertEqual("localhost", endpoint.host) - - endpoint = finding.unsaved_endpoints[2] - endpoint.clean() - self.assertEqual("127.0.0.1", endpoint.host) - self.assertEqual(80, endpoint.port) + endpoint = finding.unsaved_endpoints[2] + endpoint.clean() + self.assertEqual("127.0.0.1", endpoint.host) + self.assertEqual(80, endpoint.port) - endpoint = finding.unsaved_endpoints[3] - endpoint.clean() - self.assertEqual("foo.bar", endpoint.host) - self.assertEqual("path", endpoint.path) + endpoint = finding.unsaved_endpoints[3] + endpoint.clean() + self.assertEqual("foo.bar", endpoint.host) + self.assertEqual("path", endpoint.path) - self.assertEqual(2, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("GHSA-5mrr-rgp6-x4gr", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("CVE-2015-9235", finding.unsaved_vulnerability_ids[1]) + self.assertEqual(2, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("GHSA-5mrr-rgp6-x4gr", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("CVE-2015-9235", finding.unsaved_vulnerability_ids[1]) def test_parse_host_and_vulnerability_id_csv(self): - file = open("unittests/scans/generic/generic_report4.csv") - parser = GenericParser() - findings = parser.get_findings(file, Test()) - self.assertEqual(4, len(findings)) + with open("unittests/scans/generic/generic_report4.csv") as file: + parser = GenericParser() + findings = parser.get_findings(file, Test()) + self.assertEqual(4, len(findings)) - finding = findings[0] - finding.clean() - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - endpoint.clean() - self.assertEqual("www.example.com", endpoint.host) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2015-9235", finding.unsaved_vulnerability_ids[0]) + finding = findings[0] + finding.clean() + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + endpoint.clean() + self.assertEqual("www.example.com", endpoint.host) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2015-9235", finding.unsaved_vulnerability_ids[0]) - finding = findings[1] - finding.clean() - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - endpoint.clean() - self.assertEqual("localhost", endpoint.host) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("GHSA-5mrr-rgp6-x4gr", finding.unsaved_vulnerability_ids[0]) + finding = findings[1] + finding.clean() + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + endpoint.clean() + self.assertEqual("localhost", endpoint.host) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("GHSA-5mrr-rgp6-x4gr", finding.unsaved_vulnerability_ids[0]) - finding = findings[2] - finding.clean() - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - endpoint.clean() - self.assertEqual("127.0.0.1", endpoint.host) - self.assertEqual(80, endpoint.port) - self.assertIsNone(finding.unsaved_vulnerability_ids) + finding = findings[2] + finding.clean() + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + endpoint.clean() + self.assertEqual("127.0.0.1", endpoint.host) + self.assertEqual(80, endpoint.port) + self.assertIsNone(finding.unsaved_vulnerability_ids) - finding = findings[3] - finding.clean() - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - endpoint.clean() - self.assertEqual("foo.bar", endpoint.host) - self.assertEqual("path", endpoint.path) - self.assertIsNone(finding.unsaved_vulnerability_ids) + finding = findings[3] + finding.clean() + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + endpoint.clean() + self.assertEqual("foo.bar", endpoint.host) + self.assertEqual("path", endpoint.path) + self.assertIsNone(finding.unsaved_vulnerability_ids) def test_parse_json_with_image(self): - file = open("unittests/scans/generic/test_with_image.json") - parser = GenericParser() - findings = parser.get_findings(file, Test()) - self.assertEqual(1, len(findings)) + with open("unittests/scans/generic/test_with_image.json") as file: + parser = GenericParser() + findings = parser.get_findings(file, Test()) + self.assertEqual(1, len(findings)) - finding = findings[0] - finding.clean() - self.assertEqual(1, len(finding.unsaved_files)) - image = finding.unsaved_files[0] - self.assertEqual("Screenshot from 2017-04-10 16-54-19.png", image.get("title")) - self.assertIn("data", image) + finding = findings[0] + finding.clean() + self.assertEqual(1, len(finding.unsaved_files)) + image = finding.unsaved_files[0] + self.assertEqual("Screenshot from 2017-04-10 16-54-19.png", image.get("title")) + self.assertIn("data", image) def test_parse_json_custom_test(self): - file = open("unittests/scans/generic/generic_custom_test.json") - parser = GenericParser() - tests = parser.get_tests(parser.get_scan_types()[0], file) - self.assertEqual(1, len(tests)) - findings = tests[0].findings - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("test title", finding.title) - self.assertEqual(True, finding.active) - self.assertEqual(True, finding.verified) - self.assertEqual(False, finding.duplicate) - self.assertIn(finding.severity, Finding.SEVERITIES) - self.assertEqual("CVE-2020-36234", finding.cve) - self.assertEqual(261, finding.cwe) - self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N", finding.cvssv3) - self.assertIn("security", finding.tags) - self.assertIn("network", finding.tags) - self.assertEqual("3287f2d0-554f-491b-8516-3c349ead8ee5", finding.unique_id_from_tool) - self.assertEqual("TEST1", finding.vuln_id_from_tool) + with open("unittests/scans/generic/generic_custom_test.json") as file: + parser = GenericParser() + tests = parser.get_tests(parser.get_scan_types()[0], file) + self.assertEqual(1, len(tests)) + findings = tests[0].findings + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("test title", finding.title) + self.assertEqual(True, finding.active) + self.assertEqual(True, finding.verified) + self.assertEqual(False, finding.duplicate) + self.assertIn(finding.severity, Finding.SEVERITIES) + self.assertEqual("CVE-2020-36234", finding.cve) + self.assertEqual(261, finding.cwe) + self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N", finding.cvssv3) + self.assertIn("security", finding.tags) + self.assertIn("network", finding.tags) + self.assertEqual("3287f2d0-554f-491b-8516-3c349ead8ee5", finding.unique_id_from_tool) + self.assertEqual("TEST1", finding.vuln_id_from_tool) def test_parse_json_empty_finding(self): - file = open("unittests/scans/generic/generic_empty.json") - parser = GenericParser() - with self.assertRaisesMessage(ValueError, - "Required fields are missing: ['description', 'severity', 'title']"): - parser.get_findings(file, Test()) + with open("unittests/scans/generic/generic_empty.json") as file: + parser = GenericParser() + with self.assertRaisesMessage(ValueError, + "Required fields are missing: ['description', 'severity', 'title']"): + parser.get_findings(file, Test()) def test_parse_json_invalid_finding(self): - file = open("unittests/scans/generic/generic_invalid.json") - parser = GenericParser() - with self.assertRaisesMessage(ValueError, - "Not allowed fields are present: ['invalid_field', 'last_status_update']"): - parser.get_findings(file, Test()) + with open("unittests/scans/generic/generic_invalid.json") as file: + parser = GenericParser() + with self.assertRaisesMessage(ValueError, + "Not allowed fields are present: ['invalid_field', 'last_status_update']"): + parser.get_findings(file, Test()) diff --git a/unittests/tools/test_ggshield_parser.py b/unittests/tools/test_ggshield_parser.py index 99c0ddd9d2..53797b77ba 100755 --- a/unittests/tools/test_ggshield_parser.py +++ b/unittests/tools/test_ggshield_parser.py @@ -6,37 +6,34 @@ class TestGgshieldParser(DojoTestCase): def test_parse_empty(self): - testfile = open("unittests/scans/ggshield/no_finding.json") - parser = GgshieldParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(0, len(findings)) + with open("unittests/scans/ggshield/no_finding.json") as testfile: + parser = GgshieldParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_one_finding(self): - testfile = open("unittests/scans/ggshield/one_finding.json") - parser = GgshieldParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("wapf/settings.py", finding.file_path) - self.assertEqual("Hard coded Django Secret Key found in wapf/settings.py", finding.title) - self.assertIsNotNone(finding.description) - self.assertEqual("2021-07-05", finding.date) + with open("unittests/scans/ggshield/one_finding.json") as testfile: + parser = GgshieldParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("wapf/settings.py", finding.file_path) + self.assertEqual("Hard coded Django Secret Key found in wapf/settings.py", finding.title) + self.assertIsNotNone(finding.description) + self.assertEqual("2021-07-05", finding.date) def test_parse_many_finding(self): - testfile = open("unittests/scans/ggshield/many_findings.json") - parser = GgshieldParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(2, len(findings)) - finding = findings[0] - self.assertEqual("wapf/settings.py", finding.file_path) - self.assertEqual("Hard coded Django Secret Key found in wapf/settings.py", finding.title) - self.assertIsNotNone(finding.description) - self.assertEqual("2021-03-13", finding.date) - finding = findings[1] - self.assertEqual("wapf/settings.py", finding.file_path) - self.assertEqual("Hard coded Django Secret Key found in wapf/settings.py", finding.title) - self.assertIsNotNone(finding.description) - self.assertEqual("2021-07-05", finding.date) + with open("unittests/scans/ggshield/many_findings.json") as testfile: + parser = GgshieldParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(2, len(findings)) + finding = findings[0] + self.assertEqual("wapf/settings.py", finding.file_path) + self.assertEqual("Hard coded Django Secret Key found in wapf/settings.py", finding.title) + self.assertIsNotNone(finding.description) + self.assertEqual("2021-03-13", finding.date) + finding = findings[1] + self.assertEqual("wapf/settings.py", finding.file_path) + self.assertEqual("Hard coded Django Secret Key found in wapf/settings.py", finding.title) + self.assertIsNotNone(finding.description) + self.assertEqual("2021-07-05", finding.date) diff --git a/unittests/tools/test_github_vulnerability_parser.py b/unittests/tools/test_github_vulnerability_parser.py index 9b54d9fdc6..df22540824 100644 --- a/unittests/tools/test_github_vulnerability_parser.py +++ b/unittests/tools/test_github_vulnerability_parser.py @@ -10,271 +10,271 @@ class TestGithubVulnerabilityParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): """sample with zero vulnerability""" - testfile = open("unittests/scans/github_vulnerability/github-0-vuln.json") - parser = GithubVulnerabilityParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/github_vulnerability/github-0-vuln.json") as testfile: + parser = GithubVulnerabilityParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_findings(self): """sample with one vulnerability""" - testfile = open("unittests/scans/github_vulnerability/github-1-vuln.json") - parser = GithubVulnerabilityParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - for finding in findings: - finding.clean() + with open("unittests/scans/github_vulnerability/github-1-vuln.json") as testfile: + parser = GithubVulnerabilityParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + for finding in findings: + finding.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual(finding.title, "Critical severity vulnerability that affects package") - self.assertEqual( - finding.description, - "This is a sample description for sample description from Github API.", - ) - self.assertEqual(finding.severity, "Critical") - self.assertEqual(finding.component_name, "package") - self.assertEqual(finding.unique_id_from_tool, "aabbccddeeff1122334401") + with self.subTest(i=0): + finding = findings[0] + self.assertEqual(finding.title, "Critical severity vulnerability that affects package") + self.assertEqual( + finding.description, + "This is a sample description for sample description from Github API.", + ) + self.assertEqual(finding.severity, "Critical") + self.assertEqual(finding.component_name, "package") + self.assertEqual(finding.unique_id_from_tool, "aabbccddeeff1122334401") def test_parse_file_with_one_vuln_has_one_finding_and_dependabot_direct_link(self): """sample with one vulnerability""" - testfile = open("unittests/scans/github_vulnerability/github-1-vuln-repo-dependabot-link.json") - parser = GithubVulnerabilityParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - for finding in findings: - finding.clean() + with open("unittests/scans/github_vulnerability/github-1-vuln-repo-dependabot-link.json") as testfile: + parser = GithubVulnerabilityParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + for finding in findings: + finding.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual(finding.title, "Critical severity vulnerability that affects package") - self.assertEqual( - finding.description, - "[https://github.com/OWASP/test-repository/security/dependabot/1](https://github.com/OWASP/test-repository/security/dependabot/1)\nThis is a sample description for sample description from Github API.", - ) - self.assertEqual(finding.severity, "Critical") - self.assertEqual(finding.component_name, "package") - self.assertEqual(finding.unique_id_from_tool, "aabbccddeeff1122334401") + with self.subTest(i=0): + finding = findings[0] + self.assertEqual(finding.title, "Critical severity vulnerability that affects package") + self.assertEqual( + finding.description, + "[https://github.com/OWASP/test-repository/security/dependabot/1](https://github.com/OWASP/test-repository/security/dependabot/1)\nThis is a sample description for sample description from Github API.", + ) + self.assertEqual(finding.severity, "Critical") + self.assertEqual(finding.component_name, "package") + self.assertEqual(finding.unique_id_from_tool, "aabbccddeeff1122334401") def test_parse_file_with_multiple_vuln_has_multiple_findings(self): """sample with five vulnerability""" - testfile = open("unittests/scans/github_vulnerability/github-5-vuln.json") - parser = GithubVulnerabilityParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(5, len(findings)) + with open("unittests/scans/github_vulnerability/github-5-vuln.json") as testfile: + parser = GithubVulnerabilityParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(5, len(findings)) def test_parse_file_issue2984(self): - testfile = open("unittests/scans/github_vulnerability/github_issue2984.json") - parser = GithubVulnerabilityParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(4, len(findings)) - for finding in findings: - finding.clean() + with open("unittests/scans/github_vulnerability/github_issue2984.json") as testfile: + parser = GithubVulnerabilityParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(4, len(findings)) + for finding in findings: + finding.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual(finding.title, "XXXXXXXXXXXXXXX") - self.assertEqual(finding.severity, "Medium") - self.assertEqual(finding.unique_id_from_tool, "xxxxxxxxx") - with self.subTest(i=1): - finding = findings[1] - self.assertEqual(finding.title, "AMSVNASCMASNCADNNJSADC") - self.assertEqual(finding.severity, "Medium") - self.assertEqual(finding.unique_id_from_tool, "AFDSFSDAFSDASFDAFSDASFD=") - with self.subTest(i=3): - finding = findings[3] - self.assertEqual(finding.title, "SDKPKÁSMNMKSDANJDOPASJOKNDOSAJ") - self.assertEqual(finding.severity, "Medium") - self.assertEqual(finding.unique_id_from_tool, "DASFMMFKLNKDSAKFSDLANJKKFDSNJSAKDFNJKDFS=") + with self.subTest(i=0): + finding = findings[0] + self.assertEqual(finding.title, "XXXXXXXXXXXXXXX") + self.assertEqual(finding.severity, "Medium") + self.assertEqual(finding.unique_id_from_tool, "xxxxxxxxx") + with self.subTest(i=1): + finding = findings[1] + self.assertEqual(finding.title, "AMSVNASCMASNCADNNJSADC") + self.assertEqual(finding.severity, "Medium") + self.assertEqual(finding.unique_id_from_tool, "AFDSFSDAFSDASFDAFSDASFD=") + with self.subTest(i=3): + finding = findings[3] + self.assertEqual(finding.title, "SDKPKÁSMNMKSDANJDOPASJOKNDOSAJ") + self.assertEqual(finding.severity, "Medium") + self.assertEqual(finding.unique_id_from_tool, "DASFMMFKLNKDSAKFSDLANJKKFDSNJSAKDFNJKDFS=") def test_parse_file_search(self): - testfile = open("unittests/scans/github_vulnerability/github_search.json") - parser = GithubVulnerabilityParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(2, len(findings)) - for finding in findings: - finding.clean() + with open("unittests/scans/github_vulnerability/github_search.json") as testfile: + parser = GithubVulnerabilityParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(2, len(findings)) + for finding in findings: + finding.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual(finding.title, "Deserialization of Untrusted Data in Log4j") - self.assertEqual(finding.severity, "Critical") - self.assertEqual(len(finding.unsaved_vulnerability_ids), 2) - self.assertEqual(finding.unsaved_vulnerability_ids[0], "GHSA-2qrg-x229-3v8q") - self.assertEqual(finding.unsaved_vulnerability_ids[1], "CVE-2019-17571") - self.assertEqual(finding.component_name, "log4j:log4j") - self.assertEqual(finding.unique_id_from_tool, "MDI4OlJlcG9zaXRvcnlWdWxuZXJhYmlsaXR5QWxlcnQyMDg2Nzc5NzY=") - with self.subTest(i=1): - finding = findings[1] - self.assertEqual(finding.title, "Deserialization of Untrusted Data in Log4j") - self.assertEqual(finding.severity, "Critical") - self.assertEqual(len(finding.unsaved_vulnerability_ids), 2) - self.assertEqual(finding.unsaved_vulnerability_ids[0], "GHSA-2qrg-x229-3v8q") - self.assertEqual(finding.unsaved_vulnerability_ids[1], "CVE-2019-17571") - self.assertEqual(finding.component_name, "log4j:log4j") - self.assertEqual(finding.unique_id_from_tool, "MDI4OlJlcG9zaXRvcnlWdWxuZXJhYmlsaXR5QWxlcnQ1NTE5NTI2OTM=") + with self.subTest(i=0): + finding = findings[0] + self.assertEqual(finding.title, "Deserialization of Untrusted Data in Log4j") + self.assertEqual(finding.severity, "Critical") + self.assertEqual(len(finding.unsaved_vulnerability_ids), 2) + self.assertEqual(finding.unsaved_vulnerability_ids[0], "GHSA-2qrg-x229-3v8q") + self.assertEqual(finding.unsaved_vulnerability_ids[1], "CVE-2019-17571") + self.assertEqual(finding.component_name, "log4j:log4j") + self.assertEqual(finding.unique_id_from_tool, "MDI4OlJlcG9zaXRvcnlWdWxuZXJhYmlsaXR5QWxlcnQyMDg2Nzc5NzY=") + with self.subTest(i=1): + finding = findings[1] + self.assertEqual(finding.title, "Deserialization of Untrusted Data in Log4j") + self.assertEqual(finding.severity, "Critical") + self.assertEqual(len(finding.unsaved_vulnerability_ids), 2) + self.assertEqual(finding.unsaved_vulnerability_ids[0], "GHSA-2qrg-x229-3v8q") + self.assertEqual(finding.unsaved_vulnerability_ids[1], "CVE-2019-17571") + self.assertEqual(finding.component_name, "log4j:log4j") + self.assertEqual(finding.unique_id_from_tool, "MDI4OlJlcG9zaXRvcnlWdWxuZXJhYmlsaXR5QWxlcnQ1NTE5NTI2OTM=") def test_parse_file_search2(self): """Search result with more data/attributes""" - testfile = open("unittests/scans/github_vulnerability/github_search2.json") - parser = GithubVulnerabilityParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(2, len(findings)) - for finding in findings: - finding.clean() + with open("unittests/scans/github_vulnerability/github_search2.json") as testfile: + parser = GithubVulnerabilityParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(2, len(findings)) + for finding in findings: + finding.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual(finding.title, "Deserialization of Untrusted Data in Log4j") - self.assertEqual(finding.severity, "Critical") - self.assertEqual(len(finding.unsaved_vulnerability_ids), 2) - self.assertEqual(finding.unsaved_vulnerability_ids[0], "GHSA-2qrg-x229-3v8q") - self.assertEqual(finding.unsaved_vulnerability_ids[1], "CVE-2019-17571") - self.assertEqual(finding.component_name, "log4j:log4j") - self.assertEqual(finding.unique_id_from_tool, "MDI4OlJlcG9zaXRvcnlWdWxuZXJhYmlsaXR5QWxlcnQyMDg2Nzc5NzY=") - with self.subTest(i=1): - finding = findings[1] - self.assertEqual(finding.title, "Deserialization of Untrusted Data in Log4j") - self.assertEqual(finding.severity, "Critical") - self.assertEqual(len(finding.unsaved_vulnerability_ids), 2) - self.assertEqual(finding.unsaved_vulnerability_ids[0], "GHSA-2qrg-x229-3v8q") - self.assertEqual(finding.unsaved_vulnerability_ids[1], "CVE-2019-17571") - self.assertEqual(finding.component_name, "log4j:log4j") - self.assertEqual(finding.unique_id_from_tool, "MDI4OlJlcG9zaXRvcnlWdWxuZXJhYmlsaXR5QWxlcnQ1NTE5NTI2OTM=") + with self.subTest(i=0): + finding = findings[0] + self.assertEqual(finding.title, "Deserialization of Untrusted Data in Log4j") + self.assertEqual(finding.severity, "Critical") + self.assertEqual(len(finding.unsaved_vulnerability_ids), 2) + self.assertEqual(finding.unsaved_vulnerability_ids[0], "GHSA-2qrg-x229-3v8q") + self.assertEqual(finding.unsaved_vulnerability_ids[1], "CVE-2019-17571") + self.assertEqual(finding.component_name, "log4j:log4j") + self.assertEqual(finding.unique_id_from_tool, "MDI4OlJlcG9zaXRvcnlWdWxuZXJhYmlsaXR5QWxlcnQyMDg2Nzc5NzY=") + with self.subTest(i=1): + finding = findings[1] + self.assertEqual(finding.title, "Deserialization of Untrusted Data in Log4j") + self.assertEqual(finding.severity, "Critical") + self.assertEqual(len(finding.unsaved_vulnerability_ids), 2) + self.assertEqual(finding.unsaved_vulnerability_ids[0], "GHSA-2qrg-x229-3v8q") + self.assertEqual(finding.unsaved_vulnerability_ids[1], "CVE-2019-17571") + self.assertEqual(finding.component_name, "log4j:log4j") + self.assertEqual(finding.unique_id_from_tool, "MDI4OlJlcG9zaXRvcnlWdWxuZXJhYmlsaXR5QWxlcnQ1NTE5NTI2OTM=") def test_parse_file_search3(self): """Search result with more data/attributes""" - testfile = open("unittests/scans/github_vulnerability/github_search3.json") - parser = GithubVulnerabilityParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(2, len(findings)) - for finding in findings: - finding.clean() + with open("unittests/scans/github_vulnerability/github_search3.json") as testfile: + parser = GithubVulnerabilityParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(2, len(findings)) + for finding in findings: + finding.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual(finding.title, "Deserialization of Untrusted Data in Log4j") - self.assertEqual(finding.severity, "Critical") - self.assertEqual(len(finding.unsaved_vulnerability_ids), 2) - self.assertEqual(finding.unsaved_vulnerability_ids[0], "GHSA-2qrg-x229-3v8q") - self.assertEqual(finding.unsaved_vulnerability_ids[1], "CVE-2019-17571") - self.assertEqual(finding.component_name, "log4j:log4j") - self.assertEqual(finding.cvssv3, "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H") - self.assertEqual(finding.file_path, "gogoph-crawler/pom.xml") - self.assertEqual(finding.unique_id_from_tool, "MDI4OlJlcG9zaXRvcnlWdWxuZXJhYmlsaXR5QWxlcnQyMDg2Nzc5NzY=") - with self.subTest(i=1): - finding = findings[1] - self.assertEqual(finding.title, "Deserialization of Untrusted Data in Log4j") - self.assertEqual(finding.severity, "Critical") - self.assertEqual(len(finding.unsaved_vulnerability_ids), 2) - self.assertEqual(finding.unsaved_vulnerability_ids[0], "GHSA-2qrg-x229-3v8q") - self.assertEqual(finding.unsaved_vulnerability_ids[1], "CVE-2019-17571") - self.assertEqual(finding.component_name, "log4j:log4j") - self.assertEqual(finding.cvssv3, "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H") - self.assertEqual(finding.file_path, "gogoph/pom.xml") - self.assertEqual(finding.unique_id_from_tool, "MDI4OlJlcG9zaXRvcnlWdWxuZXJhYmlsaXR5QWxlcnQ1NTE5NTI2OTM=") + with self.subTest(i=0): + finding = findings[0] + self.assertEqual(finding.title, "Deserialization of Untrusted Data in Log4j") + self.assertEqual(finding.severity, "Critical") + self.assertEqual(len(finding.unsaved_vulnerability_ids), 2) + self.assertEqual(finding.unsaved_vulnerability_ids[0], "GHSA-2qrg-x229-3v8q") + self.assertEqual(finding.unsaved_vulnerability_ids[1], "CVE-2019-17571") + self.assertEqual(finding.component_name, "log4j:log4j") + self.assertEqual(finding.cvssv3, "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H") + self.assertEqual(finding.file_path, "gogoph-crawler/pom.xml") + self.assertEqual(finding.unique_id_from_tool, "MDI4OlJlcG9zaXRvcnlWdWxuZXJhYmlsaXR5QWxlcnQyMDg2Nzc5NzY=") + with self.subTest(i=1): + finding = findings[1] + self.assertEqual(finding.title, "Deserialization of Untrusted Data in Log4j") + self.assertEqual(finding.severity, "Critical") + self.assertEqual(len(finding.unsaved_vulnerability_ids), 2) + self.assertEqual(finding.unsaved_vulnerability_ids[0], "GHSA-2qrg-x229-3v8q") + self.assertEqual(finding.unsaved_vulnerability_ids[1], "CVE-2019-17571") + self.assertEqual(finding.component_name, "log4j:log4j") + self.assertEqual(finding.cvssv3, "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H") + self.assertEqual(finding.file_path, "gogoph/pom.xml") + self.assertEqual(finding.unique_id_from_tool, "MDI4OlJlcG9zaXRvcnlWdWxuZXJhYmlsaXR5QWxlcnQ1NTE5NTI2OTM=") def test_parse_file_search4_null_cvss_vector(self): """Search result with more data/attributes""" - testfile = open("unittests/scans/github_vulnerability/github_search4_null_cvss_vector.json") - parser = GithubVulnerabilityParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(2, len(findings)) - for finding in findings: - finding.clean() + with open("unittests/scans/github_vulnerability/github_search4_null_cvss_vector.json") as testfile: + parser = GithubVulnerabilityParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(2, len(findings)) + for finding in findings: + finding.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual(finding.title, "Deserialization of Untrusted Data in Log4j") - self.assertEqual(finding.severity, "Critical") - self.assertEqual(len(finding.unsaved_vulnerability_ids), 2) - self.assertEqual(finding.unsaved_vulnerability_ids[0], "GHSA-2qrg-x229-3v8q") - self.assertEqual(finding.unsaved_vulnerability_ids[1], "CVE-2019-17571") - self.assertEqual(finding.component_name, "log4j:log4j") - self.assertEqual(finding.cvssv3, None) - self.assertEqual(finding.file_path, "gogoph-crawler/pom.xml") - self.assertEqual(finding.unique_id_from_tool, "MDI4OlJlcG9zaXRvcnlWdWxuZXJhYmlsaXR5QWxlcnQyMDg2Nzc5NzY=") - with self.subTest(i=1): - finding = findings[1] - self.assertEqual(finding.title, "Deserialization of Untrusted Data in Log4j") - self.assertEqual(finding.severity, "Critical") - self.assertEqual(len(finding.unsaved_vulnerability_ids), 2) - self.assertEqual(finding.unsaved_vulnerability_ids[0], "GHSA-2qrg-x229-3v8q") - self.assertEqual(finding.unsaved_vulnerability_ids[1], "CVE-2019-17571") - self.assertEqual(finding.component_name, "log4j:log4j") - self.assertEqual(finding.cvssv3, "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H") - self.assertEqual(finding.file_path, "gogoph/pom.xml") - self.assertEqual(finding.unique_id_from_tool, "MDI4OlJlcG9zaXRvcnlWdWxuZXJhYmlsaXR5QWxlcnQ1NTE5NTI2OTM=") + with self.subTest(i=0): + finding = findings[0] + self.assertEqual(finding.title, "Deserialization of Untrusted Data in Log4j") + self.assertEqual(finding.severity, "Critical") + self.assertEqual(len(finding.unsaved_vulnerability_ids), 2) + self.assertEqual(finding.unsaved_vulnerability_ids[0], "GHSA-2qrg-x229-3v8q") + self.assertEqual(finding.unsaved_vulnerability_ids[1], "CVE-2019-17571") + self.assertEqual(finding.component_name, "log4j:log4j") + self.assertEqual(finding.cvssv3, None) + self.assertEqual(finding.file_path, "gogoph-crawler/pom.xml") + self.assertEqual(finding.unique_id_from_tool, "MDI4OlJlcG9zaXRvcnlWdWxuZXJhYmlsaXR5QWxlcnQyMDg2Nzc5NzY=") + with self.subTest(i=1): + finding = findings[1] + self.assertEqual(finding.title, "Deserialization of Untrusted Data in Log4j") + self.assertEqual(finding.severity, "Critical") + self.assertEqual(len(finding.unsaved_vulnerability_ids), 2) + self.assertEqual(finding.unsaved_vulnerability_ids[0], "GHSA-2qrg-x229-3v8q") + self.assertEqual(finding.unsaved_vulnerability_ids[1], "CVE-2019-17571") + self.assertEqual(finding.component_name, "log4j:log4j") + self.assertEqual(finding.cvssv3, "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H") + self.assertEqual(finding.file_path, "gogoph/pom.xml") + self.assertEqual(finding.unique_id_from_tool, "MDI4OlJlcG9zaXRvcnlWdWxuZXJhYmlsaXR5QWxlcnQ1NTE5NTI2OTM=") def test_parse_cwe_and_date(self): - testfile = open("unittests/scans/github_vulnerability/github_h2.json") - parser = GithubVulnerabilityParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - for finding in findings: - finding.clean() + with open("unittests/scans/github_vulnerability/github_h2.json") as testfile: + parser = GithubVulnerabilityParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + for finding in findings: + finding.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual(finding.title, "RCE in H2 Console") - self.assertEqual(finding.severity, "Critical") - self.assertEqual(len(finding.unsaved_vulnerability_ids), 2) - self.assertEqual(finding.unsaved_vulnerability_ids[0], "GHSA-h376-j262-vhq6") - self.assertEqual(finding.unsaved_vulnerability_ids[1], "CVE-2021-42392") - self.assertEqual(finding.component_name, "com.h2database:h2") - self.assertEqual(finding.cvssv3, "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H") - self.assertEqual(finding.cvssv3_score, 9.8) - self.assertEqual(finding.cwe, 502) - self.assertEqual(datetime.datetime(2022, 5, 9, 9, 43, 40, tzinfo=tzlocal()), finding.date) - self.assertEqual(finding.file_path, "apache/cxf/syncope/cxf-syncope/pom.xml") - self.assertEqual(finding.active, True) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual(finding.title, "RCE in H2 Console") + self.assertEqual(finding.severity, "Critical") + self.assertEqual(len(finding.unsaved_vulnerability_ids), 2) + self.assertEqual(finding.unsaved_vulnerability_ids[0], "GHSA-h376-j262-vhq6") + self.assertEqual(finding.unsaved_vulnerability_ids[1], "CVE-2021-42392") + self.assertEqual(finding.component_name, "com.h2database:h2") + self.assertEqual(finding.cvssv3, "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H") + self.assertEqual(finding.cvssv3_score, 9.8) + self.assertEqual(finding.cwe, 502) + self.assertEqual(datetime.datetime(2022, 5, 9, 9, 43, 40, tzinfo=tzlocal()), finding.date) + self.assertEqual(finding.file_path, "apache/cxf/syncope/cxf-syncope/pom.xml") + self.assertEqual(finding.active, True) def test_parse_state(self): - testfile = open("unittests/scans/github_vulnerability/github_shiro.json") - parser = GithubVulnerabilityParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - for finding in findings: - finding.clean() + with open("unittests/scans/github_vulnerability/github_shiro.json") as testfile: + parser = GithubVulnerabilityParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + for finding in findings: + finding.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual(finding.title, "Apache Shiro vulnerable to a specially crafted HTTP request causing an authentication bypass") - self.assertEqual(finding.severity, "Critical") - self.assertEqual(len(finding.unsaved_vulnerability_ids), 2) - self.assertEqual(finding.unsaved_vulnerability_ids[0], "GHSA-f6jp-j6w3-w9hm") - self.assertEqual(finding.unsaved_vulnerability_ids[1], "CVE-2021-41303") - self.assertEqual(finding.component_name, "org.apache.shiro:shiro-core") - self.assertEqual(finding.cvssv3, "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H") - self.assertEqual(finding.cvssv3_score, 9.8) - self.assertEqual(finding.cwe, 287) - self.assertEqual(datetime.datetime(2021, 9, 20, 20, 33, 13, tzinfo=tzlocal()), finding.date) - self.assertEqual(finding.file_path, "apache/cxf/cxf-shiro/pom.xml") - self.assertEqual(finding.active, False) - self.assertEqual(finding.is_mitigated, True) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual(finding.title, "Apache Shiro vulnerable to a specially crafted HTTP request causing an authentication bypass") + self.assertEqual(finding.severity, "Critical") + self.assertEqual(len(finding.unsaved_vulnerability_ids), 2) + self.assertEqual(finding.unsaved_vulnerability_ids[0], "GHSA-f6jp-j6w3-w9hm") + self.assertEqual(finding.unsaved_vulnerability_ids[1], "CVE-2021-41303") + self.assertEqual(finding.component_name, "org.apache.shiro:shiro-core") + self.assertEqual(finding.cvssv3, "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H") + self.assertEqual(finding.cvssv3_score, 9.8) + self.assertEqual(finding.cwe, 287) + self.assertEqual(datetime.datetime(2021, 9, 20, 20, 33, 13, tzinfo=tzlocal()), finding.date) + self.assertEqual(finding.file_path, "apache/cxf/cxf-shiro/pom.xml") + self.assertEqual(finding.active, False) + self.assertEqual(finding.is_mitigated, True) def test_parser_version(self): - testfile = open("unittests/scans/github_vulnerability/github-vuln-version.json") - parser = GithubVulnerabilityParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - for finding in findings: - finding.clean() + with open("unittests/scans/github_vulnerability/github-vuln-version.json") as testfile: + parser = GithubVulnerabilityParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + for finding in findings: + finding.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual(finding.title, "Pivotal Spring Framework contains unsafe Java deserialization methods") - self.assertEqual(finding.severity, "Critical") - self.assertEqual(finding.component_name, "org.springframework:spring-web") - self.assertEqual(finding.component_version, "5.3.29") + with self.subTest(i=0): + finding = findings[0] + self.assertEqual(finding.title, "Pivotal Spring Framework contains unsafe Java deserialization methods") + self.assertEqual(finding.severity, "Critical") + self.assertEqual(finding.component_name, "org.springframework:spring-web") + self.assertEqual(finding.component_version, "5.3.29") def test_parse_file_issue_9582(self): - testfile = open("unittests/scans/github_vulnerability/issue_9582.json") - parser = GithubVulnerabilityParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(2, len(findings)) - for finding in findings: - finding.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual(finding.title, "py/clear-text-storage-sensitive-data") - self.assertEqual(finding.severity, "High") + with open("unittests/scans/github_vulnerability/issue_9582.json") as testfile: + parser = GithubVulnerabilityParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(2, len(findings)) + for finding in findings: + finding.clean() + with self.subTest(i=0): + finding = findings[0] + self.assertEqual(finding.title, "py/clear-text-storage-sensitive-data") + self.assertEqual(finding.severity, "High") diff --git a/unittests/tools/test_gitlab_dast_parser.py b/unittests/tools/test_gitlab_dast_parser.py index 353f7e73db..8e6a9a0817 100644 --- a/unittests/tools/test_gitlab_dast_parser.py +++ b/unittests/tools/test_gitlab_dast_parser.py @@ -5,139 +5,139 @@ class TestGitlabDastParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/gitlab_dast/gitlab_dast_zero_vul.json") - parser = GitlabDastParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/gitlab_dast/gitlab_dast_zero_vul.json") as testfile: + parser = GitlabDastParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_finding_v14(self): - testfile = open("unittests/scans/gitlab_dast/gitlab_dast_one_vul_v14.json") - parser = GitlabDastParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - finding = findings[0] + with open("unittests/scans/gitlab_dast/gitlab_dast_one_vul_v14.json") as testfile: + parser = GitlabDastParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + finding = findings[0] - # endpoint validation - for endpoint in finding.unsaved_endpoints: - endpoint.clean() + # endpoint validation + for endpoint in finding.unsaved_endpoints: + endpoint.clean() - self.assertEqual( - "5ec00bbc-2e53-44cb-83e9-3d35365277e3", finding.unique_id_from_tool - ) - self.assertEqual(3, finding.scanner_confidence) - # vulnerability does not have a name: fallback to using id as a title - self.assertEqual("5ec00bbc-2e53-44cb-83e9-3d35365277e3", finding.title) - self.assertIsInstance(finding.description, str) + self.assertEqual( + "5ec00bbc-2e53-44cb-83e9-3d35365277e3", finding.unique_id_from_tool + ) + self.assertEqual(3, finding.scanner_confidence) + # vulnerability does not have a name: fallback to using id as a title + self.assertEqual("5ec00bbc-2e53-44cb-83e9-3d35365277e3", finding.title) + self.assertIsInstance(finding.description, str) - date = finding.date.strftime("%Y-%m-%dT%H:%M:%S.%f") - self.assertEqual("2021-04-23T15:46:40.615000", date) - self.assertIsNone(finding.references) # should be None as there are no links + date = finding.date.strftime("%Y-%m-%dT%H:%M:%S.%f") + self.assertEqual("2021-04-23T15:46:40.615000", date) + self.assertIsNone(finding.references) # should be None as there are no links - self.assertEqual("High", finding.severity) - self.assertEqual("", finding.mitigation) # no solution proposed + self.assertEqual("High", finding.severity) + self.assertEqual("", finding.mitigation) # no solution proposed - self.assertEqual(359, finding.cwe) + self.assertEqual(359, finding.cwe) def test_parse_file_with_one_vuln_has_one_finding_v15(self): - testfile = open("unittests/scans/gitlab_dast/gitlab_dast_one_vul_v15.json") - parser = GitlabDastParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - finding = findings[0] + with open("unittests/scans/gitlab_dast/gitlab_dast_one_vul_v15.json") as testfile: + parser = GitlabDastParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + finding = findings[0] - # endpoint validation - for endpoint in finding.unsaved_endpoints: - endpoint.clean() + # endpoint validation + for endpoint in finding.unsaved_endpoints: + endpoint.clean() - self.assertEqual( - "5ec00bbc-2e53-44cb-83e9-3d35365277e3", finding.unique_id_from_tool - ) - self.assertEqual(None, finding.scanner_confidence) - # vulnerability does not have a name: fallback to using id as a title - self.assertEqual("5ec00bbc-2e53-44cb-83e9-3d35365277e3", finding.title) - self.assertIsInstance(finding.description, str) + self.assertEqual( + "5ec00bbc-2e53-44cb-83e9-3d35365277e3", finding.unique_id_from_tool + ) + self.assertEqual(None, finding.scanner_confidence) + # vulnerability does not have a name: fallback to using id as a title + self.assertEqual("5ec00bbc-2e53-44cb-83e9-3d35365277e3", finding.title) + self.assertIsInstance(finding.description, str) - date = finding.date.strftime("%Y-%m-%dT%H:%M:%S.%f") - self.assertEqual("2021-04-23T15:46:40.615000", date) - self.assertIsNone(finding.references) # should be None as there are no links + date = finding.date.strftime("%Y-%m-%dT%H:%M:%S.%f") + self.assertEqual("2021-04-23T15:46:40.615000", date) + self.assertIsNone(finding.references) # should be None as there are no links - self.assertEqual("High", finding.severity) - self.assertEqual("", finding.mitigation) # no solution proposed + self.assertEqual("High", finding.severity) + self.assertEqual("", finding.mitigation) # no solution proposed - self.assertEqual(359, finding.cwe) + self.assertEqual(359, finding.cwe) def test_parse_file_with_multiple_vuln_has_multiple_findings_v14(self): - testfile = open("unittests/scans/gitlab_dast/gitlab_dast_many_vul_v14.json") - parser = GitlabDastParser() - findings = parser.get_findings(testfile, Test()) - - self.assertEqual(10, len(findings)) - - # endpoint validation - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - - # the first one is done above - finding = findings[1] - # must-have fields - self.assertEqual(3, finding.scanner_confidence) - self.assertIn("Content Security Policy (CSP)", finding.description) - self.assertEqual(False, finding.static_finding) - self.assertEqual(True, finding.dynamic_finding) - - # conditional fields - date = finding.date.strftime("%Y-%m-%dT%H:%M:%S.%f") - self.assertEqual("2021-04-23T15:46:40.644000", date) - self.assertEqual( - "87e98ddf-7d75-444a-be6d-45400151a0fe", finding.unique_id_from_tool - ) - # vulnerability does not have a name: fallback to using id as a title - self.assertEqual(finding.unique_id_from_tool, finding.title) - self.assertEqual(16, finding.cwe) - self.assertIn("http://www.w3.org/TR/CSP/", finding.references) - self.assertEqual("Medium", finding.severity) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(str(endpoint), "http://api-server/v1/tree/10") - self.assertEqual(endpoint.host, "api-server") # host port path - self.assertEqual(endpoint.port, 80) - self.assertEqual(endpoint.path, "v1/tree/10") - self.assertIn("Ensure that your web server,", finding.mitigation) + with open("unittests/scans/gitlab_dast/gitlab_dast_many_vul_v14.json") as testfile: + parser = GitlabDastParser() + findings = parser.get_findings(testfile, Test()) + + self.assertEqual(10, len(findings)) + + # endpoint validation + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + + # the first one is done above + finding = findings[1] + # must-have fields + self.assertEqual(3, finding.scanner_confidence) + self.assertIn("Content Security Policy (CSP)", finding.description) + self.assertEqual(False, finding.static_finding) + self.assertEqual(True, finding.dynamic_finding) + + # conditional fields + date = finding.date.strftime("%Y-%m-%dT%H:%M:%S.%f") + self.assertEqual("2021-04-23T15:46:40.644000", date) + self.assertEqual( + "87e98ddf-7d75-444a-be6d-45400151a0fe", finding.unique_id_from_tool + ) + # vulnerability does not have a name: fallback to using id as a title + self.assertEqual(finding.unique_id_from_tool, finding.title) + self.assertEqual(16, finding.cwe) + self.assertIn("http://www.w3.org/TR/CSP/", finding.references) + self.assertEqual("Medium", finding.severity) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(str(endpoint), "http://api-server/v1/tree/10") + self.assertEqual(endpoint.host, "api-server") # host port path + self.assertEqual(endpoint.port, 80) + self.assertEqual(endpoint.path, "v1/tree/10") + self.assertIn("Ensure that your web server,", finding.mitigation) def test_parse_file_with_multiple_vuln_has_multiple_findings_v15(self): - testfile = open("unittests/scans/gitlab_dast/gitlab_dast_many_vul_v15.json") - parser = GitlabDastParser() - findings = parser.get_findings(testfile, Test()) - - self.assertEqual(10, len(findings)) - - # endpoint validation - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - - # the first one is done above - finding = findings[1] - # must-have fields - self.assertEqual(None, finding.scanner_confidence) - self.assertIn("Content Security Policy (CSP)", finding.description) - self.assertEqual(False, finding.static_finding) - self.assertEqual(True, finding.dynamic_finding) - - # conditional fields - date = finding.date.strftime("%Y-%m-%dT%H:%M:%S.%f") - self.assertEqual("2021-04-23T15:46:40.644000", date) - self.assertEqual( - "87e98ddf-7d75-444a-be6d-45400151a0fe", finding.unique_id_from_tool - ) - # vulnerability does not have a name: fallback to using id as a title - self.assertEqual(finding.unique_id_from_tool, finding.title) - self.assertEqual(16, finding.cwe) - self.assertIn("http://www.w3.org/TR/CSP/", finding.references) - self.assertEqual("Medium", finding.severity) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(str(endpoint), "http://api-server/v1/tree/10") - self.assertEqual(endpoint.host, "api-server") # host port path - self.assertEqual(endpoint.port, 80) - self.assertEqual(endpoint.path, "v1/tree/10") - self.assertIn("Ensure that your web server,", finding.mitigation) + with open("unittests/scans/gitlab_dast/gitlab_dast_many_vul_v15.json") as testfile: + parser = GitlabDastParser() + findings = parser.get_findings(testfile, Test()) + + self.assertEqual(10, len(findings)) + + # endpoint validation + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + + # the first one is done above + finding = findings[1] + # must-have fields + self.assertEqual(None, finding.scanner_confidence) + self.assertIn("Content Security Policy (CSP)", finding.description) + self.assertEqual(False, finding.static_finding) + self.assertEqual(True, finding.dynamic_finding) + + # conditional fields + date = finding.date.strftime("%Y-%m-%dT%H:%M:%S.%f") + self.assertEqual("2021-04-23T15:46:40.644000", date) + self.assertEqual( + "87e98ddf-7d75-444a-be6d-45400151a0fe", finding.unique_id_from_tool + ) + # vulnerability does not have a name: fallback to using id as a title + self.assertEqual(finding.unique_id_from_tool, finding.title) + self.assertEqual(16, finding.cwe) + self.assertIn("http://www.w3.org/TR/CSP/", finding.references) + self.assertEqual("Medium", finding.severity) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(str(endpoint), "http://api-server/v1/tree/10") + self.assertEqual(endpoint.host, "api-server") # host port path + self.assertEqual(endpoint.port, 80) + self.assertEqual(endpoint.path, "v1/tree/10") + self.assertIn("Ensure that your web server,", finding.mitigation) diff --git a/unittests/tools/test_gitlab_dep_scan_parser.py b/unittests/tools/test_gitlab_dep_scan_parser.py index 7e1a7f43ed..a4e691260e 100644 --- a/unittests/tools/test_gitlab_dep_scan_parser.py +++ b/unittests/tools/test_gitlab_dep_scan_parser.py @@ -6,75 +6,61 @@ class TestGitlabDepScanParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open( - f"{get_unit_tests_path()}/scans/gitlab_dep_scan/gl-dependency-scanning-report-0-vuln.json" - ) - parser = GitlabDepScanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open(f"{get_unit_tests_path()}/scans/gitlab_dep_scan/gl-dependency-scanning-report-0-vuln.json") as testfile: + parser = GitlabDepScanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_finding_v14(self): - testfile = open( - f"{get_unit_tests_path()}/scans/gitlab_dep_scan/gl-dependency-scanning-report-1-vuln_v14.json" - ) - parser = GitlabDepScanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) + with open(f"{get_unit_tests_path()}/scans/gitlab_dep_scan/gl-dependency-scanning-report-1-vuln_v14.json") as testfile: + parser = GitlabDepScanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) def test_parse_file_with_one_vuln_has_one_finding_v15(self): - testfile = open( - f"{get_unit_tests_path()}/scans/gitlab_dep_scan/gl-dependency-scanning-report-1-vuln_v15.json" - ) - parser = GitlabDepScanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) + with open(f"{get_unit_tests_path()}/scans/gitlab_dep_scan/gl-dependency-scanning-report-1-vuln_v15.json") as testfile: + parser = GitlabDepScanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) def test_parse_file_with_two_vuln_has_one_missing_component__v14(self): - testfile = open( - f"{get_unit_tests_path()}/scans/gitlab_dep_scan/gl-dependency-scanning-report-2-vuln-missing-component_v14.json" - ) - parser = GitlabDepScanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(2, len(findings)) - finding = findings[0] - self.assertEqual(None, finding.component_name) - self.assertEqual(None, finding.component_version) - finding = findings[1] - self.assertEqual("golang.org/x/crypto", finding.component_name) - self.assertEqual("v0.0.0-20190308221718-c2843e01d9a2", finding.component_version) + with open(f"{get_unit_tests_path()}/scans/gitlab_dep_scan/gl-dependency-scanning-report-2-vuln-missing-component_v14.json") as testfile: + parser = GitlabDepScanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(2, len(findings)) + finding = findings[0] + self.assertEqual(None, finding.component_name) + self.assertEqual(None, finding.component_version) + finding = findings[1] + self.assertEqual("golang.org/x/crypto", finding.component_name) + self.assertEqual("v0.0.0-20190308221718-c2843e01d9a2", finding.component_version) def test_parse_file_with_two_vuln_has_one_missing_component__v15(self): - testfile = open( - f"{get_unit_tests_path()}/scans/gitlab_dep_scan/gl-dependency-scanning-report-2-vuln-missing-component_v15.json" - ) - parser = GitlabDepScanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(2, len(findings)) - finding = findings[0] - self.assertEqual(None, finding.component_name) - self.assertEqual(None, finding.component_version) - finding = findings[1] - self.assertEqual("golang.org/x/crypto", finding.component_name) - self.assertEqual("v0.0.0-20190308221718-c2843e01d9a2", finding.component_version) + with open(f"{get_unit_tests_path()}/scans/gitlab_dep_scan/gl-dependency-scanning-report-2-vuln-missing-component_v15.json") as testfile: + parser = GitlabDepScanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(2, len(findings)) + finding = findings[0] + self.assertEqual(None, finding.component_name) + self.assertEqual(None, finding.component_version) + finding = findings[1] + self.assertEqual("golang.org/x/crypto", finding.component_name) + self.assertEqual("v0.0.0-20190308221718-c2843e01d9a2", finding.component_version) def test_parse_file_with_multiple_vuln_has_multiple_findings_v14(self): - testfile = open( - f"{get_unit_tests_path()}/scans/gitlab_dep_scan/gl-dependency-scanning-report-many-vuln_v14.json" - ) - parser = GitlabDepScanParser() - findings = parser.get_findings(testfile, Test()) - self.assertGreater(len(findings), 2) + with open(f"{get_unit_tests_path()}/scans/gitlab_dep_scan/gl-dependency-scanning-report-many-vuln_v14.json") as testfile: + parser = GitlabDepScanParser() + findings = parser.get_findings(testfile, Test()) + self.assertGreater(len(findings), 2) - self.assertEqual(1, len(findings[0].unsaved_vulnerability_ids)) - self.assertEqual("CVE-2020-29652", findings[0].unsaved_vulnerability_ids[0]) + self.assertEqual(1, len(findings[0].unsaved_vulnerability_ids)) + self.assertEqual("CVE-2020-29652", findings[0].unsaved_vulnerability_ids[0]) def test_parse_file_with_multiple_vuln_has_multiple_findings_v15(self): - testfile = open( - f"{get_unit_tests_path()}/scans/gitlab_dep_scan/gl-dependency-scanning-report-many-vuln_v15.json" - ) - parser = GitlabDepScanParser() - findings = parser.get_findings(testfile, Test()) - self.assertGreater(len(findings), 2) + with open(f"{get_unit_tests_path()}/scans/gitlab_dep_scan/gl-dependency-scanning-report-many-vuln_v15.json") as testfile: + parser = GitlabDepScanParser() + findings = parser.get_findings(testfile, Test()) + self.assertGreater(len(findings), 2) - self.assertEqual(1, len(findings[0].unsaved_vulnerability_ids)) - self.assertEqual("CVE-2020-29652", findings[0].unsaved_vulnerability_ids[0]) + self.assertEqual(1, len(findings[0].unsaved_vulnerability_ids)) + self.assertEqual("CVE-2020-29652", findings[0].unsaved_vulnerability_ids[0]) diff --git a/unittests/tools/test_gitleaks_parser.py b/unittests/tools/test_gitleaks_parser.py index 0c8f84138a..23b9878d83 100644 --- a/unittests/tools/test_gitleaks_parser.py +++ b/unittests/tools/test_gitleaks_parser.py @@ -6,110 +6,110 @@ class TestGitleaksParser(DojoTestCase): def test_parse_file_legacy_with_no_findings(self): - testfile = open(get_unit_tests_path() + "/scans/gitleaks/no_findings.json") - parser = GitleaksParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open(get_unit_tests_path() + "/scans/gitleaks/no_findings.json") as testfile: + parser = GitleaksParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_legacy_with_one_finding(self): - testfile = open(get_unit_tests_path() + "/scans/gitleaks/data_one.json") - parser = GitleaksParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Hard Coded Asymmetric Private Key", finding.title) - self.assertEqual("cert-key.pem", finding.file_path) - self.assertIsNone(finding.line) # some old version don't have this data - self.assertIn("AsymmetricPrivateKey", finding.unsaved_tags) + with open(get_unit_tests_path() + "/scans/gitleaks/data_one.json") as testfile: + parser = GitleaksParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Hard Coded Asymmetric Private Key", finding.title) + self.assertEqual("cert-key.pem", finding.file_path) + self.assertIsNone(finding.line) # some old version don't have this data + self.assertIn("AsymmetricPrivateKey", finding.unsaved_tags) def test_parse_file_legacy_with_multiple_finding(self): - testfile = open(get_unit_tests_path() + "/scans/gitleaks/data_many.json") - parser = GitleaksParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(2, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Hard Coded Github", finding.title) - self.assertEqual(".bashrc", finding.file_path) - self.assertIsNone(finding.line) # some old version don't have this data - self.assertIn("Github", finding.unsaved_tags) + with open(get_unit_tests_path() + "/scans/gitleaks/data_many.json") as testfile: + parser = GitleaksParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(2, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Hard Coded Github", finding.title) + self.assertEqual(".bashrc", finding.file_path) + self.assertIsNone(finding.line) # some old version don't have this data + self.assertIn("Github", finding.unsaved_tags) def test_parse_file_legacy_with_multiple_redacted_finding(self): - testfile = open(get_unit_tests_path() + "/scans/gitleaks/redacted_data_many.json") - parser = GitleaksParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(6, len(findings)) + with open(get_unit_tests_path() + "/scans/gitleaks/redacted_data_many.json") as testfile: + parser = GitleaksParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(6, len(findings)) def test_parse_file_legacy_from_issue4336(self): - testfile = open(get_unit_tests_path() + "/scans/gitleaks/issue4336.json") - parser = GitleaksParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Hard Coded Twitter Client ID", finding.title) - self.assertEqual("README.md", finding.file_path) - self.assertEqual(23, finding.line) + with open(get_unit_tests_path() + "/scans/gitleaks/issue4336.json") as testfile: + parser = GitleaksParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Hard Coded Twitter Client ID", finding.title) + self.assertEqual("README.md", finding.file_path) + self.assertEqual(23, finding.line) def test_parse_file_from_version_7_5_0(self): - testfile = open(get_unit_tests_path() + "/scans/gitleaks/version_7.5.0.json") - parser = GitleaksParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(4, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Hard Coded AWS Access Key", finding.title) - self.assertEqual("dojo/unittests/scans/gitlab_secret_detection_report/gitlab_secret_detection_report_1_vuln.json", finding.file_path) - self.assertEqual(13, finding.line) - self.assertIn("key", finding.unsaved_tags) - self.assertIn("AWS", finding.unsaved_tags) - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("Hard Coded Asymmetric Private Key", finding.title) - self.assertEqual("dojo/unittests/scans/gitlab_secret_detection_report/gitlab_secret_detection_report_3_vuln.json", finding.file_path) - self.assertEqual(13, finding.line) - self.assertIn("AsymmetricPrivateKey", finding.unsaved_tags) - with self.subTest(i=2): - finding = findings[2] - self.assertEqual("Hard Coded AWS Access Key", finding.title) - self.assertEqual("dojo/unittests/scans/gitlab_secret_detection_report/gitlab_secret_detection_report_3_vuln.json", finding.file_path) - self.assertEqual(44, finding.line) - self.assertIn("AWS", finding.unsaved_tags) - with self.subTest(i=3): - finding = findings[3] - self.assertEqual("Hard Coded AWS Access Key", finding.title) - self.assertEqual("dojo/unittests/tools/test_gitlab_secret_detection_report_parser.py", finding.file_path) - self.assertEqual(37, finding.line) - self.assertIn("AWS", finding.unsaved_tags) + with open(get_unit_tests_path() + "/scans/gitleaks/version_7.5.0.json") as testfile: + parser = GitleaksParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(4, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Hard Coded AWS Access Key", finding.title) + self.assertEqual("dojo/unittests/scans/gitlab_secret_detection_report/gitlab_secret_detection_report_1_vuln.json", finding.file_path) + self.assertEqual(13, finding.line) + self.assertIn("key", finding.unsaved_tags) + self.assertIn("AWS", finding.unsaved_tags) + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("Hard Coded Asymmetric Private Key", finding.title) + self.assertEqual("dojo/unittests/scans/gitlab_secret_detection_report/gitlab_secret_detection_report_3_vuln.json", finding.file_path) + self.assertEqual(13, finding.line) + self.assertIn("AsymmetricPrivateKey", finding.unsaved_tags) + with self.subTest(i=2): + finding = findings[2] + self.assertEqual("Hard Coded AWS Access Key", finding.title) + self.assertEqual("dojo/unittests/scans/gitlab_secret_detection_report/gitlab_secret_detection_report_3_vuln.json", finding.file_path) + self.assertEqual(44, finding.line) + self.assertIn("AWS", finding.unsaved_tags) + with self.subTest(i=3): + finding = findings[3] + self.assertEqual("Hard Coded AWS Access Key", finding.title) + self.assertEqual("dojo/unittests/tools/test_gitlab_secret_detection_report_parser.py", finding.file_path) + self.assertEqual(37, finding.line) + self.assertIn("AWS", finding.unsaved_tags) def test_parse_file_from_version_8(self): - testfile = open(get_unit_tests_path() + "/scans/gitleaks/gitleaks8_many.json") - parser = GitleaksParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(3, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Hard coded AWS found in /conf/aws.tf", finding.title) - self.assertEqual("/conf/aws.tf", finding.file_path) - self.assertEqual(2, finding.line) - self.assertIn("74d53286c550630f80847d37f68aa3065554ac813544072ccd1278da71fafe31", finding.description) - self.assertIn("9619c91b3fd2998be5d9ce198833d7ac9489d9bc378ad7cd28963d5a967f8699", finding.description) - self.assertIn("\n**Commit message:** Lorem ipsum dolor sit amet, consetetur sadipscing elitr", finding.description) - self.assertEqual(2, finding.nb_occurences) - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("Hard coded RSA private key found in conf/rsa.pk", finding.title) - description = '''**Secret:** -----BEGIN RSA PRIVATE KEY----- + with open(get_unit_tests_path() + "/scans/gitleaks/gitleaks8_many.json") as testfile: + parser = GitleaksParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(3, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Hard coded AWS found in /conf/aws.tf", finding.title) + self.assertEqual("/conf/aws.tf", finding.file_path) + self.assertEqual(2, finding.line) + self.assertIn("74d53286c550630f80847d37f68aa3065554ac813544072ccd1278da71fafe31", finding.description) + self.assertIn("9619c91b3fd2998be5d9ce198833d7ac9489d9bc378ad7cd28963d5a967f8699", finding.description) + self.assertIn("\n**Commit message:** Lorem ipsum dolor sit amet, consetetur sadipscing elitr", finding.description) + self.assertEqual(2, finding.nb_occurences) + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("Hard coded RSA private key found in conf/rsa.pk", finding.title) + description = '''**Secret:** -----BEGIN RSA PRIVATE KEY----- **Match:** -----BEGIN RSA PRIVATE KEY----- **Rule Id:** RSA-PK''' - self.assertEqual(description, finding.description) - self.assertIn("tag1", finding.unsaved_tags) - self.assertIn("tag2", finding.unsaved_tags) - with self.subTest(i=2): - finding = findings[2] - self.assertEqual("Hard coded Generic API Key found in tests/api.py", finding.title) - description = '''**Secret:** dfjksdjfs3294dfjlsdaf213 + self.assertEqual(description, finding.description) + self.assertIn("tag1", finding.unsaved_tags) + self.assertIn("tag2", finding.unsaved_tags) + with self.subTest(i=2): + finding = findings[2] + self.assertEqual("Hard coded Generic API Key found in tests/api.py", finding.title) + description = '''**Secret:** dfjksdjfs3294dfjlsdaf213 **Match:** apikey = "dfjksdjfs3294dfjlsdaf213" **Commit message:** ``` @@ -121,4 +121,4 @@ def test_parse_file_from_version_8(self): **Commit hash:** 69235ea9ea4d59e18e2cc3c295526de46aa1365c1f0c7a95a22ff1537acdf517 **Commit date:** 2016-09-16T18:17:59Z **Rule Id:** generic-api-key''' - self.assertEqual(description, finding.description) + self.assertEqual(description, finding.description) diff --git a/unittests/tools/test_gosec_parser.py b/unittests/tools/test_gosec_parser.py index c39adeeba6..104b9c19a2 100644 --- a/unittests/tools/test_gosec_parser.py +++ b/unittests/tools/test_gosec_parser.py @@ -6,11 +6,11 @@ class TestGosecParser(DojoTestCase): def test_parse_file_with_one_finding(self): - testfile = open("unittests/scans/gosec/many_vulns.json") - parser = GosecParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(28, len(findings)) - finding = findings[0] - self.assertEqual("Low", finding.severity) - self.assertEqual("/vagrant/go/src/govwa/app.go", finding.file_path) - self.assertEqual(79, finding.line) + with open("unittests/scans/gosec/many_vulns.json") as testfile: + parser = GosecParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(28, len(findings)) + finding = findings[0] + self.assertEqual("Low", finding.severity) + self.assertEqual("/vagrant/go/src/govwa/app.go", finding.file_path) + self.assertEqual(79, finding.line) diff --git a/unittests/tools/test_govulncheck_parser.py b/unittests/tools/test_govulncheck_parser.py index b098cd7ab3..99dd19108a 100644 --- a/unittests/tools/test_govulncheck_parser.py +++ b/unittests/tools/test_govulncheck_parser.py @@ -7,126 +7,123 @@ class TestGovulncheckParser(DojoTestCase): def test_parse_empty(self): with self.assertRaises(ValueError) as exp: - testfile = open("unittests/scans/govulncheck/empty.json") - parser = GovulncheckParser() - parser.get_findings(testfile, Test()) + with open("unittests/scans/govulncheck/empty.json") as testfile: + parser = GovulncheckParser() + parser.get_findings(testfile, Test()) self.assertIn( "Invalid JSON format", str(exp.exception) ) def test_parse_no_findings(self): - testfile = open("unittests/scans/govulncheck/no_vulns.json") - parser = GovulncheckParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/govulncheck/no_vulns.json") as testfile: + parser = GovulncheckParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_many_findings(self): - testfile = open("unittests/scans/govulncheck/many_vulns.json") - parser = GovulncheckParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - - self.assertEqual(3, len(findings)) - - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("GO-2022-1144", finding.title) - self.assertEqual("Info", finding.severity) - self.assertEqual("CVE-2022-41717", finding.cve) - self.assertEqual("stdlib", finding.component_name) - self.assertEqual("v1.19.0", finding.component_version) - self.assertEqual("GO-2022-1144", finding.unique_id_from_tool) - self.assertEqual("https://pkg.go.dev/vuln/GO-2022-1144", finding.url) - self.assertIsNotNone(finding.impact) - self.assertIsNotNone(finding.description) - self.assertEqual("https://go.dev/issue/56350", finding.references) - - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("GO-2022-1143", finding.title) - self.assertEqual("Info", finding.severity) - self.assertEqual("CVE-2022-41720", finding.cve) - self.assertEqual("stdlib", finding.component_name) - self.assertEqual("v1.19.0", finding.component_version) - self.assertEqual("GO-2022-1143", finding.unique_id_from_tool) - self.assertEqual("https://pkg.go.dev/vuln/GO-2022-1143", finding.url) - self.assertIsNotNone(finding.impact) - self.assertIsNotNone(finding.description) - self.assertEqual("https://go.dev/issue/56694", finding.references) - - with self.subTest(i=2): - finding = findings[2] - self.assertEqual("GO-2022-0969", finding.title) - self.assertEqual("Info", finding.severity) - self.assertEqual("CVE-2022-27664", finding.cve) - self.assertEqual("stdlib", finding.component_name) - self.assertEqual("v1.19.0", finding.component_version) - self.assertEqual("GO-2022-0969", finding.unique_id_from_tool) - self.assertEqual("https://pkg.go.dev/vuln/GO-2022-0969", finding.url) - self.assertIsNotNone(finding.impact) - self.assertIsNotNone(finding.description) - self.assertEqual("https://groups.google.com/g/golang-announce/c/x49AQzIVX-s", finding.references) + with open("unittests/scans/govulncheck/many_vulns.json") as testfile: + parser = GovulncheckParser() + findings = parser.get_findings(testfile, Test()) + + self.assertEqual(3, len(findings)) + + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("GO-2022-1144", finding.title) + self.assertEqual("Info", finding.severity) + self.assertEqual("CVE-2022-41717", finding.cve) + self.assertEqual("stdlib", finding.component_name) + self.assertEqual("v1.19.0", finding.component_version) + self.assertEqual("GO-2022-1144", finding.unique_id_from_tool) + self.assertEqual("https://pkg.go.dev/vuln/GO-2022-1144", finding.url) + self.assertIsNotNone(finding.impact) + self.assertIsNotNone(finding.description) + self.assertEqual("https://go.dev/issue/56350", finding.references) + + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("GO-2022-1143", finding.title) + self.assertEqual("Info", finding.severity) + self.assertEqual("CVE-2022-41720", finding.cve) + self.assertEqual("stdlib", finding.component_name) + self.assertEqual("v1.19.0", finding.component_version) + self.assertEqual("GO-2022-1143", finding.unique_id_from_tool) + self.assertEqual("https://pkg.go.dev/vuln/GO-2022-1143", finding.url) + self.assertIsNotNone(finding.impact) + self.assertIsNotNone(finding.description) + self.assertEqual("https://go.dev/issue/56694", finding.references) + + with self.subTest(i=2): + finding = findings[2] + self.assertEqual("GO-2022-0969", finding.title) + self.assertEqual("Info", finding.severity) + self.assertEqual("CVE-2022-27664", finding.cve) + self.assertEqual("stdlib", finding.component_name) + self.assertEqual("v1.19.0", finding.component_version) + self.assertEqual("GO-2022-0969", finding.unique_id_from_tool) + self.assertEqual("https://pkg.go.dev/vuln/GO-2022-0969", finding.url) + self.assertIsNotNone(finding.impact) + self.assertIsNotNone(finding.description) + self.assertEqual("https://groups.google.com/g/golang-announce/c/x49AQzIVX-s", finding.references) def test_parse_new_version_no_findings(self): - testfile = open("unittests/scans/govulncheck/no_vulns_new_version.json") - parser = GovulncheckParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/govulncheck/no_vulns_new_version.json") as testfile: + parser = GovulncheckParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_new_version_many_findings(self): - testfile = open("unittests/scans/govulncheck/many_vulns_new_version.json") - parser = GovulncheckParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - - self.assertEqual(1, len(findings)) - - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("GO-2023-1840 - stdlib - runtime", finding.title) - self.assertEqual("Info", finding.severity) - self.assertEqual("CVE-2023-29403", finding.cve) - self.assertEqual("stdlib", finding.component_name) - self.assertEqual("v1.20.1", finding.component_version) - self.assertEqual("GO-2023-1840", finding.unique_id_from_tool) - self.assertEqual("runtime", finding.file_path) - self.assertEqual("https://pkg.go.dev/vuln/GO-2023-1840", finding.url) - self.assertIsNotNone(finding.impact) - self.assertIsNotNone(finding.description) - self.assertIsNotNone(finding.references) + with open("unittests/scans/govulncheck/many_vulns_new_version.json") as testfile: + parser = GovulncheckParser() + findings = parser.get_findings(testfile, Test()) + + self.assertEqual(1, len(findings)) + + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("GO-2023-1840 - stdlib - runtime", finding.title) + self.assertEqual("Info", finding.severity) + self.assertEqual("CVE-2023-29403", finding.cve) + self.assertEqual("stdlib", finding.component_name) + self.assertEqual("v1.20.1", finding.component_version) + self.assertEqual("GO-2023-1840", finding.unique_id_from_tool) + self.assertEqual("runtime", finding.file_path) + self.assertEqual("https://pkg.go.dev/vuln/GO-2023-1840", finding.url) + self.assertIsNotNone(finding.impact) + self.assertIsNotNone(finding.description) + self.assertIsNotNone(finding.references) def test_parse_new_version_many_findings_custom_severity(self): - testfile = open("unittests/scans/govulncheck/many_vulns_new_version_custom_severity.json") - parser = GovulncheckParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - - self.assertEqual(2, len(findings)) - - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Low", finding.severity) - self.assertEqual("GO-2021-0113 - golang.org/x/text - golang.org/x/text/language", finding.title) - self.assertEqual("CVE-2021-38561", finding.cve) - self.assertEqual("golang.org/x/text", finding.component_name) - self.assertEqual("v0.3.5", finding.component_version) - self.assertEqual("GO-2021-0113", finding.unique_id_from_tool) - self.assertEqual("golang.org/x/text/language", finding.file_path) - self.assertEqual("https://pkg.go.dev/vuln/GO-2021-0113", finding.url) - self.assertIsNotNone(finding.impact) - self.assertIsNotNone(finding.description) - self.assertIsNotNone(finding.references) - - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("High", finding.severity) - self.assertEqual("GO-2022-1059 - golang.org/x/text - golang.org/x/text/language", finding.title) - self.assertEqual("CVE-2022-32149", finding.cve) - self.assertEqual("golang.org/x/text", finding.component_name) - self.assertEqual("v0.3.5", finding.component_version) - self.assertEqual("GO-2022-1059", finding.unique_id_from_tool) - self.assertEqual("golang.org/x/text/language", finding.file_path) - self.assertEqual("https://pkg.go.dev/vuln/GO-2022-1059", finding.url) - self.assertIsNotNone(finding.impact) - self.assertIsNotNone(finding.description) - self.assertIsNotNone(finding.references) + with open("unittests/scans/govulncheck/many_vulns_new_version_custom_severity.json") as testfile: + parser = GovulncheckParser() + findings = parser.get_findings(testfile, Test()) + + self.assertEqual(2, len(findings)) + + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Low", finding.severity) + self.assertEqual("GO-2021-0113 - golang.org/x/text - golang.org/x/text/language", finding.title) + self.assertEqual("CVE-2021-38561", finding.cve) + self.assertEqual("golang.org/x/text", finding.component_name) + self.assertEqual("v0.3.5", finding.component_version) + self.assertEqual("GO-2021-0113", finding.unique_id_from_tool) + self.assertEqual("golang.org/x/text/language", finding.file_path) + self.assertEqual("https://pkg.go.dev/vuln/GO-2021-0113", finding.url) + self.assertIsNotNone(finding.impact) + self.assertIsNotNone(finding.description) + self.assertIsNotNone(finding.references) + + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("High", finding.severity) + self.assertEqual("GO-2022-1059 - golang.org/x/text - golang.org/x/text/language", finding.title) + self.assertEqual("CVE-2022-32149", finding.cve) + self.assertEqual("golang.org/x/text", finding.component_name) + self.assertEqual("v0.3.5", finding.component_version) + self.assertEqual("GO-2022-1059", finding.unique_id_from_tool) + self.assertEqual("golang.org/x/text/language", finding.file_path) + self.assertEqual("https://pkg.go.dev/vuln/GO-2022-1059", finding.url) + self.assertIsNotNone(finding.impact) + self.assertIsNotNone(finding.description) + self.assertIsNotNone(finding.references) diff --git a/unittests/tools/test_h1_parser.py b/unittests/tools/test_h1_parser.py index 4cf655a453..74325261e9 100644 --- a/unittests/tools/test_h1_parser.py +++ b/unittests/tools/test_h1_parser.py @@ -6,19 +6,19 @@ class TestHackerOneParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_finding(self): - testfile = open("unittests/scans/h1/data_empty.json") - parser = H1Parser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/h1/data_empty.json") as testfile: + parser = H1Parser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_finding(self): - testfile = open("unittests/scans/h1/data_one.json") - parser = H1Parser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) + with open("unittests/scans/h1/data_one.json") as testfile: + parser = H1Parser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) def test_parse_file_with_multiple_vuln_has_multiple_finding(self): - testfile = open("unittests/scans/h1/data_many.json") - parser = H1Parser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(2, len(findings)) + with open("unittests/scans/h1/data_many.json") as testfile: + parser = H1Parser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(2, len(findings)) diff --git a/unittests/tools/test_harbor_vulnerability_parser.py b/unittests/tools/test_harbor_vulnerability_parser.py index 5f1048e1e4..aad6137a8b 100644 --- a/unittests/tools/test_harbor_vulnerability_parser.py +++ b/unittests/tools/test_harbor_vulnerability_parser.py @@ -6,62 +6,62 @@ class TestHarborVulnerabilityParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/harbor_vulnerability/harbor-0-vuln.json") - parser = HarborVulnerabilityParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/harbor_vulnerability/harbor-0-vuln.json") as testfile: + parser = HarborVulnerabilityParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) # Sample with One Test # + also verify data with one test def test_parse_file_with_one_vuln_has_one_findings(self): - testfile = open("unittests/scans/harbor_vulnerability/harbor-1-vuln.json") - parser = HarborVulnerabilityParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) + with open("unittests/scans/harbor_vulnerability/harbor-1-vuln.json") as testfile: + parser = HarborVulnerabilityParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual(finding.title, "CVE-YYYY-NNN - package (exploitable-version)") - self.assertEqual( - finding.description, - "This is a sample description for sample description from Harbor API.", - ) - self.assertEqual(finding.severity, 'Info') - self.assertEqual(finding.mitigation, 'Upgrade package to version unexploitable-version') - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual(finding.unsaved_vulnerability_ids[0], 'CVE-YYYY-NNN') - self.assertEqual(finding.component_name, 'package') - self.assertEqual(finding.component_version, 'exploitable-version') - self.assertEqual(finding.references, 'https://github.com/goharbor/harbor\n') + finding = findings[0] + self.assertEqual(finding.title, "CVE-YYYY-NNN - package (exploitable-version)") + self.assertEqual( + finding.description, + "This is a sample description for sample description from Harbor API.", + ) + self.assertEqual(finding.severity, 'Info') + self.assertEqual(finding.mitigation, 'Upgrade package to version unexploitable-version') + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual(finding.unsaved_vulnerability_ids[0], 'CVE-YYYY-NNN') + self.assertEqual(finding.component_name, 'package') + self.assertEqual(finding.component_version, 'exploitable-version') + self.assertEqual(finding.references, 'https://github.com/goharbor/harbor\n') # Sample with Multiple Test def test_parse_file_with_multiple_vuln_has_multiple_findings(self): - testfile = open("unittests/scans/harbor_vulnerability/harbor-5-vuln.json") - parser = HarborVulnerabilityParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(5, len(findings)) + with open("unittests/scans/harbor_vulnerability/harbor-5-vuln.json") as testfile: + parser = HarborVulnerabilityParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(5, len(findings)) - finding = findings[1] - self.assertEqual(finding.severity, 'High') - self.assertIsNone(finding.mitigation) - self.assertIsNone(finding.references) + finding = findings[1] + self.assertEqual(finding.severity, 'High') + self.assertIsNone(finding.mitigation) + self.assertIsNone(finding.references) # Sample with Trivy Test def test_parse_file_with_multiple_vuln_has_multiple_trivy_findings(self): - testfile = open("unittests/scans/harbor_vulnerability/harbor-trivy-vuln.json") - parser = HarborVulnerabilityParser() - findings = parser.get_findings(testfile, Test()) + with open("unittests/scans/harbor_vulnerability/harbor-trivy-vuln.json") as testfile: + parser = HarborVulnerabilityParser() + findings = parser.get_findings(testfile, Test()) - finding = findings[0] - self.assertEqual(finding.severity, 'High') - self.assertEqual(finding.cwe, '125') + finding = findings[0] + self.assertEqual(finding.severity, 'High') + self.assertEqual(finding.cwe, '125') # Sample with harborapi pip def test_parse_file_with_multiple_vuln_has_harborapi_pip_package(self): - testfile = open("unittests/scans/harbor_vulnerability/harborapipip.json") - parser = HarborVulnerabilityParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(2, len(findings)) + with open("unittests/scans/harbor_vulnerability/harborapipip.json") as testfile: + parser = HarborVulnerabilityParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(2, len(findings)) - finding = findings[0] - self.assertEqual(finding.severity, 'Medium') - self.assertEqual(finding.cwe, '787') + finding = findings[0] + self.assertEqual(finding.severity, 'Medium') + self.assertEqual(finding.cwe, '787') diff --git a/unittests/tools/test_humble_parser.py b/unittests/tools/test_humble_parser.py index ccd99d4437..d057010638 100644 --- a/unittests/tools/test_humble_parser.py +++ b/unittests/tools/test_humble_parser.py @@ -5,32 +5,30 @@ class TestHumbleParser(DojoTestCase): def test_humble_parser_with_many_findings(self): - testfile = open("unittests/scans/humble/many_findings.json") - parser = HumbleParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - testfile.close() - self.assertEqual(9, len(findings)) - finding = findings[0] - self.assertEqual(finding.unsaved_endpoints[0].host, "asdf.asf.hs") - self.assertEqual("Missing header: Clear-Site-Data", finding.title) - finding = findings[7] - self.assertEqual("Deprecated header: Strict-Transport-Security (Recommended Values)", finding.title) + with open("unittests/scans/humble/many_findings.json") as testfile: + parser = HumbleParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(9, len(findings)) + finding = findings[0] + self.assertEqual(finding.unsaved_endpoints[0].host, "asdf.asf.hs") + self.assertEqual("Missing header: Clear-Site-Data", finding.title) + finding = findings[7] + self.assertEqual("Deprecated header: Strict-Transport-Security (Recommended Values)", finding.title) def test_humble_parser_with_many_findings2(self): - testfile = open("unittests/scans/humble/many_findings2.json") - parser = HumbleParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - testfile.close() - self.assertEqual(16, len(findings)) - finding = findings[0] - self.assertEqual(finding.unsaved_endpoints[0].host, "testestset.com") - self.assertEqual("Missing header: Clear-Site-Data", finding.title) - finding = findings[7] - self.assertEqual("Missing header: Referrer-Policy", finding.title) - self.assertEqual("This security Header is missing: Referrer-Policy", finding.description) + with open("unittests/scans/humble/many_findings2.json") as testfile: + parser = HumbleParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(16, len(findings)) + finding = findings[0] + self.assertEqual(finding.unsaved_endpoints[0].host, "testestset.com") + self.assertEqual("Missing header: Clear-Site-Data", finding.title) + finding = findings[7] + self.assertEqual("Missing header: Referrer-Policy", finding.title) + self.assertEqual("This security Header is missing: Referrer-Policy", finding.description) diff --git a/unittests/tools/test_huskyci_parser.py b/unittests/tools/test_huskyci_parser.py index 55075956fa..46f07433ad 100644 --- a/unittests/tools/test_huskyci_parser.py +++ b/unittests/tools/test_huskyci_parser.py @@ -6,34 +6,31 @@ class TestHuskyCIParser(DojoTestCase): def test_parse_file_no_finding(self): - testfile = open("unittests/scans/huskyci/huskyci_report_no_finding.json") - parser = HuskyCIParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/huskyci/huskyci_report_no_finding.json") as testfile: + parser = HuskyCIParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_has_one_finding_one_tool(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/huskyci/huskyci_report_one_finding_one_tool.json" - ) - parser = HuskyCIParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1, len(findings)) + ) as testfile: + parser = HuskyCIParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) def test_parse_file_has_many_finding_one_tool(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/huskyci/huskyci_report_many_finding_one_tool.json" - ) - parser = HuskyCIParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(3, len(findings)) + ) as testfile: + parser = HuskyCIParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(3, len(findings)) def test_parse_file_has_many_finding_two_tools(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/huskyci/huskyci_report_many_finding_two_tools.json" - ) - parser = HuskyCIParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(15, len(findings)) + ) as testfile: + parser = HuskyCIParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(15, len(findings)) diff --git a/unittests/tools/test_hydra_parser.py b/unittests/tools/test_hydra_parser.py index 3e7dfca34c..d475ce2de5 100644 --- a/unittests/tools/test_hydra_parser.py +++ b/unittests/tools/test_hydra_parser.py @@ -9,113 +9,108 @@ class TestHydraParser(DojoTestCase): __test_datetime = datetime(2019, 3, 1, 14, 44, 22) def test_invalid_json_format(self): - testfile = open("unittests/scans/hydra/invalid.json") - parser = HydraParser() - with self.assertRaises(ValueError): - parser.get_findings(testfile, Test()) + with open("unittests/scans/hydra/invalid.json") as testfile: + parser = HydraParser() + with self.assertRaises(ValueError): + parser.get_findings(testfile, Test()) def test_parser_ensures_data_is_for_hydra_before_parsing(self): - testfile = open("unittests/scans/hydra/oddly_familiar_json_that_isnt_us.json") - parser = HydraParser() - with self.assertRaises(ValueError): - parser.get_findings(testfile, Test()) + with open("unittests/scans/hydra/oddly_familiar_json_that_isnt_us.json") as testfile: + parser = HydraParser() + with self.assertRaises(ValueError): + parser.get_findings(testfile, Test()) def test_hydra_parser_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/hydra/hydra_report_no_finding.json") - parser = HydraParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(0, len(findings)) + with open("unittests/scans/hydra/hydra_report_no_finding.json") as testfile: + parser = HydraParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_hydra_parser_with_one_finding_has_one_finding(self): - testfile = open("unittests/scans/hydra/hydra_report_one_finding.json") - parser = HydraParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.__assertAllEndpointsAreClean(findings) - self.assertEqual(1, len(findings)) - - finding = findings[0] - - self.__assertFindingEquals( - finding, - self.__test_datetime, - "127.0.0.1", - "9999", - "bill@example.com", - "bill" - ) + with open("unittests/scans/hydra/hydra_report_one_finding.json") as testfile: + parser = HydraParser() + findings = parser.get_findings(testfile, Test()) + self.__assertAllEndpointsAreClean(findings) + self.assertEqual(1, len(findings)) + + finding = findings[0] + + self.__assertFindingEquals( + finding, + self.__test_datetime, + "127.0.0.1", + "9999", + "bill@example.com", + "bill" + ) def test_hydra_parser_with_one_finding_and_missing_date_has_one_finding(self): - testfile = open("unittests/scans/hydra/hydra_report_one_finding_missing_date.json") - parser = HydraParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.__assertAllEndpointsAreClean(findings) - self.assertEqual(1, len(findings)) - - finding = findings[0] - - self.__assertFindingEquals( - finding, - date.today(), - "127.0.0.1", - "9999", - "bill@example.com", - "bill" - ) + with open("unittests/scans/hydra/hydra_report_one_finding_missing_date.json") as testfile: + parser = HydraParser() + findings = parser.get_findings(testfile, Test()) + self.__assertAllEndpointsAreClean(findings) + self.assertEqual(1, len(findings)) + + finding = findings[0] + + self.__assertFindingEquals( + finding, + date.today(), + "127.0.0.1", + "9999", + "bill@example.com", + "bill" + ) def test_hydra_parser_with_two_findings_with_one_incomplete_has_one_finding(self): - testfile = open("unittests/scans/hydra/hydra_report_two_findings_with_one_incomplete.json") - parser = HydraParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.__assertAllEndpointsAreClean(findings) - self.assertEqual(1, len(findings)) - - finding = findings[0] - - self.__assertFindingEquals( - finding, - self.__test_datetime, - "127.0.0.1", - "9999", - "bill@example.com", - "bill" - ) + with open("unittests/scans/hydra/hydra_report_two_findings_with_one_incomplete.json") as testfile: + parser = HydraParser() + findings = parser.get_findings(testfile, Test()) + self.__assertAllEndpointsAreClean(findings) + self.assertEqual(1, len(findings)) + + finding = findings[0] + + self.__assertFindingEquals( + finding, + self.__test_datetime, + "127.0.0.1", + "9999", + "bill@example.com", + "bill" + ) def test_hydra_parser_with_many_findings_has_many_findings(self): - testfile = open("unittests/scans/hydra/hydra_report_many_finding.json") - parser = HydraParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.__assertAllEndpointsAreClean(findings) - self.assertEqual(3, len(findings)) - - self.__assertFindingEquals( - findings[0], - self.__test_datetime, - "127.0.0.1", - "9999", - "bill@example.com", - "bill" - ) - self.__assertFindingEquals( - findings[1], - self.__test_datetime, - "192.168.0.1", - "1234", - "joe@example.com", - "joe" - ) - self.__assertFindingEquals( - findings[2], - self.__test_datetime, - "something.bad.com", - "4321", - "jimmy@bad.com", - "somesimplepassword" - ) + with open("unittests/scans/hydra/hydra_report_many_finding.json") as testfile: + parser = HydraParser() + findings = parser.get_findings(testfile, Test()) + self.__assertAllEndpointsAreClean(findings) + self.assertEqual(3, len(findings)) + + self.__assertFindingEquals( + findings[0], + self.__test_datetime, + "127.0.0.1", + "9999", + "bill@example.com", + "bill" + ) + self.__assertFindingEquals( + findings[1], + self.__test_datetime, + "192.168.0.1", + "1234", + "joe@example.com", + "joe" + ) + self.__assertFindingEquals( + findings[2], + self.__test_datetime, + "something.bad.com", + "4321", + "jimmy@bad.com", + "somesimplepassword" + ) def __assertFindingEquals( self, diff --git a/unittests/tools/test_immuniweb_parser.py b/unittests/tools/test_immuniweb_parser.py index 74b9e12d23..49e2c619de 100644 --- a/unittests/tools/test_immuniweb_parser.py +++ b/unittests/tools/test_immuniweb_parser.py @@ -6,25 +6,25 @@ class TestImmuniwebParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/immuniweb/ImmuniWeb-0-vuln.xml") - parser = ImmuniwebParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/immuniweb/ImmuniWeb-0-vuln.xml") as testfile: + parser = ImmuniwebParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_finding(self): - testfile = open("unittests/scans/immuniweb/ImmuniWeb-1-vuln.xml") - parser = ImmuniwebParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) + with open("unittests/scans/immuniweb/ImmuniWeb-1-vuln.xml") as testfile: + parser = ImmuniwebParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) def test_parse_file_with_multiple_vuln_has_multiple_findings(self): - testfile = open("unittests/scans/immuniweb/ImmuniWeb-multiple-vuln.xml") - parser = ImmuniwebParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertGreater(len(findings), 2) + with open("unittests/scans/immuniweb/ImmuniWeb-multiple-vuln.xml") as testfile: + parser = ImmuniwebParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertGreater(len(findings), 2) diff --git a/unittests/tools/test_intsights_parser.py b/unittests/tools/test_intsights_parser.py index c091a00c2e..b35e75de8c 100644 --- a/unittests/tools/test_intsights_parser.py +++ b/unittests/tools/test_intsights_parser.py @@ -6,74 +6,67 @@ class TestIntSightsParser(DojoTestCase): def test_intsights_parser_with_one_critical_vuln_has_one_findings_json( self): - testfile = open("unittests/scans/intsights/intsights_one_vul.json") - parser = IntSightsParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() + with open("unittests/scans/intsights/intsights_one_vul.json") as testfile: + parser = IntSightsParser() + findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) + self.assertEqual(1, len(findings)) - finding = list(findings)[0] + finding = list(findings)[0] - self.assertEqual( - '5c80dbf83b4a3900078b6be6', - finding.unique_id_from_tool) - self.assertEqual( - 'HTTP headers weakness in initech.com web server', - finding.title) - self.assertEqual('Critical', finding.severity) - self.assertEqual( - "https://dashboard.intsights.com/#/threat-command/alerts?search=5c80dbf83b4a3900078b6be6", - finding.references) + self.assertEqual( + '5c80dbf83b4a3900078b6be6', + finding.unique_id_from_tool) + self.assertEqual( + 'HTTP headers weakness in initech.com web server', + finding.title) + self.assertEqual('Critical', finding.severity) + self.assertEqual( + "https://dashboard.intsights.com/#/threat-command/alerts?search=5c80dbf83b4a3900078b6be6", + finding.references) def test_intsights_parser_with_one_critical_vuln_has_one_findings_csv( self): - testfile = open("unittests/scans/intsights/intsights_one_vuln.csv") - parser = IntSightsParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1, len(findings)) + with open("unittests/scans/intsights/intsights_one_vuln.csv") as testfile: + parser = IntSightsParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) - finding = list(findings)[0] + finding = list(findings)[0] - self.assertEqual( - "mn7xy83finmmth4ja363rci9", - finding.unique_id_from_tool) - self.assertEqual( - "HTTP headers weakness in company-domain.com web server", - finding.title) + self.assertEqual( + "mn7xy83finmmth4ja363rci9", + finding.unique_id_from_tool) + self.assertEqual( + "HTTP headers weakness in company-domain.com web server", + finding.title) def test_intsights_parser_with_many_vuln_has_many_findings_json(self): - testfile = open("unittests/scans/intsights/intsights_many_vul.json") - parser = IntSightsParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(3, len(findings)) + with open("unittests/scans/intsights/intsights_many_vul.json") as testfile: + parser = IntSightsParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(3, len(findings)) def test_intsights_parser_with_many_vuln_has_many_findings_csv(self): - testfile = open("unittests/scans/intsights/intsights_many_vuln.csv") - parser = IntSightsParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(9, len(findings)) + with open("unittests/scans/intsights/intsights_many_vuln.csv") as testfile: + parser = IntSightsParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(9, len(findings)) def test_intsights_parser_invalid_text_with_error_csv(self): with self.assertRaises(ValueError): - testfile = open( - "unittests/scans/intsights/intsights_invalid_file.txt") - parser = IntSightsParser() - parser.get_findings(testfile, Test()) + with open("unittests/scans/intsights/intsights_invalid_file.txt") as testfile: + parser = IntSightsParser() + parser.get_findings(testfile, Test()) def test_intsights_parser_with_no_alerts_json(self): - testfile = open("unittests/scans/intsights/intsights_zero_vuln.json") - parser = IntSightsParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(0, len(findings)) + with open("unittests/scans/intsights/intsights_zero_vuln.json") as testfile: + parser = IntSightsParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_intsights_parser_with_no_alerts_csv(self): - testfile = open("unittests/scans/intsights/intsights_zero_vuln.csv") - parser = IntSightsParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(0, len(findings)) + with open("unittests/scans/intsights/intsights_zero_vuln.csv") as testfile: + parser = IntSightsParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) diff --git a/unittests/tools/test_kics_parser.py b/unittests/tools/test_kics_parser.py index 608f92f15a..41b8efb9fe 100644 --- a/unittests/tools/test_kics_parser.py +++ b/unittests/tools/test_kics_parser.py @@ -6,192 +6,192 @@ class TestKICSParser(DojoTestCase): def test_parse_no_findings(self): - testfile = open("unittests/scans/kics/no_findings.json") - parser = KICSParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/kics/no_findings.json") as testfile: + parser = KICSParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_many_findings(self): - testfile = open("unittests/scans/kics/many_findings.json") - parser = KICSParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(18, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Secret Management: Passwords And Secrets In Infrastructure Code", finding.title) - self.assertEqual("High", finding.severity) - self.assertTrue(finding.active) - self.assertFalse(finding.verified) - self.assertEqual("Hardcoded secret key should not appear in source", finding.mitigation) - self.assertEqual("test/charts/example/terraform/main.tf", finding.file_path) - self.assertEqual(25, finding.line) - self.assertEqual("Common", finding.component_name) - description = '''Query to find passwords and secrets in infrastructure code. + with open("unittests/scans/kics/many_findings.json") as testfile: + parser = KICSParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(18, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Secret Management: Passwords And Secrets In Infrastructure Code", finding.title) + self.assertEqual("High", finding.severity) + self.assertTrue(finding.active) + self.assertFalse(finding.verified) + self.assertEqual("Hardcoded secret key should not appear in source", finding.mitigation) + self.assertEqual("test/charts/example/terraform/main.tf", finding.file_path) + self.assertEqual(25, finding.line) + self.assertEqual("Common", finding.component_name) + description = '''Query to find passwords and secrets in infrastructure code. **Platform:** Common **Category:** Secret Management **Issue type:** RedundantAttribute''' - self.assertEqual(description, finding.description) - self.assertEqual('https://kics.io/', finding.references) - self.assertEqual(1, finding.nb_occurences) - - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("Access Control: S3 Bucket Access to Any Principal", finding.title) - self.assertEqual("High", finding.severity) - self.assertTrue(finding.active) - self.assertFalse(finding.verified) - self.assertEqual("aws_s3_bucket_policy[this].policy.Principal is not equal to, nor does it contain '*'", finding.mitigation) - self.assertEqual("test/charts/example/terraform/s3.tf", finding.file_path) - self.assertEqual(36, finding.line) - self.assertEqual("Terraform", finding.component_name) - description = '''S3 Buckets must not allow Actions From All Principals, as to prevent leaking private information to the entire internet or allow unauthorized data tampering / deletion. This means the 'Effect' must not be 'Allow' when there are All Principals + self.assertEqual(description, finding.description) + self.assertEqual('https://kics.io/', finding.references) + self.assertEqual(1, finding.nb_occurences) + + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("Access Control: S3 Bucket Access to Any Principal", finding.title) + self.assertEqual("High", finding.severity) + self.assertTrue(finding.active) + self.assertFalse(finding.verified) + self.assertEqual("aws_s3_bucket_policy[this].policy.Principal is not equal to, nor does it contain '*'", finding.mitigation) + self.assertEqual("test/charts/example/terraform/s3.tf", finding.file_path) + self.assertEqual(36, finding.line) + self.assertEqual("Terraform", finding.component_name) + description = '''S3 Buckets must not allow Actions From All Principals, as to prevent leaking private information to the entire internet or allow unauthorized data tampering / deletion. This means the 'Effect' must not be 'Allow' when there are All Principals **Platform:** Terraform **Category:** Access Control **Issue type:** IncorrectValue **Actual value:** aws_s3_bucket_policy[this].policy.Principal is equal to or contains \'*\'''' - self.assertEqual(description, finding.description) - self.assertEqual('https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy', finding.references) - self.assertEqual(1, finding.nb_occurences) - - with self.subTest(i=2): - finding = findings[2] - self.assertEqual("Access Control: S3 Bucket Allows Get Action From All Principals", finding.title) - self.assertEqual("High", finding.severity) - self.assertTrue(finding.active) - self.assertFalse(finding.verified) - self.assertEqual("aws_s3_bucket_policy[this].policy.Action is not a 'Get' action", finding.mitigation) - self.assertEqual("test/charts/example/terraform/s3.tf", finding.file_path) - self.assertEqual(43, finding.line) - self.assertEqual("Terraform", finding.component_name) - self.assertIsNotNone(finding.description) - self.assertEqual(1, finding.nb_occurences) - - with self.subTest(i=3): - finding = findings[3] - self.assertEqual("Encryption: S3 Bucket Without Server-side-encryption", finding.title) - self.assertEqual("High", finding.severity) - self.assertTrue(finding.active) - self.assertFalse(finding.verified) - self.assertEqual("'aws_s3_bucket.server_side_encryption_configuration' exists", finding.mitigation) - self.assertEqual("test/charts/example/terraform/s3.tf", finding.file_path) - self.assertEqual(5, finding.line) - self.assertEqual("Terraform", finding.component_name) - self.assertIsNotNone(finding.description) - self.assertEqual(1, finding.nb_occurences) - - with self.subTest(i=4): - finding = findings[4] - self.assertEqual("Insecure Configurations: S3 Static Website Host Enabled", finding.title) - self.assertEqual("High", finding.severity) - self.assertTrue(finding.active) - self.assertFalse(finding.verified) - self.assertEqual("resource.aws_s3_bucket[this].website doesn't have static websites inside", finding.mitigation) - self.assertEqual("test/charts/example/terraform/s3.tf", finding.file_path) - self.assertEqual(19, finding.line) - self.assertEqual("Terraform", finding.component_name) - self.assertIsNotNone(finding.description) - self.assertEqual(1, finding.nb_occurences) - - with self.subTest(i=5): - finding = findings[5] - self.assertEqual("Resource Management: CPU Limits Not Set", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertTrue(finding.active) - self.assertFalse(finding.verified) - self.assertEqual("spec.template.spec.containers.name=example has CPU limits", finding.mitigation) - self.assertEqual("test/charts/example/templates/example.yaml", finding.file_path) - self.assertEqual(62, finding.line) - self.assertEqual("Kubernetes", finding.component_name) - self.assertIsNotNone(finding.description) - self.assertEqual(1, finding.nb_occurences) - - with self.subTest(i=6): - finding = findings[6] - self.assertEqual("Availability: Liveness Probe Is Not Defined", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertTrue(finding.active) - self.assertFalse(finding.verified) - self.assertEqual("metadata.name={{example}}.spec.containers.name={{example}}.livenessProbe is defined", finding.mitigation) - self.assertEqual("test/charts/example/templates/example.yaml", finding.file_path) - self.assertEqual(62, finding.line) - self.assertEqual("Kubernetes", finding.component_name) - self.assertIsNotNone(finding.description) - self.assertEqual(1, finding.nb_occurences) - - with self.subTest(i=7): - finding = findings[7] - self.assertEqual("Observability: S3 Bucket Without Versioning", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertTrue(finding.active) - self.assertFalse(finding.verified) - self.assertEqual("'versioning' is equal 'true'", finding.mitigation) - self.assertEqual("test/charts/example/terraform/s3.tf", finding.file_path) - self.assertEqual(5, finding.line) - self.assertEqual("Terraform", finding.component_name) - self.assertIsNotNone(finding.description) - self.assertEqual(1, finding.nb_occurences) - - with self.subTest(i=8): - finding = findings[8] - self.assertEqual("Insecure Configurations: Seccomp Profile Is Not Configured", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertTrue(finding.active) - self.assertFalse(finding.verified) - self.assertEqual("'spec.template.metadata.annotations' is set", finding.mitigation) - self.assertEqual("test/charts/example/templates/example.yaml", finding.file_path) - self.assertEqual(19, finding.line) - self.assertEqual("Kubernetes", finding.component_name) - self.assertIsNotNone(finding.description) - self.assertEqual(1, finding.nb_occurences) - - with self.subTest(i=9): - finding = findings[9] - self.assertEqual("Insecure Defaults: Service Account Token Automount Not Disabled", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertTrue(finding.active) - self.assertFalse(finding.verified) - self.assertEqual("'spec.template.spec.automountServiceAccountToken' is false", finding.mitigation) - self.assertEqual("test/charts/example/templates/example.yaml", finding.file_path) - self.assertEqual(22, finding.line) - self.assertEqual("Kubernetes", finding.component_name) - self.assertIsNotNone(finding.description) - self.assertEqual(1, finding.nb_occurences) - - with self.subTest(i=10): - finding = findings[10] - self.assertEqual("Best Practices: No Drop Capabilities for Containers", finding.title) - self.assertEqual("Low", finding.severity) - self.assertTrue(finding.active) - self.assertFalse(finding.verified) - self.assertEqual("metadata.name={{example}}.spec.containers.name=example.securityContext is set", finding.mitigation) - self.assertEqual("test/charts/example/templates/example.yaml", finding.file_path) - self.assertEqual(62, finding.line) - self.assertEqual("Kubernetes", finding.component_name) - self.assertIsNotNone(finding.description) - self.assertEqual(1, finding.nb_occurences) - - with self.subTest(i=11): - finding = findings[11] - self.assertEqual("Access Control: Permissive Access to Create Pods", finding.title) - self.assertEqual("Low", finding.severity) - self.assertTrue(finding.active) - self.assertFalse(finding.verified) - self.assertEqual("metadata.name=example.rules.verbs should not contain a wildcard value when metadata.name=example.rules.resources contains a wildcard value", finding.mitigation) - self.assertEqual("test/charts/example/templates/rbac.yaml", finding.file_path) - self.assertEqual(20, finding.line) - self.assertEqual("Kubernetes", finding.component_name) - self.assertIsNotNone(finding.description) - self.assertEqual(1, finding.nb_occurences) - - with self.subTest(i=12): - finding = findings[12] - self.assertEqual("Insecure Configurations: Pod or Container Without Security Context", finding.title) - self.assertEqual("Low", finding.severity) - self.assertTrue(finding.active) - self.assertFalse(finding.verified) - self.assertEqual("spec.template.spec.containers.name=example has a security context", finding.mitigation) - self.assertEqual("test/charts/example/templates/example.yaml", finding.file_path) - self.assertEqual(62, finding.line) - self.assertEqual("Kubernetes", finding.component_name) - self.assertIsNotNone(finding.description) - self.assertEqual(1, finding.nb_occurences) + self.assertEqual(description, finding.description) + self.assertEqual('https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy', finding.references) + self.assertEqual(1, finding.nb_occurences) + + with self.subTest(i=2): + finding = findings[2] + self.assertEqual("Access Control: S3 Bucket Allows Get Action From All Principals", finding.title) + self.assertEqual("High", finding.severity) + self.assertTrue(finding.active) + self.assertFalse(finding.verified) + self.assertEqual("aws_s3_bucket_policy[this].policy.Action is not a 'Get' action", finding.mitigation) + self.assertEqual("test/charts/example/terraform/s3.tf", finding.file_path) + self.assertEqual(43, finding.line) + self.assertEqual("Terraform", finding.component_name) + self.assertIsNotNone(finding.description) + self.assertEqual(1, finding.nb_occurences) + + with self.subTest(i=3): + finding = findings[3] + self.assertEqual("Encryption: S3 Bucket Without Server-side-encryption", finding.title) + self.assertEqual("High", finding.severity) + self.assertTrue(finding.active) + self.assertFalse(finding.verified) + self.assertEqual("'aws_s3_bucket.server_side_encryption_configuration' exists", finding.mitigation) + self.assertEqual("test/charts/example/terraform/s3.tf", finding.file_path) + self.assertEqual(5, finding.line) + self.assertEqual("Terraform", finding.component_name) + self.assertIsNotNone(finding.description) + self.assertEqual(1, finding.nb_occurences) + + with self.subTest(i=4): + finding = findings[4] + self.assertEqual("Insecure Configurations: S3 Static Website Host Enabled", finding.title) + self.assertEqual("High", finding.severity) + self.assertTrue(finding.active) + self.assertFalse(finding.verified) + self.assertEqual("resource.aws_s3_bucket[this].website doesn't have static websites inside", finding.mitigation) + self.assertEqual("test/charts/example/terraform/s3.tf", finding.file_path) + self.assertEqual(19, finding.line) + self.assertEqual("Terraform", finding.component_name) + self.assertIsNotNone(finding.description) + self.assertEqual(1, finding.nb_occurences) + + with self.subTest(i=5): + finding = findings[5] + self.assertEqual("Resource Management: CPU Limits Not Set", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertTrue(finding.active) + self.assertFalse(finding.verified) + self.assertEqual("spec.template.spec.containers.name=example has CPU limits", finding.mitigation) + self.assertEqual("test/charts/example/templates/example.yaml", finding.file_path) + self.assertEqual(62, finding.line) + self.assertEqual("Kubernetes", finding.component_name) + self.assertIsNotNone(finding.description) + self.assertEqual(1, finding.nb_occurences) + + with self.subTest(i=6): + finding = findings[6] + self.assertEqual("Availability: Liveness Probe Is Not Defined", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertTrue(finding.active) + self.assertFalse(finding.verified) + self.assertEqual("metadata.name={{example}}.spec.containers.name={{example}}.livenessProbe is defined", finding.mitigation) + self.assertEqual("test/charts/example/templates/example.yaml", finding.file_path) + self.assertEqual(62, finding.line) + self.assertEqual("Kubernetes", finding.component_name) + self.assertIsNotNone(finding.description) + self.assertEqual(1, finding.nb_occurences) + + with self.subTest(i=7): + finding = findings[7] + self.assertEqual("Observability: S3 Bucket Without Versioning", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertTrue(finding.active) + self.assertFalse(finding.verified) + self.assertEqual("'versioning' is equal 'true'", finding.mitigation) + self.assertEqual("test/charts/example/terraform/s3.tf", finding.file_path) + self.assertEqual(5, finding.line) + self.assertEqual("Terraform", finding.component_name) + self.assertIsNotNone(finding.description) + self.assertEqual(1, finding.nb_occurences) + + with self.subTest(i=8): + finding = findings[8] + self.assertEqual("Insecure Configurations: Seccomp Profile Is Not Configured", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertTrue(finding.active) + self.assertFalse(finding.verified) + self.assertEqual("'spec.template.metadata.annotations' is set", finding.mitigation) + self.assertEqual("test/charts/example/templates/example.yaml", finding.file_path) + self.assertEqual(19, finding.line) + self.assertEqual("Kubernetes", finding.component_name) + self.assertIsNotNone(finding.description) + self.assertEqual(1, finding.nb_occurences) + + with self.subTest(i=9): + finding = findings[9] + self.assertEqual("Insecure Defaults: Service Account Token Automount Not Disabled", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertTrue(finding.active) + self.assertFalse(finding.verified) + self.assertEqual("'spec.template.spec.automountServiceAccountToken' is false", finding.mitigation) + self.assertEqual("test/charts/example/templates/example.yaml", finding.file_path) + self.assertEqual(22, finding.line) + self.assertEqual("Kubernetes", finding.component_name) + self.assertIsNotNone(finding.description) + self.assertEqual(1, finding.nb_occurences) + + with self.subTest(i=10): + finding = findings[10] + self.assertEqual("Best Practices: No Drop Capabilities for Containers", finding.title) + self.assertEqual("Low", finding.severity) + self.assertTrue(finding.active) + self.assertFalse(finding.verified) + self.assertEqual("metadata.name={{example}}.spec.containers.name=example.securityContext is set", finding.mitigation) + self.assertEqual("test/charts/example/templates/example.yaml", finding.file_path) + self.assertEqual(62, finding.line) + self.assertEqual("Kubernetes", finding.component_name) + self.assertIsNotNone(finding.description) + self.assertEqual(1, finding.nb_occurences) + + with self.subTest(i=11): + finding = findings[11] + self.assertEqual("Access Control: Permissive Access to Create Pods", finding.title) + self.assertEqual("Low", finding.severity) + self.assertTrue(finding.active) + self.assertFalse(finding.verified) + self.assertEqual("metadata.name=example.rules.verbs should not contain a wildcard value when metadata.name=example.rules.resources contains a wildcard value", finding.mitigation) + self.assertEqual("test/charts/example/templates/rbac.yaml", finding.file_path) + self.assertEqual(20, finding.line) + self.assertEqual("Kubernetes", finding.component_name) + self.assertIsNotNone(finding.description) + self.assertEqual(1, finding.nb_occurences) + + with self.subTest(i=12): + finding = findings[12] + self.assertEqual("Insecure Configurations: Pod or Container Without Security Context", finding.title) + self.assertEqual("Low", finding.severity) + self.assertTrue(finding.active) + self.assertFalse(finding.verified) + self.assertEqual("spec.template.spec.containers.name=example has a security context", finding.mitigation) + self.assertEqual("test/charts/example/templates/example.yaml", finding.file_path) + self.assertEqual(62, finding.line) + self.assertEqual("Kubernetes", finding.component_name) + self.assertIsNotNone(finding.description) + self.assertEqual(1, finding.nb_occurences) diff --git a/unittests/tools/test_kiuwan_parser.py b/unittests/tools/test_kiuwan_parser.py index 2f7a25e033..ec10baf2c0 100644 --- a/unittests/tools/test_kiuwan_parser.py +++ b/unittests/tools/test_kiuwan_parser.py @@ -6,31 +6,31 @@ class TestKiuwanParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/kiuwan/kiuwan_no_vuln.csv") - parser = KiuwanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/kiuwan/kiuwan_no_vuln.csv") as testfile: + parser = KiuwanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_two_vuln_has_two_findings(self): - testfile = open("unittests/scans/kiuwan/kiuwan_two_vuln.csv") - parser = KiuwanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(2, len(findings)) + with open("unittests/scans/kiuwan/kiuwan_two_vuln.csv") as testfile: + parser = KiuwanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(2, len(findings)) def test_parse_file_with_multiple_vuln_has_multiple_finding(self): - testfile = open("unittests/scans/kiuwan/kiuwan_many_vuln.csv") - parser = KiuwanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(131, len(findings)) + with open("unittests/scans/kiuwan/kiuwan_many_vuln.csv") as testfile: + parser = KiuwanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(131, len(findings)) def test_parse_file_with_defects(self): - testfile = open("unittests/scans/kiuwan/kiuwan_defects.csv") - parser = KiuwanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) + with open("unittests/scans/kiuwan/kiuwan_defects.csv") as testfile: + parser = KiuwanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) def test_parse_file_issue_9308(self): - testfile = open("unittests/scans/kiuwan/issue_9308.csv") - parser = KiuwanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(2, len(findings)) + with open("unittests/scans/kiuwan/issue_9308.csv") as testfile: + parser = KiuwanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(2, len(findings)) diff --git a/unittests/tools/test_kubebench_parser.py b/unittests/tools/test_kubebench_parser.py index 0494e92ff3..d5359e59bf 100644 --- a/unittests/tools/test_kubebench_parser.py +++ b/unittests/tools/test_kubebench_parser.py @@ -6,55 +6,55 @@ class TestKubeBenchParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/kubebench/kube-bench-report-zero-vuln.json" - ) - parser = KubeBenchParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + ) as testfile: + parser = KubeBenchParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_finding(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/kubebench/kube-bench-report-one-vuln.json" - ) - parser = KubeBenchParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) + ) as testfile: + parser = KubeBenchParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) def test_parse_file_with_multiple_vuln_has_multiple_findings(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/kubebench/kube-bench-report-many-vuln.json" - ) - parser = KubeBenchParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(len(findings), 4) + ) as testfile: + parser = KubeBenchParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(len(findings), 4) def test_parse_file_with_controls_tag(self): # The testfile has been derived from https://github.com/kubernetes-sigs/wg-policy-prototypes/blob/master/policy-report/kube-bench-adapter/samples/kube-bench-output.json - testfile = open( + with open( get_unit_tests_path() + "/scans/kubebench/kube-bench-controls.json" - ) - parser = KubeBenchParser() - findings = parser.get_findings(testfile, Test()) - - medium_severities = 0 - info_severities = 0 - for finding in findings: - if finding.severity == 'Medium': - medium_severities += 1 - if finding.severity == 'Info': - info_severities += 1 - - self.assertEqual(36, medium_severities) - self.assertEqual(20, info_severities) - - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("1.1.1 - Ensure that the API server pod specification file permissions are set to 644 or more restrictive (Automated)", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertIsNotNone(finding.description) - self.assertIsNotNone(finding.mitigation) - self.assertTrue(finding.static_finding) - self.assertFalse(finding.dynamic_finding) - self.assertEqual("1.1.1", finding.vuln_id_from_tool) + ) as testfile: + parser = KubeBenchParser() + findings = parser.get_findings(testfile, Test()) + + medium_severities = 0 + info_severities = 0 + for finding in findings: + if finding.severity == 'Medium': + medium_severities += 1 + if finding.severity == 'Info': + info_severities += 1 + + self.assertEqual(36, medium_severities) + self.assertEqual(20, info_severities) + + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("1.1.1 - Ensure that the API server pod specification file permissions are set to 644 or more restrictive (Automated)", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertIsNotNone(finding.description) + self.assertIsNotNone(finding.mitigation) + self.assertTrue(finding.static_finding) + self.assertFalse(finding.dynamic_finding) + self.assertEqual("1.1.1", finding.vuln_id_from_tool) diff --git a/unittests/tools/test_kubehunter_parser.py b/unittests/tools/test_kubehunter_parser.py index 6c0683364a..e1cc133af0 100644 --- a/unittests/tools/test_kubehunter_parser.py +++ b/unittests/tools/test_kubehunter_parser.py @@ -6,50 +6,45 @@ class TestKubeHunterParser(TestCase): def test_kubehunter_parser_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/kubehunter/kubehunter_zero_vul.json") - parser = KubeHunterParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(0, len(findings)) + with open("unittests/scans/kubehunter/kubehunter_zero_vul.json") as testfile: + parser = KubeHunterParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_kubehunter_parser_with_one_criticle_vuln_has_one_findings(self): - testfile = open("unittests/scans/kubehunter/kubehunter_one_vul.json") - parser = KubeHunterParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - self.assertEqual("KHV044", findings[0].vuln_id_from_tool) - self.assertEqual("Privileged Container", findings[0].title) - self.assertEqual(True, finding.active) - - self.assertEqual(False, finding.duplicate) - self.assertEqual(finding.severity, 'High') + with open("unittests/scans/kubehunter/kubehunter_one_vul.json") as testfile: + parser = KubeHunterParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + self.assertEqual("KHV044", findings[0].vuln_id_from_tool) + self.assertEqual("Privileged Container", findings[0].title) + self.assertEqual(True, finding.active) + + self.assertEqual(False, finding.duplicate) + self.assertEqual(finding.severity, 'High') def test_kubehunter_parser_with_many_vuln_has_many_findings(self): - testfile = open("unittests/scans/kubehunter/kubehunter_many_vul.json") - parser = KubeHunterParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() + with open("unittests/scans/kubehunter/kubehunter_many_vul.json") as testfile: + parser = KubeHunterParser() + findings = parser.get_findings(testfile, Test()) - self.assertEqual(8, len(findings)) + self.assertEqual(8, len(findings)) def test_kubehunter_parser_empty_with_error(self): with self.assertRaises(ValueError) as context: - testfile = open("unittests/scans/kubehunter/empty.json") - parser = KubeHunterParser() - parser.get_findings(testfile, Test()) - testfile.close() + with open("unittests/scans/kubehunter/empty.json") as testfile: + parser = KubeHunterParser() + parser.get_findings(testfile, Test()) self.assertEqual( "Expecting value: line 1 column 1 (char 0)", str(context.exception) ) def test_kubehunter_parser_dupe(self): - testfile = open("unittests/scans/kubehunter/dupe.json") - parser = KubeHunterParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1, len(findings)) + with open("unittests/scans/kubehunter/dupe.json") as testfile: + parser = KubeHunterParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) diff --git a/unittests/tools/test_kubescape_parser.py b/unittests/tools/test_kubescape_parser.py index 74f03661c3..c134f0c7ca 100644 --- a/unittests/tools/test_kubescape_parser.py +++ b/unittests/tools/test_kubescape_parser.py @@ -5,28 +5,19 @@ class TestOrtParser(DojoTestCase): def test_parse_file_has_many_findings(self): - testfile = open( - get_unit_tests_path() + "/scans/kubescape/many_findings.json" - ) - parser = KubescapeParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(710, len(findings)) + with open(get_unit_tests_path() + "/scans/kubescape/many_findings.json") as testfile: + parser = KubescapeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(710, len(findings)) def test_parse_file_has_many_results(self): - testfile = open( - get_unit_tests_path() + "/scans/kubescape/results.json" - ) - parser = KubescapeParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(20, len(findings)) + with open(get_unit_tests_path() + "/scans/kubescape/results.json") as testfile: + parser = KubescapeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(20, len(findings)) def test_parse_file_with_a_failure(self): - testfile = open( - get_unit_tests_path() + "/scans/kubescape/with_a_failure.json" - ) - parser = KubescapeParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(18, len(findings)) + with open(get_unit_tests_path() + "/scans/kubescape/with_a_failure.json") as testfile: + parser = KubescapeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(18, len(findings)) diff --git a/unittests/tools/test_mend_parser.py b/unittests/tools/test_mend_parser.py index 9a4e84d94d..d7a693aa3a 100644 --- a/unittests/tools/test_mend_parser.py +++ b/unittests/tools/test_mend_parser.py @@ -6,32 +6,32 @@ class TestMendParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/mend/okhttp_no_vuln.json") - parser = MendParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/mend/okhttp_no_vuln.json") as testfile: + parser = MendParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_findings(self): - testfile = open("unittests/scans/mend/okhttp_one_vuln.json") - parser = MendParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - finding = list(findings)[0] - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2019-9658", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", finding.cvssv3) - self.assertEqual(5.3, finding.cvssv3_score) + with open("unittests/scans/mend/okhttp_one_vuln.json") as testfile: + parser = MendParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + finding = list(findings)[0] + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2019-9658", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", finding.cvssv3) + self.assertEqual(5.3, finding.cvssv3_score) def test_parse_file_with_multiple_vuln_has_multiple_finding(self): - testfile = open("unittests/scans/mend/okhttp_many_vuln.json") - parser = MendParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(6, len(findings)) + with open("unittests/scans/mend/okhttp_many_vuln.json") as testfile: + parser = MendParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(6, len(findings)) def test_parse_file_with_multiple_vuln_cli_output(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/mend/cli_generated_many_vulns.json" - ) - parser = MendParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(20, len(findings)) + ) as testfile: + parser = MendParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(20, len(findings)) diff --git a/unittests/tools/test_meterian_parser.py b/unittests/tools/test_meterian_parser.py index f5e2e88136..b2f74271b1 100644 --- a/unittests/tools/test_meterian_parser.py +++ b/unittests/tools/test_meterian_parser.py @@ -7,88 +7,76 @@ class TestMeterianParser(DojoTestCase): def test_meterianParser_invalid_security_report_raise_ValueError_exception(self): with self.assertRaises(ValueError): - testfile = open("unittests/scans/meterian/report_invalid.json") - parser = MeterianParser() - parser.get_findings(testfile, Test()) + with open("unittests/scans/meterian/report_invalid.json") as testfile: + parser = MeterianParser() + parser.get_findings(testfile, Test()) def test_meterianParser_report_has_no_finding(self): - testfile = open("unittests/scans/meterian/report_no_vulns.json") - - parser = MeterianParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() + with open("unittests/scans/meterian/report_no_vulns.json") as testfile: + parser = MeterianParser() + findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + self.assertEqual(0, len(findings)) def test_meterianParser_report_has_one_findings(self): - testfile = open("unittests/scans/meterian/report_one_vuln.json") - - parser = MeterianParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() + with open("unittests/scans/meterian/report_one_vuln.json") as testfile: + parser = MeterianParser() + findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) + self.assertEqual(1, len(findings)) def test_meterianParser_report_has_many_findings(self): - testfile = open("unittests/scans/meterian/report_many_vulns.json") - - parser = MeterianParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() + with open("unittests/scans/meterian/report_many_vulns.json") as testfile: + parser = MeterianParser() + findings = parser.get_findings(testfile, Test()) - self.assertEqual(20, len(findings)) + self.assertEqual(20, len(findings)) def test_meterianParser_finding_has_fields(self): - testfile = open("unittests/scans/meterian/report_one_vuln.json") - - parser = MeterianParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - - finding = findings[0] - self.assertEqual(1, len(findings)) - self.assertEqual("date-and-time:0.6.3", finding.title) - self.assertEqual("2021-06-02", finding.date) - self.assertEqual("High", finding.severity) - self.assertEqual("Issue severity of: **High** from a base " - + "CVSS score of: **7.5**", finding.severity_justification) - self.assertEqual("date-and-time is an npm package for manipulating " - + "date and time. In date-and-time before version 0.14.2, there a regular " - + "expression involved in parsing which can be exploited to to cause a denial " - + "of service. This is fixed in version 0.14.2.", finding.description) - self.assertEqual("7be36211-b569-30c0-8851-26b4bb8740ca", finding.unique_id_from_tool) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2020-26289", finding.unsaved_vulnerability_ids[0]) - self.assertEqual(400, finding.cwe) - self.assertTrue(finding.mitigation.startswith("## Remediation")) - self.assertIn("Upgrade date-and-time to version 0.14.2 or higher.", finding.mitigation) - self.assertIn("https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-26289", finding.references, "found " + finding.references) - self.assertIn("https://nvd.nist.gov/vuln/detail/CVE-2020-26289", finding.references, "found " + finding.references) - self.assertIn("https://www.npmjs.com/package/date-and-time", finding.references, "found " + finding.references) - self.assertIn("https://github.com/knowledgecode/date-and-time/security/advisories/GHSA-r92x-f52r-x54g", finding.references, "found " + finding.references) - self.assertIn("https://github.com/knowledgecode/date-and-time/commit/9e4b501eacddccc8b1f559fb414f48472ee17c2a", finding.references, "found " + finding.references) - self.assertIn("Manifest file", finding.file_path) - self.assertEqual(["nodejs"], finding.tags) + with open("unittests/scans/meterian/report_one_vuln.json") as testfile: + parser = MeterianParser() + findings = parser.get_findings(testfile, Test()) + + finding = findings[0] + self.assertEqual(1, len(findings)) + self.assertEqual("date-and-time:0.6.3", finding.title) + self.assertEqual("2021-06-02", finding.date) + self.assertEqual("High", finding.severity) + self.assertEqual("Issue severity of: **High** from a base " + + "CVSS score of: **7.5**", finding.severity_justification) + self.assertEqual("date-and-time is an npm package for manipulating " + + "date and time. In date-and-time before version 0.14.2, there a regular " + + "expression involved in parsing which can be exploited to to cause a denial " + + "of service. This is fixed in version 0.14.2.", finding.description) + self.assertEqual("7be36211-b569-30c0-8851-26b4bb8740ca", finding.unique_id_from_tool) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2020-26289", finding.unsaved_vulnerability_ids[0]) + self.assertEqual(400, finding.cwe) + self.assertTrue(finding.mitigation.startswith("## Remediation")) + self.assertIn("Upgrade date-and-time to version 0.14.2 or higher.", finding.mitigation) + self.assertIn("https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-26289", finding.references, "found " + finding.references) + self.assertIn("https://nvd.nist.gov/vuln/detail/CVE-2020-26289", finding.references, "found " + finding.references) + self.assertIn("https://www.npmjs.com/package/date-and-time", finding.references, "found " + finding.references) + self.assertIn("https://github.com/knowledgecode/date-and-time/security/advisories/GHSA-r92x-f52r-x54g", finding.references, "found " + finding.references) + self.assertIn("https://github.com/knowledgecode/date-and-time/commit/9e4b501eacddccc8b1f559fb414f48472ee17c2a", finding.references, "found " + finding.references) + self.assertIn("Manifest file", finding.file_path) + self.assertEqual(["nodejs"], finding.tags) def test_meterianParser_finding_has_no_remediation(self): - testfile = open("unittests/scans/meterian/report_one_vuln_no_remediation.json") - - parser = MeterianParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() + with open("unittests/scans/meterian/report_one_vuln_no_remediation.json") as testfile: + parser = MeterianParser() + findings = parser.get_findings(testfile, Test()) - finding = findings[0] - self.assertTrue(finding.mitigation.startswith("We were not able to provide a safe version for this library.")) - self.assertIn("You should consider replacing this component as it could be an " - + "issue for the safety of your application.", finding.mitigation) + finding = findings[0] + self.assertTrue(finding.mitigation.startswith("We were not able to provide a safe version for this library.")) + self.assertIn("You should consider replacing this component as it could be an " + + "issue for the safety of your application.", finding.mitigation) def test_meterianParser_dual_language_report_has_two_findins(self): - testfile = open("unittests/scans/meterian/report_multi_language.json") - - parser = MeterianParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() + with open("unittests/scans/meterian/report_multi_language.json") as testfile: + parser = MeterianParser() + findings = parser.get_findings(testfile, Test()) - self.assertEqual(2, len(findings)) - self.assertIn("nodejs", findings[0].tags) - self.assertIn("ruby", findings[1].tags) + self.assertEqual(2, len(findings)) + self.assertIn("nodejs", findings[0].tags) + self.assertIn("ruby", findings[1].tags) diff --git a/unittests/tools/test_microfocus_webinspect_parser.py b/unittests/tools/test_microfocus_webinspect_parser.py index 40609f8678..b7c2438c27 100644 --- a/unittests/tools/test_microfocus_webinspect_parser.py +++ b/unittests/tools/test_microfocus_webinspect_parser.py @@ -9,58 +9,58 @@ def test_parse_file_with_no_vuln_has_no_findings(self): test = Test() test.engagement = Engagement() test.engagement.product = Product() - testfile = open( + with open( get_unit_tests_path() + "/scans/microfocus_webinspect/Webinspect_no_vuln.xml" - ) - parser = MicrofocusWebinspectParser() - findings = parser.get_findings(testfile, test) - self.assertEqual(0, len(findings)) + ) as testfile: + parser = MicrofocusWebinspectParser() + findings = parser.get_findings(testfile, test) + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_findings(self): test = Test() test.engagement = Engagement() test.engagement.product = Product() - testfile = open( + with open( get_unit_tests_path() + "/scans/microfocus_webinspect/Webinspect_one_vuln.xml" - ) - parser = MicrofocusWebinspectParser() - findings = parser.get_findings(testfile, test) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - item = findings[0] - self.assertEqual(200, item.cwe) - self.assertEqual(1, len(item.unsaved_endpoints)) - endpoint = item.unsaved_endpoints[0] - self.assertEqual("www.microfocus.com", endpoint.host) - self.assertEqual(443, endpoint.port) - self.assertIsNone(endpoint.path) # path begins with '/' but Endpoint store "root-less" path + ) as testfile: + parser = MicrofocusWebinspectParser() + findings = parser.get_findings(testfile, test) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + item = findings[0] + self.assertEqual(200, item.cwe) + self.assertEqual(1, len(item.unsaved_endpoints)) + endpoint = item.unsaved_endpoints[0] + self.assertEqual("www.microfocus.com", endpoint.host) + self.assertEqual(443, endpoint.port) + self.assertIsNone(endpoint.path) # path begins with '/' but Endpoint store "root-less" path def test_parse_file_with_multiple_vuln_has_multiple_finding(self): test = Test() test.engagement = Engagement() test.engagement.product = Product() - testfile = open( + with open( get_unit_tests_path() + "/scans/microfocus_webinspect/Webinspect_many_vuln.xml" - ) - parser = MicrofocusWebinspectParser() - findings = parser.get_findings(testfile, test) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(8, len(findings)) - item = findings[1] - self.assertEqual(525, item.cwe) - self.assertIsNotNone(item.references) - self.assertEqual( - "1cfe38ee-89f7-4110-ad7c-8fca476b2f04", item.unique_id_from_tool - ) - self.assertEqual(1, len(item.unsaved_endpoints)) - endpoint = item.unsaved_endpoints[0] - self.assertEqual("php.vulnweb.com", endpoint.host) - self.assertEqual(80, endpoint.port) - self.assertIsNone(endpoint.path) # path begins with '/' but Endpoint store "root-less" path + )as testfile: + parser = MicrofocusWebinspectParser() + findings = parser.get_findings(testfile, test) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(8, len(findings)) + item = findings[1] + self.assertEqual(525, item.cwe) + self.assertIsNotNone(item.references) + self.assertEqual( + "1cfe38ee-89f7-4110-ad7c-8fca476b2f04", item.unique_id_from_tool + ) + self.assertEqual(1, len(item.unsaved_endpoints)) + endpoint = item.unsaved_endpoints[0] + self.assertEqual("php.vulnweb.com", endpoint.host) + self.assertEqual(80, endpoint.port) + self.assertIsNone(endpoint.path) # path begins with '/' but Endpoint store "root-less" path def test_convert_severity(self): with self.subTest("convert info", val="0"): @@ -73,56 +73,56 @@ def test_convert_severity(self): ) def test_parse_file_version_18_20(self): - testfile = open("unittests/scans/microfocus_webinspect/Webinspect_V18_20.xml") - parser = MicrofocusWebinspectParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(4, len(findings)) - item = findings[0] - self.assertEqual('Cache Management: Headers', item.title) - self.assertEqual('Info', item.severity) - self.assertEqual(200, item.cwe) - self.assertEqual(2, item.nb_occurences) - self.assertEqual(2, len(item.unsaved_endpoints)) - endpoint = item.unsaved_endpoints[0] - self.assertEqual("www.microfocus.com", endpoint.host) - self.assertEqual(443, endpoint.port) - self.assertIsNone(endpoint.path) # path begins with '/' but Endpoint store "root-less" path - endpoint = item.unsaved_endpoints[1] - self.assertEqual("www.microfocus.com", endpoint.host) - self.assertEqual(443, endpoint.port) - self.assertEqual("en-us/home", endpoint.path) # path begins with '/' but Endpoint store "root-less" path - item = findings[1] - self.assertEqual(525, item.cwe) - self.assertEqual(1, item.nb_occurences) - self.assertEqual(1, len(item.unsaved_endpoints)) - endpoint = item.unsaved_endpoints[0] - self.assertEqual("www.microfocus.com", endpoint.host) - self.assertEqual(443, endpoint.port) - item = findings[2] - self.assertEqual(200, item.cwe) - self.assertEqual(1, item.nb_occurences) - self.assertEqual(1, len(item.unsaved_endpoints)) - endpoint = item.unsaved_endpoints[0] - self.assertEqual("www.microfocus.com", endpoint.host) - self.assertEqual(443, endpoint.port) - item = findings[3] - self.assertEqual(613, item.cwe) - self.assertEqual(1, item.nb_occurences) - self.assertEqual(1, len(item.unsaved_endpoints)) - endpoint = item.unsaved_endpoints[0] - self.assertEqual("www.microfocus.com", endpoint.host) - self.assertEqual(443, endpoint.port) + with open("unittests/scans/microfocus_webinspect/Webinspect_V18_20.xml") as testfile: + parser = MicrofocusWebinspectParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(4, len(findings)) + item = findings[0] + self.assertEqual('Cache Management: Headers', item.title) + self.assertEqual('Info', item.severity) + self.assertEqual(200, item.cwe) + self.assertEqual(2, item.nb_occurences) + self.assertEqual(2, len(item.unsaved_endpoints)) + endpoint = item.unsaved_endpoints[0] + self.assertEqual("www.microfocus.com", endpoint.host) + self.assertEqual(443, endpoint.port) + self.assertIsNone(endpoint.path) # path begins with '/' but Endpoint store "root-less" path + endpoint = item.unsaved_endpoints[1] + self.assertEqual("www.microfocus.com", endpoint.host) + self.assertEqual(443, endpoint.port) + self.assertEqual("en-us/home", endpoint.path) # path begins with '/' but Endpoint store "root-less" path + item = findings[1] + self.assertEqual(525, item.cwe) + self.assertEqual(1, item.nb_occurences) + self.assertEqual(1, len(item.unsaved_endpoints)) + endpoint = item.unsaved_endpoints[0] + self.assertEqual("www.microfocus.com", endpoint.host) + self.assertEqual(443, endpoint.port) + item = findings[2] + self.assertEqual(200, item.cwe) + self.assertEqual(1, item.nb_occurences) + self.assertEqual(1, len(item.unsaved_endpoints)) + endpoint = item.unsaved_endpoints[0] + self.assertEqual("www.microfocus.com", endpoint.host) + self.assertEqual(443, endpoint.port) + item = findings[3] + self.assertEqual(613, item.cwe) + self.assertEqual(1, item.nb_occurences) + self.assertEqual(1, len(item.unsaved_endpoints)) + endpoint = item.unsaved_endpoints[0] + self.assertEqual("www.microfocus.com", endpoint.host) + self.assertEqual(443, endpoint.port) def test_parse_file_issue7690(self): test = Test() test.engagement = Engagement() test.engagement.product = Product() - testfile = open( + with open( get_unit_tests_path() + "/scans/microfocus_webinspect/issue_7690.xml" - ) - parser = MicrofocusWebinspectParser() - findings = parser.get_findings(testfile, test) - self.assertEqual(30, len(findings)) + ) as testfile: + parser = MicrofocusWebinspectParser() + findings = parser.get_findings(testfile, test) + self.assertEqual(30, len(findings)) diff --git a/unittests/tools/test_mobsfscan_parser.py b/unittests/tools/test_mobsfscan_parser.py index 76e805852a..a65f3a61a6 100644 --- a/unittests/tools/test_mobsfscan_parser.py +++ b/unittests/tools/test_mobsfscan_parser.py @@ -6,152 +6,149 @@ class TestMobsfscanParser(DojoTestCase): def test_parse_no_findings(self): - testfile = open("unittests/scans/mobsfscan/no_findings.json") - parser = MobsfscanParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(0, len(findings)) + with open("unittests/scans/mobsfscan/no_findings.json") as testfile: + parser = MobsfscanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_many_findings(self): - testfile = open("unittests/scans/mobsfscan/many_findings.json") - parser = MobsfscanParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(7, len(findings)) - - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("android_certificate_transparency", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(295, finding.cwe) - self.assertIsNotNone(finding.references) - - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("android_kotlin_hardcoded", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(798, finding.cwe) - self.assertIsNotNone(finding.references) - self.assertEqual("app/src/main/java/com/routes/domain/analytics/event/Signatures.kt", finding.file_path) - self.assertEqual(10, finding.line) - - with self.subTest(i=2): - finding = findings[2] - self.assertEqual("android_prevent_screenshot", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(200, finding.cwe) - self.assertIsNotNone(finding.references) - - with self.subTest(i=3): - finding = findings[3] - self.assertEqual("android_root_detection", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(919, finding.cwe) - self.assertIsNotNone(finding.references) - - with self.subTest(i=4): - finding = findings[4] - self.assertEqual("android_safetynet", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(353, finding.cwe) - self.assertIsNotNone(finding.references) - - with self.subTest(i=5): - finding = findings[5] - self.assertEqual("android_ssl_pinning", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(295, finding.cwe) - self.assertIsNotNone(finding.references) - - with self.subTest(i=6): - finding = findings[6] - self.assertEqual("android_tapjacking", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(200, finding.cwe) - self.assertIsNotNone(finding.references) + with open("unittests/scans/mobsfscan/many_findings.json") as testfile: + parser = MobsfscanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(7, len(findings)) + + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("android_certificate_transparency", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(295, finding.cwe) + self.assertIsNotNone(finding.references) + + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("android_kotlin_hardcoded", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(798, finding.cwe) + self.assertIsNotNone(finding.references) + self.assertEqual("app/src/main/java/com/routes/domain/analytics/event/Signatures.kt", finding.file_path) + self.assertEqual(10, finding.line) + + with self.subTest(i=2): + finding = findings[2] + self.assertEqual("android_prevent_screenshot", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(200, finding.cwe) + self.assertIsNotNone(finding.references) + + with self.subTest(i=3): + finding = findings[3] + self.assertEqual("android_root_detection", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(919, finding.cwe) + self.assertIsNotNone(finding.references) + + with self.subTest(i=4): + finding = findings[4] + self.assertEqual("android_safetynet", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(353, finding.cwe) + self.assertIsNotNone(finding.references) + + with self.subTest(i=5): + finding = findings[5] + self.assertEqual("android_ssl_pinning", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(295, finding.cwe) + self.assertIsNotNone(finding.references) + + with self.subTest(i=6): + finding = findings[6] + self.assertEqual("android_tapjacking", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(200, finding.cwe) + self.assertIsNotNone(finding.references) def test_parse_many_findings_cwe_lower(self): - testfile = open("unittests/scans/mobsfscan/many_findings_cwe_lower.json") - parser = MobsfscanParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(7, len(findings)) - - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("android_certificate_transparency", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(295, finding.cwe) - self.assertIsNotNone(finding.references) - - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("android_kotlin_hardcoded", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(798, finding.cwe) - self.assertIsNotNone(finding.references) - self.assertEqual("app/src/main/java/com/routes/domain/analytics/event/Signatures.kt", finding.file_path) - self.assertEqual(10, finding.line) - - with self.subTest(i=2): - finding = findings[2] - self.assertEqual("android_prevent_screenshot", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(200, finding.cwe) - self.assertIsNotNone(finding.references) - - with self.subTest(i=3): - finding = findings[3] - self.assertEqual("android_root_detection", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(919, finding.cwe) - self.assertIsNotNone(finding.references) - - with self.subTest(i=4): - finding = findings[4] - self.assertEqual("android_safetynet", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(353, finding.cwe) - self.assertIsNotNone(finding.references) - - with self.subTest(i=5): - finding = findings[5] - self.assertEqual("android_ssl_pinning", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(295, finding.cwe) - self.assertIsNotNone(finding.references) - - with self.subTest(i=6): - finding = findings[6] - self.assertEqual("android_tapjacking", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertEqual(200, finding.cwe) - self.assertIsNotNone(finding.references) + with open("unittests/scans/mobsfscan/many_findings_cwe_lower.json") as testfile: + parser = MobsfscanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(7, len(findings)) + + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("android_certificate_transparency", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(295, finding.cwe) + self.assertIsNotNone(finding.references) + + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("android_kotlin_hardcoded", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(798, finding.cwe) + self.assertIsNotNone(finding.references) + self.assertEqual("app/src/main/java/com/routes/domain/analytics/event/Signatures.kt", finding.file_path) + self.assertEqual(10, finding.line) + + with self.subTest(i=2): + finding = findings[2] + self.assertEqual("android_prevent_screenshot", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(200, finding.cwe) + self.assertIsNotNone(finding.references) + + with self.subTest(i=3): + finding = findings[3] + self.assertEqual("android_root_detection", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(919, finding.cwe) + self.assertIsNotNone(finding.references) + + with self.subTest(i=4): + finding = findings[4] + self.assertEqual("android_safetynet", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(353, finding.cwe) + self.assertIsNotNone(finding.references) + + with self.subTest(i=5): + finding = findings[5] + self.assertEqual("android_ssl_pinning", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(295, finding.cwe) + self.assertIsNotNone(finding.references) + + with self.subTest(i=6): + finding = findings[6] + self.assertEqual("android_tapjacking", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertEqual(200, finding.cwe) + self.assertIsNotNone(finding.references) diff --git a/unittests/tools/test_mozilla_observatory_parser.py b/unittests/tools/test_mozilla_observatory_parser.py index 4df3f20658..0408f7cea1 100644 --- a/unittests/tools/test_mozilla_observatory_parser.py +++ b/unittests/tools/test_mozilla_observatory_parser.py @@ -5,233 +5,233 @@ class TestMozillaObservatoryParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/mozilla_observatory/mozilla_no_vuln.json") - parser = MozillaObservatoryParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(4, len(findings)) - # test that all findings are not active - for finding in findings: - self.assertFalse(finding.active) - if "strict-transport-security" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertEqual("Preloaded via the HTTP Strict Transport Security (HSTS) preloading process", finding.title) - self.assertEqual("Info", finding.severity) - self.assertIn("Preloaded via the HTTP Strict Transport Security (HSTS) preloading process", finding.description) + with open("unittests/scans/mozilla_observatory/mozilla_no_vuln.json") as testfile: + parser = MozillaObservatoryParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(4, len(findings)) + # test that all findings are not active + for finding in findings: + self.assertFalse(finding.active) + if "strict-transport-security" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertEqual("Preloaded via the HTTP Strict Transport Security (HSTS) preloading process", finding.title) + self.assertEqual("Info", finding.severity) + self.assertIn("Preloaded via the HTTP Strict Transport Security (HSTS) preloading process", finding.description) def test_parse_file_with_two_vuln_has_two_findings(self): - testfile = open("unittests/scans/mozilla_observatory/mozilla_gitlab_two_vuln.json") - parser = MozillaObservatoryParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(2, len(findings)) + with open("unittests/scans/mozilla_observatory/mozilla_gitlab_two_vuln.json") as testfile: + parser = MozillaObservatoryParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(2, len(findings)) def test_parse_file_with_multiple_vuln_has_multiple_finding(self): - testfile = open("unittests/scans/mozilla_observatory/mozilla_google_many_vuln.json") - parser = MozillaObservatoryParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(6, len(findings)) + with open("unittests/scans/mozilla_observatory/mozilla_google_many_vuln.json") as testfile: + parser = MozillaObservatoryParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(6, len(findings)) def test_parse_file_cli_mozilla_org(self): """Test from the CLI""" - testfile = open("unittests/scans/mozilla_observatory/mozilla_org.json") - parser = MozillaObservatoryParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(12, len(findings)) - for finding in findings: - if "content-security-policy" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertTrue(finding.active) - self.assertEqual("Content Security Policy (CSP) implemented unsafely. This includes 'unsafe-inline' or data: inside script-src, overly broad sources such as https: inside object-src or script-src, or not restricting the sources for object-src or script-src.", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertIn("Content Security Policy (CSP) implemented unsafely. This includes 'unsafe-inline' or data: inside script-src, overly broad sources such as https: inside object-src or script-src, or not restricting the sources for object-src or script-src.", finding.description) - else: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertFalse(finding.active) + with open("unittests/scans/mozilla_observatory/mozilla_org.json") as testfile: + parser = MozillaObservatoryParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(12, len(findings)) + for finding in findings: + if "content-security-policy" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertTrue(finding.active) + self.assertEqual("Content Security Policy (CSP) implemented unsafely. This includes 'unsafe-inline' or data: inside script-src, overly broad sources such as https: inside object-src or script-src, or not restricting the sources for object-src or script-src.", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertIn("Content Security Policy (CSP) implemented unsafely. This includes 'unsafe-inline' or data: inside script-src, overly broad sources such as https: inside object-src or script-src, or not restricting the sources for object-src or script-src.", finding.description) + else: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertFalse(finding.active) def test_parse_file_cli_demo(self): """Test from the CLI""" - testfile = open("unittests/scans/mozilla_observatory/demo.json") - parser = MozillaObservatoryParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(12, len(findings)) - for finding in findings: - if "content-security-policy" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool="content-security-policy"): - self.assertTrue(finding.active) - self.assertEqual("Content Security Policy (CSP) header not implemented", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertIn("Content Security Policy (CSP) header not implemented", finding.description) - self.assertEqual("content-security-policy", finding.vuln_id_from_tool) - elif "cookies" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool="cookies"): - self.assertTrue(finding.active) - self.assertEqual("Cookies set without using the Secure flag or set over HTTP", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertIn("Cookies set without using the Secure flag or set over HTTP", finding.description) - elif "strict-transport-security" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool="strict-transport-security"): - self.assertTrue(finding.active) - self.assertEqual("HTTP Strict Transport Security (HSTS) header not implemented", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertIn("HTTP Strict Transport Security (HSTS) header not implemented", finding.description) - else: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertFalse(finding.active) + with open("unittests/scans/mozilla_observatory/demo.json") as testfile: + parser = MozillaObservatoryParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(12, len(findings)) + for finding in findings: + if "content-security-policy" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool="content-security-policy"): + self.assertTrue(finding.active) + self.assertEqual("Content Security Policy (CSP) header not implemented", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertIn("Content Security Policy (CSP) header not implemented", finding.description) + self.assertEqual("content-security-policy", finding.vuln_id_from_tool) + elif "cookies" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool="cookies"): + self.assertTrue(finding.active) + self.assertEqual("Cookies set without using the Secure flag or set over HTTP", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertIn("Cookies set without using the Secure flag or set over HTTP", finding.description) + elif "strict-transport-security" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool="strict-transport-security"): + self.assertTrue(finding.active) + self.assertEqual("HTTP Strict Transport Security (HSTS) header not implemented", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertIn("HTTP Strict Transport Security (HSTS) header not implemented", finding.description) + else: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertFalse(finding.active) def test_parse_file_cli_juicy(self): """Test from the CLI""" - testfile = open("unittests/scans/mozilla_observatory/juicy.json") - parser = MozillaObservatoryParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(12, len(findings)) - for finding in findings: - if "content-security-policy" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertTrue(finding.active) - self.assertEqual("Content Security Policy (CSP) header not implemented", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertIn("Content Security Policy (CSP) header not implemented", finding.description) - elif "strict-transport-security" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertTrue(finding.active) - self.assertEqual("HTTP Strict Transport Security (HSTS) header not implemented", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertIn("HTTP Strict Transport Security (HSTS) header not implemented", finding.description) - elif "x-xss-protection" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertTrue(finding.active) - self.assertEqual("X-XSS-Protection header not implemented", finding.title) - self.assertEqual("Low", finding.severity) - self.assertIn("X-XSS-Protection header not implemented", finding.description) - elif "subresource-integrity" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertTrue(finding.active) - self.assertEqual("Subresource Integrity (SRI) not implemented, and external scripts are loaded over HTTP or use protocol-relative URLs via src=\"//...\"", finding.title) - self.assertEqual("High", finding.severity) - self.assertIn("Subresource Integrity (SRI) not implemented", finding.description) - elif "redirection" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertTrue(finding.active) - self.assertEqual("Does not redirect to an HTTPS site", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertIn("Does not redirect to an HTTPS site", finding.description) - else: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertFalse(finding.active) + with open("unittests/scans/mozilla_observatory/juicy.json") as testfile: + parser = MozillaObservatoryParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(12, len(findings)) + for finding in findings: + if "content-security-policy" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertTrue(finding.active) + self.assertEqual("Content Security Policy (CSP) header not implemented", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertIn("Content Security Policy (CSP) header not implemented", finding.description) + elif "strict-transport-security" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertTrue(finding.active) + self.assertEqual("HTTP Strict Transport Security (HSTS) header not implemented", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertIn("HTTP Strict Transport Security (HSTS) header not implemented", finding.description) + elif "x-xss-protection" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertTrue(finding.active) + self.assertEqual("X-XSS-Protection header not implemented", finding.title) + self.assertEqual("Low", finding.severity) + self.assertIn("X-XSS-Protection header not implemented", finding.description) + elif "subresource-integrity" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertTrue(finding.active) + self.assertEqual("Subresource Integrity (SRI) not implemented, and external scripts are loaded over HTTP or use protocol-relative URLs via src=\"//...\"", finding.title) + self.assertEqual("High", finding.severity) + self.assertIn("Subresource Integrity (SRI) not implemented", finding.description) + elif "redirection" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertTrue(finding.active) + self.assertEqual("Does not redirect to an HTTPS site", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertIn("Does not redirect to an HTTPS site", finding.description) + else: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertFalse(finding.active) def test_parse_file_cli_nmap_scanme(self): """Test from the CLI""" - testfile = open("unittests/scans/mozilla_observatory/nmap_scanme.json") - parser = MozillaObservatoryParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(12, len(findings)) - for finding in findings: - if "content-security-policy" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertTrue(finding.active) - self.assertEqual("Content Security Policy (CSP) header not implemented", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertIn("Content Security Policy (CSP) header not implemented", finding.description) - elif "strict-transport-security" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertTrue(finding.active) - self.assertEqual("HTTP Strict Transport Security (HSTS) header cannot be set, as site contains an invalid certificate chain", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertIn("HTTP Strict Transport Security (HSTS) header cannot be set, as site contains an invalid certificate chain", finding.description) - elif "x-xss-protection" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertTrue(finding.active) - self.assertEqual("X-XSS-Protection header not implemented", finding.title) - self.assertEqual("Low", finding.severity) - self.assertIn("X-XSS-Protection header not implemented", finding.description) - elif "x-frame-options" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertTrue(finding.active) - self.assertEqual("X-Frame-Options (XFO) header not implemented", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertIn("X-Frame-Options (XFO) header not implemented", finding.description) - elif "x-content-type-options" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertTrue(finding.active) - self.assertEqual("X-Content-Type-Options header not implemented", finding.title) - self.assertEqual("Low", finding.severity) - self.assertIn("X-Content-Type-Options header not implemented", finding.description) - elif "subresource-integrity" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertTrue(finding.active) - self.assertEqual("Subresource Integrity (SRI) not implemented, and external scripts are loaded over HTTP or use protocol-relative URLs via src=\"//...\"", finding.title) - self.assertEqual("High", finding.severity) - self.assertIn("Subresource Integrity (SRI) not implemented", finding.description) - elif "redirection" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertTrue(finding.active) - self.assertEqual("Initial redirection from HTTP to HTTPS is to a different host, preventing HSTS", finding.title) - self.assertEqual("Low", finding.severity) - self.assertIn("Initial redirection from HTTP to HTTPS is to a different host, preventing HSTS", finding.description) - elif "referrer-policy-private" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertTrue(finding.active) - self.assertEqual("Referrer-Policy header not implemented", finding.title) - self.assertEqual("Info", finding.severity) - self.assertIn("Referrer-Policy header not implemented", finding.description) - else: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertFalse(finding.active) + with open("unittests/scans/mozilla_observatory/nmap_scanme.json") as testfile: + parser = MozillaObservatoryParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(12, len(findings)) + for finding in findings: + if "content-security-policy" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertTrue(finding.active) + self.assertEqual("Content Security Policy (CSP) header not implemented", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertIn("Content Security Policy (CSP) header not implemented", finding.description) + elif "strict-transport-security" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertTrue(finding.active) + self.assertEqual("HTTP Strict Transport Security (HSTS) header cannot be set, as site contains an invalid certificate chain", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertIn("HTTP Strict Transport Security (HSTS) header cannot be set, as site contains an invalid certificate chain", finding.description) + elif "x-xss-protection" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertTrue(finding.active) + self.assertEqual("X-XSS-Protection header not implemented", finding.title) + self.assertEqual("Low", finding.severity) + self.assertIn("X-XSS-Protection header not implemented", finding.description) + elif "x-frame-options" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertTrue(finding.active) + self.assertEqual("X-Frame-Options (XFO) header not implemented", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertIn("X-Frame-Options (XFO) header not implemented", finding.description) + elif "x-content-type-options" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertTrue(finding.active) + self.assertEqual("X-Content-Type-Options header not implemented", finding.title) + self.assertEqual("Low", finding.severity) + self.assertIn("X-Content-Type-Options header not implemented", finding.description) + elif "subresource-integrity" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertTrue(finding.active) + self.assertEqual("Subresource Integrity (SRI) not implemented, and external scripts are loaded over HTTP or use protocol-relative URLs via src=\"//...\"", finding.title) + self.assertEqual("High", finding.severity) + self.assertIn("Subresource Integrity (SRI) not implemented", finding.description) + elif "redirection" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertTrue(finding.active) + self.assertEqual("Initial redirection from HTTP to HTTPS is to a different host, preventing HSTS", finding.title) + self.assertEqual("Low", finding.severity) + self.assertIn("Initial redirection from HTTP to HTTPS is to a different host, preventing HSTS", finding.description) + elif "referrer-policy-private" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertTrue(finding.active) + self.assertEqual("Referrer-Policy header not implemented", finding.title) + self.assertEqual("Info", finding.severity) + self.assertIn("Referrer-Policy header not implemented", finding.description) + else: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertFalse(finding.active) def test_parse_file_cli_nmap_scanme_no_name_attribute(self): """Test from the CLI""" - testfile = open("unittests/scans/mozilla_observatory/nmap_scanme_2022.json") - parser = MozillaObservatoryParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(12, len(findings)) - for finding in findings: - if "content-security-policy" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertTrue(finding.active) - self.assertEqual("Content Security Policy (CSP) header not implemented", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertIn("Content Security Policy (CSP) header not implemented", finding.description) - elif "strict-transport-security" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertTrue(finding.active) - self.assertEqual("HTTP Strict Transport Security (HSTS) header cannot be set for sites not available over HTTPS", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertIn("HTTP Strict Transport Security (HSTS) header cannot be set for sites not available over HTTPS", finding.description) - elif "x-xss-protection" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertTrue(finding.active) - self.assertEqual("X-XSS-Protection header not implemented", finding.title) - self.assertEqual("Low", finding.severity) - self.assertIn("X-XSS-Protection header not implemented", finding.description) - elif "x-frame-options" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertTrue(finding.active) - self.assertEqual("X-Frame-Options (XFO) header not implemented", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertIn("X-Frame-Options (XFO) header not implemented", finding.description) - elif "x-content-type-options" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertTrue(finding.active) - self.assertEqual("X-Content-Type-Options header not implemented", finding.title) - self.assertEqual("Low", finding.severity) - self.assertIn("X-Content-Type-Options header not implemented", finding.description) - elif "subresource-integrity" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertFalse(finding.active) - self.assertEqual("Subresource Integrity (SRI) not implemented, but all scripts are loaded from a similar origin", finding.title) - self.assertEqual("Info", finding.severity) - self.assertIn("Subresource Integrity (SRI) not implemented", finding.description) - elif "redirection" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertTrue(finding.active) - self.assertEqual("Does not redirect to an HTTPS site", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertIn("Does not redirect to an HTTPS site", finding.description) - elif "referrer-policy-private" == finding.vuln_id_from_tool: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertTrue(finding.active) - self.assertEqual("Referrer-Policy header not implemented", finding.title) - self.assertEqual("Info", finding.severity) - self.assertIn("Referrer-Policy header not implemented", finding.description) - else: - with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): - self.assertFalse(finding.active) + with open("unittests/scans/mozilla_observatory/nmap_scanme_2022.json") as testfile: + parser = MozillaObservatoryParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(12, len(findings)) + for finding in findings: + if "content-security-policy" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertTrue(finding.active) + self.assertEqual("Content Security Policy (CSP) header not implemented", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertIn("Content Security Policy (CSP) header not implemented", finding.description) + elif "strict-transport-security" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertTrue(finding.active) + self.assertEqual("HTTP Strict Transport Security (HSTS) header cannot be set for sites not available over HTTPS", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertIn("HTTP Strict Transport Security (HSTS) header cannot be set for sites not available over HTTPS", finding.description) + elif "x-xss-protection" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertTrue(finding.active) + self.assertEqual("X-XSS-Protection header not implemented", finding.title) + self.assertEqual("Low", finding.severity) + self.assertIn("X-XSS-Protection header not implemented", finding.description) + elif "x-frame-options" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertTrue(finding.active) + self.assertEqual("X-Frame-Options (XFO) header not implemented", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertIn("X-Frame-Options (XFO) header not implemented", finding.description) + elif "x-content-type-options" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertTrue(finding.active) + self.assertEqual("X-Content-Type-Options header not implemented", finding.title) + self.assertEqual("Low", finding.severity) + self.assertIn("X-Content-Type-Options header not implemented", finding.description) + elif "subresource-integrity" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertFalse(finding.active) + self.assertEqual("Subresource Integrity (SRI) not implemented, but all scripts are loaded from a similar origin", finding.title) + self.assertEqual("Info", finding.severity) + self.assertIn("Subresource Integrity (SRI) not implemented", finding.description) + elif "redirection" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertTrue(finding.active) + self.assertEqual("Does not redirect to an HTTPS site", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertIn("Does not redirect to an HTTPS site", finding.description) + elif "referrer-policy-private" == finding.vuln_id_from_tool: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertTrue(finding.active) + self.assertEqual("Referrer-Policy header not implemented", finding.title) + self.assertEqual("Info", finding.severity) + self.assertIn("Referrer-Policy header not implemented", finding.description) + else: + with self.subTest(vuln_id_from_tool=finding.vuln_id_from_tool): + self.assertFalse(finding.active) diff --git a/unittests/tools/test_nancy_parser.py b/unittests/tools/test_nancy_parser.py index fdb7e77c28..ae45c36239 100644 --- a/unittests/tools/test_nancy_parser.py +++ b/unittests/tools/test_nancy_parser.py @@ -6,35 +6,32 @@ class TestNancyParser(DojoTestCase): def test_nancy_parser_with_no_vuln_has_no_findings(self): - testfile = open(path.join(path.dirname(__file__), "../scans/nancy/nancy_no_findings.json")) - parser = NancyParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(0, len(findings)) + with open(path.join(path.dirname(__file__), "../scans/nancy/nancy_no_findings.json")) as testfile: + parser = NancyParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_nancy_parser_with_one_vuln_has_one_findings(self): - testfile = open(path.join(path.dirname(__file__), "../scans/nancy/nancy_one_findings.json")) - parser = NancyParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual('Info', finding.severity) - self.assertIsNotNone(finding.description) - self.assertGreater(len(finding.description), 0) - self.assertEqual(None, finding.cve) - self.assertEqual("CVE-2017-1000070", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N", finding.cvssv3) + with open(path.join(path.dirname(__file__), "../scans/nancy/nancy_one_findings.json")) as testfile: + parser = NancyParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual('Info', finding.severity) + self.assertIsNotNone(finding.description) + self.assertGreater(len(finding.description), 0) + self.assertEqual(None, finding.cve) + self.assertEqual("CVE-2017-1000070", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N", finding.cvssv3) def test_nancy_plus_parser_with_many_vuln_has_many_findings(self): - testfile = open(path.join(path.dirname(__file__), "../scans/nancy/nancy_many_findings.json")) - parser = NancyParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(13, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual(0, finding.cwe) - self.assertIsNotNone(finding.description) - self.assertGreater(len(finding.description), 0) + with open(path.join(path.dirname(__file__), "../scans/nancy/nancy_many_findings.json")) as testfile: + parser = NancyParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(13, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual(0, finding.cwe) + self.assertIsNotNone(finding.description) + self.assertGreater(len(finding.description), 0) diff --git a/unittests/tools/test_netsparker_parser.py b/unittests/tools/test_netsparker_parser.py index c0ac7aa703..b675b04961 100644 --- a/unittests/tools/test_netsparker_parser.py +++ b/unittests/tools/test_netsparker_parser.py @@ -6,79 +6,79 @@ class TestNetsparkerParser(DojoTestCase): def test_parse_file_with_one_finding(self): - testfile = open("unittests/scans/netsparker/netsparker_one_finding.json") - parser = NetsparkerParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertEqual(16, finding.cwe) - self.assertEqual("25/06/2021", finding.date.strftime("%d/%m/%Y")) - self.assertIsNotNone(finding.description) - self.assertGreater(len(finding.description), 0) - self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N/E:H/RL:O/RC:C", finding.cvssv3) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(str(endpoint), "http://php.testsparker.com/auth/login.php") + with open("unittests/scans/netsparker/netsparker_one_finding.json") as testfile: + parser = NetsparkerParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertEqual(16, finding.cwe) + self.assertEqual("25/06/2021", finding.date.strftime("%d/%m/%Y")) + self.assertIsNotNone(finding.description) + self.assertGreater(len(finding.description), 0) + self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N/E:H/RL:O/RC:C", finding.cvssv3) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(str(endpoint), "http://php.testsparker.com/auth/login.php") def test_parse_file_with_multiple_finding(self): - testfile = open("unittests/scans/netsparker/netsparker_many_findings.json") - parser = NetsparkerParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(16, len(findings)) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertEqual(16, finding.cwe) - self.assertEqual("25/06/2021", finding.date.strftime("%d/%m/%Y")) - self.assertIsNotNone(finding.description) - self.assertGreater(len(finding.description), 0) - self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N/E:H/RL:O/RC:C", finding.cvssv3) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(str(endpoint), "http://php.testsparker.com/auth/login.php") + with open("unittests/scans/netsparker/netsparker_many_findings.json") as testfile: + parser = NetsparkerParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(16, len(findings)) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertEqual(16, finding.cwe) + self.assertEqual("25/06/2021", finding.date.strftime("%d/%m/%Y")) + self.assertIsNotNone(finding.description) + self.assertGreater(len(finding.description), 0) + self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N/E:H/RL:O/RC:C", finding.cvssv3) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(str(endpoint), "http://php.testsparker.com/auth/login.php") - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("Critical", finding.severity) - self.assertEqual(89, finding.cwe) - self.assertEqual("25/06/2021", finding.date.strftime("%d/%m/%Y")) - self.assertIsNotNone(finding.description) - self.assertGreater(len(finding.description), 0) - self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", finding.cvssv3) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(str(endpoint), "http://php.testsparker.com/artist.php?id=-1%20OR%2017-7=10") + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("Critical", finding.severity) + self.assertEqual(89, finding.cwe) + self.assertEqual("25/06/2021", finding.date.strftime("%d/%m/%Y")) + self.assertIsNotNone(finding.description) + self.assertGreater(len(finding.description), 0) + self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", finding.cvssv3) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(str(endpoint), "http://php.testsparker.com/artist.php?id=-1%20OR%2017-7=10") - with self.subTest(i=2): - finding = findings[2] - self.assertEqual("Medium", finding.severity) - self.assertEqual(205, finding.cwe) - self.assertEqual("25/06/2021", finding.date.strftime("%d/%m/%Y")) - self.assertIsNotNone(finding.description) - self.assertGreater(len(finding.description), 0) - self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N/E:H/RL:O/RC:C", finding.cvssv3) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(str(endpoint), "http://php.testsparker.com") + with self.subTest(i=2): + finding = findings[2] + self.assertEqual("Medium", finding.severity) + self.assertEqual(205, finding.cwe) + self.assertEqual("25/06/2021", finding.date.strftime("%d/%m/%Y")) + self.assertIsNotNone(finding.description) + self.assertGreater(len(finding.description), 0) + self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N/E:H/RL:O/RC:C", finding.cvssv3) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(str(endpoint), "http://php.testsparker.com") def test_parse_file_issue_9816(self): - testfile = open("unittests/scans/netsparker/issue_9816.json") - parser = NetsparkerParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(3, len(findings)) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("High", finding.severity) - self.assertEqual(614, finding.cwe) - self.assertEqual("03/02/2019", finding.date.strftime("%d/%m/%Y")) + with open("unittests/scans/netsparker/issue_9816.json") as testfile: + parser = NetsparkerParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(3, len(findings)) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("High", finding.severity) + self.assertEqual(614, finding.cwe) + self.assertEqual("03/02/2019", finding.date.strftime("%d/%m/%Y")) diff --git a/unittests/tools/test_nexpose_parser.py b/unittests/tools/test_nexpose_parser.py index 41b9ddffdf..c7d6554cbe 100644 --- a/unittests/tools/test_nexpose_parser.py +++ b/unittests/tools/test_nexpose_parser.py @@ -9,215 +9,214 @@ class TestNexposeParser(DojoTestCase): def test_nexpose_parser_has_no_finding(self): - testfile = open("unittests/scans/nexpose/no_vuln.xml") - parser = NexposeParser() - findings = parser.get_findings(testfile, Test()) + with open("unittests/scans/nexpose/no_vuln.xml") as testfile: + parser = NexposeParser() + findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() - self.assertEqual(1, len(findings)) + self.assertEqual(1, len(findings)) - # vuln 1 - finding = findings[0] - self.assertEqual("Info", finding.severity) - self.assertEqual("Host Up", finding.title) + # vuln 1 + finding = findings[0] + self.assertEqual("Info", finding.severity) + self.assertEqual("Host Up", finding.title) def test_nexpose_parser_has_many_finding(self): test = Test() test.engagement = Engagement() test.engagement.product = Product() - testfile = open("unittests/scans/nexpose/many_vulns.xml") - parser = NexposeParser() - findings = parser.get_findings(testfile, test) - testfile.close() - - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - - self.assertEqual(38, len(findings)) - - # vuln 1 - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertEqual("TCP Sequence Number Approximation Vulnerability", finding.title) - self.assertEqual(3, len(finding.unsaved_endpoints)) - self.assertIn("https://www.securityfocus.com/bid/10183", finding.references) # BID: 10183 - self.assertIn("https://www.kb.cert.org/vuls/id/415294.html", finding.references) # CERT-VN: 415294 - self.assertIn("https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2004-0230", finding.references) # CVE: CVE-2004-0230 - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2004-0230", finding.unsaved_vulnerability_ids[0]) - - # vuln 2 - finding = findings[2] - self.assertEqual("Low", finding.severity) - self.assertEqual("TCP timestamp response", finding.title) - self.assertEqual(5, len(finding.unsaved_endpoints)) - self.assertIsNone(finding.unsaved_vulnerability_ids) - - # vuln 2 - endpoint - endpoint = finding.unsaved_endpoints[0] - self.assertIsNone(endpoint.port) - self.assertIsNone(endpoint.protocol) - - # vuln 5 - finding = findings[5] - self.assertEqual("Default SSH password: root password \"root\"", finding.title) - self.assertEqual(1, len(finding.unsaved_endpoints)) - - # vuln 5 - endpoint - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(22, endpoint.port) - self.assertEqual("ssh", endpoint.protocol) - - # vuln 9 - finding = findings[9] - self.assertEqual("Missing HttpOnly Flag From Cookie", finding.title) - self.assertEqual(1, len(finding.unsaved_endpoints)) - - # vuln 9 - endpoint - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(80, endpoint.port) - self.assertEqual("http", endpoint.protocol) - - # vuln 26 - finding = findings[26] - self.assertIn("radius (RADIUS authentication protocol (RFC\n2138))", finding.description) - self.assertEqual("radius-radius-authentication-protocol-rfc-2138", finding.unsaved_tags[0]) - self.assertEqual("udp", finding.unsaved_endpoints[0].protocol) - - # vuln 27 - finding = findings[27] - self.assertIn("nfs_acl", finding.description) - self.assertEqual("nfs-acl", finding.unsaved_tags[0]) - self.assertEqual("tcp", finding.unsaved_endpoints[0].protocol) - - # vuln 29 - finding = findings[29] - self.assertIn("Backup Exec Agent Browser", finding.description) - self.assertEqual("backup-exec-agent-browser", finding.unsaved_tags[0]) - self.assertEqual("tcp", finding.unsaved_endpoints[0].protocol) - - # vuln 31 - finding = findings[31] - self.assertIn("sun-answerbook (Sun Answerbook HTTP server)", finding.description) - self.assertEqual("sun-answerbook-sun-answerbook-http-server", finding.unsaved_tags[0]) - self.assertEqual("tcp", finding.unsaved_endpoints[0].protocol) - - # vuln 32 - finding = findings[32] - self.assertIn("HP JetDirect Data", finding.description) - self.assertEqual("hp-jetdirect-data", finding.unsaved_tags[0]) - self.assertEqual("tcp", finding.unsaved_endpoints[0].protocol) - - # vuln 33 - finding = findings[33] - self.assertEqual("TLS/SSL Server Supports DES and IDEA Cipher Suites", finding.title) - self.assertEqual(1, len(finding.unsaved_endpoints)) - - # vuln 33 - endpoint - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(443, endpoint.port) - self.assertEqual("tcp", endpoint.protocol) - - # vuln 37 - finding = findings[37] - self.assertEqual("Open port UDP/137", finding.title) - self.assertIn('udp/137 port is open with "CIFS Name Service" service', finding.description) - self.assertIn('cifs-name-service', finding.unsaved_tags) - self.assertEqual(1, len(finding.unsaved_endpoints)) - - # vuln 37 - endpoint - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(137, endpoint.port) - self.assertEqual('udp', endpoint.protocol) + with open("unittests/scans/nexpose/many_vulns.xml") as testfile: + parser = NexposeParser() + findings = parser.get_findings(testfile, test) + + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + + self.assertEqual(38, len(findings)) + + # vuln 1 + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertEqual("TCP Sequence Number Approximation Vulnerability", finding.title) + self.assertEqual(3, len(finding.unsaved_endpoints)) + self.assertIn("https://www.securityfocus.com/bid/10183", finding.references) # BID: 10183 + self.assertIn("https://www.kb.cert.org/vuls/id/415294.html", finding.references) # CERT-VN: 415294 + self.assertIn("https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2004-0230", finding.references) # CVE: CVE-2004-0230 + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2004-0230", finding.unsaved_vulnerability_ids[0]) + + # vuln 2 + finding = findings[2] + self.assertEqual("Low", finding.severity) + self.assertEqual("TCP timestamp response", finding.title) + self.assertEqual(5, len(finding.unsaved_endpoints)) + self.assertIsNone(finding.unsaved_vulnerability_ids) + + # vuln 2 - endpoint + endpoint = finding.unsaved_endpoints[0] + self.assertIsNone(endpoint.port) + self.assertIsNone(endpoint.protocol) + + # vuln 5 + finding = findings[5] + self.assertEqual("Default SSH password: root password \"root\"", finding.title) + self.assertEqual(1, len(finding.unsaved_endpoints)) + + # vuln 5 - endpoint + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(22, endpoint.port) + self.assertEqual("ssh", endpoint.protocol) + + # vuln 9 + finding = findings[9] + self.assertEqual("Missing HttpOnly Flag From Cookie", finding.title) + self.assertEqual(1, len(finding.unsaved_endpoints)) + + # vuln 9 - endpoint + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(80, endpoint.port) + self.assertEqual("http", endpoint.protocol) + + # vuln 26 + finding = findings[26] + self.assertIn("radius (RADIUS authentication protocol (RFC\n2138))", finding.description) + self.assertEqual("radius-radius-authentication-protocol-rfc-2138", finding.unsaved_tags[0]) + self.assertEqual("udp", finding.unsaved_endpoints[0].protocol) + + # vuln 27 + finding = findings[27] + self.assertIn("nfs_acl", finding.description) + self.assertEqual("nfs-acl", finding.unsaved_tags[0]) + self.assertEqual("tcp", finding.unsaved_endpoints[0].protocol) + + # vuln 29 + finding = findings[29] + self.assertIn("Backup Exec Agent Browser", finding.description) + self.assertEqual("backup-exec-agent-browser", finding.unsaved_tags[0]) + self.assertEqual("tcp", finding.unsaved_endpoints[0].protocol) + + # vuln 31 + finding = findings[31] + self.assertIn("sun-answerbook (Sun Answerbook HTTP server)", finding.description) + self.assertEqual("sun-answerbook-sun-answerbook-http-server", finding.unsaved_tags[0]) + self.assertEqual("tcp", finding.unsaved_endpoints[0].protocol) + + # vuln 32 + finding = findings[32] + self.assertIn("HP JetDirect Data", finding.description) + self.assertEqual("hp-jetdirect-data", finding.unsaved_tags[0]) + self.assertEqual("tcp", finding.unsaved_endpoints[0].protocol) + + # vuln 33 + finding = findings[33] + self.assertEqual("TLS/SSL Server Supports DES and IDEA Cipher Suites", finding.title) + self.assertEqual(1, len(finding.unsaved_endpoints)) + + # vuln 33 - endpoint + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(443, endpoint.port) + self.assertEqual("tcp", endpoint.protocol) + + # vuln 37 + finding = findings[37] + self.assertEqual("Open port UDP/137", finding.title) + self.assertIn('udp/137 port is open with "CIFS Name Service" service', finding.description) + self.assertIn('cifs-name-service', finding.unsaved_tags) + self.assertEqual(1, len(finding.unsaved_endpoints)) + + # vuln 37 - endpoint + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(137, endpoint.port) + self.assertEqual('udp', endpoint.protocol) def test_nexpose_parser_tests_outside_endpoint(self): - testfile = open("unittests/scans/nexpose/report_auth.xml") - parser = NexposeParser() - - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - - self.assertEqual(5, len(findings)) - - # vuln 0 - finding = findings[0] - self.assertEqual("High", finding.severity) - self.assertEqual("ICMP redirection enabled", finding.title) - self.assertEqual(4, len(finding.unsaved_endpoints)) - self.assertIsNone(finding.unsaved_vulnerability_ids) - - # vuln 1 - finding = findings[1] - self.assertEqual("Medium", finding.severity) - self.assertEqual("No password for Grub", finding.title) - self.assertEqual(4, len(finding.unsaved_endpoints)) - self.assertIsNone(finding.unsaved_vulnerability_ids) - - # vuln 2 - finding = findings[2] - self.assertEqual("Low", finding.severity) - self.assertEqual("User home directory mode unsafe", finding.title) - self.assertEqual(16, len(finding.unsaved_endpoints)) - self.assertIsNone(finding.unsaved_vulnerability_ids) + with open("unittests/scans/nexpose/report_auth.xml") as testfile: + parser = NexposeParser() + + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + + self.assertEqual(5, len(findings)) + + # vuln 0 + finding = findings[0] + self.assertEqual("High", finding.severity) + self.assertEqual("ICMP redirection enabled", finding.title) + self.assertEqual(4, len(finding.unsaved_endpoints)) + self.assertIsNone(finding.unsaved_vulnerability_ids) + + # vuln 1 + finding = findings[1] + self.assertEqual("Medium", finding.severity) + self.assertEqual("No password for Grub", finding.title) + self.assertEqual(4, len(finding.unsaved_endpoints)) + self.assertIsNone(finding.unsaved_vulnerability_ids) + + # vuln 2 + finding = findings[2] + self.assertEqual("Low", finding.severity) + self.assertEqual("User home directory mode unsafe", finding.title) + self.assertEqual(16, len(finding.unsaved_endpoints)) + self.assertIsNone(finding.unsaved_vulnerability_ids) def test_nexpose_parser_dns(self): - testfile = open("unittests/scans/nexpose/dns.xml") - parser = NexposeParser() - findings = parser.get_findings(testfile, Test()) - - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - - self.assertEqual(6, len(findings)) - # vuln 1 - finding = findings[1] - self.assertEqual("DNS server allows cache snooping", finding.title) - self.assertEqual(2, len(finding.unsaved_endpoints)) - self.assertEqual('dns', str(finding.unsaved_endpoints[0].protocol)) - self.assertEqual('tcp', str(finding.unsaved_endpoints[0].fragment)) - self.assertEqual('dns', str(finding.unsaved_endpoints[1].protocol)) - self.assertEqual('udp', str(finding.unsaved_endpoints[1].fragment)) - self.assertEqual('dns://192.168.1.1#tcp', str(finding.unsaved_endpoints[0])) - self.assertEqual('dns://192.168.1.1#udp', str(finding.unsaved_endpoints[1])) - - # vuln 2 - finding = findings[2] - self.assertEqual("Nameserver Processes Recursive Queries", finding.title) - self.assertEqual(2, len(finding.unsaved_endpoints)) - self.assertEqual('dns', str(finding.unsaved_endpoints[0].protocol)) - self.assertEqual('tcp', str(finding.unsaved_endpoints[0].fragment)) - self.assertEqual('dns', str(finding.unsaved_endpoints[1].protocol)) - self.assertEqual('udp', str(finding.unsaved_endpoints[1].fragment)) - self.assertEqual('dns://192.168.1.1#tcp', str(finding.unsaved_endpoints[0])) - self.assertEqual('dns://192.168.1.1#udp', str(finding.unsaved_endpoints[1])) - - # vuln 4 - finding = findings[4] - self.assertEqual("DNS Traffic Amplification", finding.title) - self.assertEqual(1, len(finding.unsaved_endpoints)) - self.assertEqual('dns', str(finding.unsaved_endpoints[0].protocol)) - self.assertEqual('udp', str(finding.unsaved_endpoints[0].fragment)) - self.assertEqual('dns://192.168.1.1#udp', str(finding.unsaved_endpoints[0])) + with open("unittests/scans/nexpose/dns.xml") as testfile: + parser = NexposeParser() + findings = parser.get_findings(testfile, Test()) + + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + + self.assertEqual(6, len(findings)) + # vuln 1 + finding = findings[1] + self.assertEqual("DNS server allows cache snooping", finding.title) + self.assertEqual(2, len(finding.unsaved_endpoints)) + self.assertEqual('dns', str(finding.unsaved_endpoints[0].protocol)) + self.assertEqual('tcp', str(finding.unsaved_endpoints[0].fragment)) + self.assertEqual('dns', str(finding.unsaved_endpoints[1].protocol)) + self.assertEqual('udp', str(finding.unsaved_endpoints[1].fragment)) + self.assertEqual('dns://192.168.1.1#tcp', str(finding.unsaved_endpoints[0])) + self.assertEqual('dns://192.168.1.1#udp', str(finding.unsaved_endpoints[1])) + + # vuln 2 + finding = findings[2] + self.assertEqual("Nameserver Processes Recursive Queries", finding.title) + self.assertEqual(2, len(finding.unsaved_endpoints)) + self.assertEqual('dns', str(finding.unsaved_endpoints[0].protocol)) + self.assertEqual('tcp', str(finding.unsaved_endpoints[0].fragment)) + self.assertEqual('dns', str(finding.unsaved_endpoints[1].protocol)) + self.assertEqual('udp', str(finding.unsaved_endpoints[1].fragment)) + self.assertEqual('dns://192.168.1.1#tcp', str(finding.unsaved_endpoints[0])) + self.assertEqual('dns://192.168.1.1#udp', str(finding.unsaved_endpoints[1])) + + # vuln 4 + finding = findings[4] + self.assertEqual("DNS Traffic Amplification", finding.title) + self.assertEqual(1, len(finding.unsaved_endpoints)) + self.assertEqual('dns', str(finding.unsaved_endpoints[0].protocol)) + self.assertEqual('udp', str(finding.unsaved_endpoints[0].fragment)) + self.assertEqual('dns://192.168.1.1#udp', str(finding.unsaved_endpoints[0])) @override_settings(USE_FIRST_SEEN=True) def test_nexpose_parser_use_first_seen(self): - testfile = open("unittests/scans/nexpose/dns.xml") - parser = NexposeParser() - findings = parser.get_findings(testfile, Test()) - - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - - self.assertEqual(6, len(findings)) - finding = findings[2] - self.assertEqual(datetime.datetime(2021, 2, 11, 16, 45, 6, 81000), finding.date, finding.title) - finding = findings[4] - self.assertEqual(datetime.datetime(2021, 2, 11, 16, 45, 6, 81000), finding.date, finding.title) + with open("unittests/scans/nexpose/dns.xml") as testfile: + parser = NexposeParser() + findings = parser.get_findings(testfile, Test()) + + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + + self.assertEqual(6, len(findings)) + finding = findings[2] + self.assertEqual(datetime.datetime(2021, 2, 11, 16, 45, 6, 81000), finding.date, finding.title) + finding = findings[4] + self.assertEqual(datetime.datetime(2021, 2, 11, 16, 45, 6, 81000), finding.date, finding.title) diff --git a/unittests/tools/test_nikto_parser.py b/unittests/tools/test_nikto_parser.py index 862b948929..69be4b0b3a 100644 --- a/unittests/tools/test_nikto_parser.py +++ b/unittests/tools/test_nikto_parser.py @@ -10,178 +10,176 @@ def test_parse_file_with_old_format(self): engagement = Engagement() engagement.product = Product() test.engagement = engagement - testfile = open("unittests/scans/nikto/nikto-report-old-format.xml") - parser = NiktoParser() - findings = parser.get_findings(testfile, test) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) + with open("unittests/scans/nikto/nikto-report-old-format.xml") as testfile: + parser = NiktoParser() + findings = parser.get_findings(testfile, test) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/nikto/nikto-report-zero-vuln.xml") - parser = NiktoParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/nikto/nikto-report-zero-vuln.xml") as testfile: + parser = NiktoParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_finding(self): test = Test() engagement = Engagement() engagement.product = Product() test.engagement = engagement - testfile = open("unittests/scans/nikto/nikto-report-one-vuln.xml") - parser = NiktoParser() - findings = parser.get_findings(testfile, test) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) + with open("unittests/scans/nikto/nikto-report-one-vuln.xml") as testfile: + parser = NiktoParser() + findings = parser.get_findings(testfile, test) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) def test_parse_file_with_multiple_vuln_has_multiple_findings(self): test = Test() engagement = Engagement() engagement.product = Product() test.engagement = engagement - testfile = open("unittests/scans/nikto/nikto-report-many-vuln.xml") - parser = NiktoParser() - findings = parser.get_findings(testfile, test) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(len(findings), 10) + with open("unittests/scans/nikto/nikto-report-many-vuln.xml") as testfile: + parser = NiktoParser() + findings = parser.get_findings(testfile, test) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(len(findings), 10) def test_parse_file_json_with_multiple_vuln_has_multiple_findings(self): - testfile = open("unittests/scans/nikto/juice-shop.json") - parser = NiktoParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(11, len(findings)) - for finding in findings: - if "OSVDB-3092" == finding.unique_id_from_tool: - self.assertEqual("001811", finding.vuln_id_from_tool) + with open("unittests/scans/nikto/juice-shop.json") as testfile: + parser = NiktoParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(11, len(findings)) + for finding in findings: + if "OSVDB-3092" == finding.unique_id_from_tool: + self.assertEqual("001811", finding.vuln_id_from_tool) + self.assertEqual(1, finding.nb_occurences) + self.assertEqual("Medium", finding.severity) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(443, endpoint.port) + self.assertEqual("juice-shop.herokuapp.com", endpoint.host) + self.assertEqual("public/", endpoint.path) + if ("Retrieved via header: 1.1 vegur" == finding.title and "Info" == finding.severity): + self.assertEqual(1, len(finding.unsaved_endpoints)) + if ("Potentially Interesting Backup/Cert File Found. " == finding.title and "Info" == finding.severity): + self.assertEqual(140, len(finding.unsaved_endpoints)) + + def test_parse_file_json_with_uri_errors(self): + with open("unittests/scans/nikto/nikto-output.xml") as testfile: + parser = NiktoParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(13, len(findings)) + for finding in findings: + if "favicon.ico file identifies this server as: Apache Tomcat" == finding.title: + self.assertEqual("500008", finding.vuln_id_from_tool) + self.assertEqual(1, finding.nb_occurences) + self.assertEqual("Medium", finding.severity) + # this one as error in URL + # self.assertEqual(1, len(finding.unsaved_endpoints)) + # endpoint = finding.unsaved_endpoints[0] + # self.assertEqual(443, endpoint.port) + # self.assertEqual("juice-shop.herokuapp.com", endpoint.host) + # self.assertEqual("public/", endpoint.path) + elif "/examples/servlets/index.html: Apache Tomcat default JSP pages present." == finding.title: + self.assertEqual("000366", finding.vuln_id_from_tool) + self.assertEqual(1, finding.nb_occurences) + self.assertEqual("Info", finding.severity) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(8070, endpoint.port) + self.assertEqual("127.0.0.1", endpoint.host) + self.assertEqual("examples/servlets/index.html", endpoint.path) + + def test_parse_file_json_another(self): + with open("unittests/scans/nikto/tdh.json") as testfile: + parser = NiktoParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(8, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Uncommon header 'x-cacheable' found, with contents: YES", finding.title) + self.assertEqual("999100", finding.vuln_id_from_tool) self.assertEqual(1, finding.nb_occurences) - self.assertEqual("Medium", finding.severity) + self.assertEqual("Info", finding.severity) self.assertEqual(1, len(finding.unsaved_endpoints)) endpoint = finding.unsaved_endpoints[0] self.assertEqual(443, endpoint.port) - self.assertEqual("juice-shop.herokuapp.com", endpoint.host) - self.assertEqual("public/", endpoint.path) - if ("Retrieved via header: 1.1 vegur" == finding.title - and "Info" == finding.severity): + self.assertEqual("www.tdh.com", endpoint.host) + self.assertIsNone(endpoint.path) + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("Uncommon header 'x-cache' found, with contents: HIT", finding.title) + self.assertEqual("999100", finding.vuln_id_from_tool) + self.assertEqual(1, finding.nb_occurences) + self.assertEqual("Info", finding.severity) self.assertEqual(1, len(finding.unsaved_endpoints)) - if ("Potentially Interesting Backup/Cert File Found. " == finding.title - and "Info" == finding.severity): - self.assertEqual(140, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(443, endpoint.port) + self.assertEqual("www.tdh.com", endpoint.host) + self.assertIsNone(endpoint.path) - def test_parse_file_json_with_uri_errors(self): - testfile = open("unittests/scans/nikto/nikto-output.xml") - parser = NiktoParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(13, len(findings)) - for finding in findings: - if "favicon.ico file identifies this server as: Apache Tomcat" == finding.title: - self.assertEqual("500008", finding.vuln_id_from_tool) + def test_parse_file_xml_another(self): + with open("unittests/scans/nikto/tdh.xml") as testfile: + parser = NiktoParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(6, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Uncommon header 'x-cache' found, with contents: HIT", finding.title) + self.assertEqual("999100", finding.vuln_id_from_tool) self.assertEqual(1, finding.nb_occurences) - self.assertEqual("Medium", finding.severity) - # this one as error in URL - # self.assertEqual(1, len(finding.unsaved_endpoints)) - # endpoint = finding.unsaved_endpoints[0] - # self.assertEqual(443, endpoint.port) - # self.assertEqual("juice-shop.herokuapp.com", endpoint.host) - # self.assertEqual("public/", endpoint.path) - elif "/examples/servlets/index.html: Apache Tomcat default JSP pages present." == finding.title: - self.assertEqual("000366", finding.vuln_id_from_tool) + self.assertEqual("Info", finding.severity) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(443, endpoint.port) + self.assertEqual("64.220.43.153", endpoint.host) + self.assertIsNone(endpoint.path) + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("Uncommon header 'x-cacheable' found, with contents: YES", finding.title) + self.assertEqual("999100", finding.vuln_id_from_tool) self.assertEqual(1, finding.nb_occurences) self.assertEqual("Info", finding.severity) self.assertEqual(1, len(finding.unsaved_endpoints)) endpoint = finding.unsaved_endpoints[0] - self.assertEqual(8070, endpoint.port) - self.assertEqual("127.0.0.1", endpoint.host) - self.assertEqual("examples/servlets/index.html", endpoint.path) - - def test_parse_file_json_another(self): - testfile = open("unittests/scans/nikto/tdh.json") - parser = NiktoParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(8, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Uncommon header 'x-cacheable' found, with contents: YES", finding.title) - self.assertEqual("999100", finding.vuln_id_from_tool) - self.assertEqual(1, finding.nb_occurences) - self.assertEqual("Info", finding.severity) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(443, endpoint.port) - self.assertEqual("www.tdh.com", endpoint.host) - self.assertIsNone(endpoint.path) - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("Uncommon header 'x-cache' found, with contents: HIT", finding.title) - self.assertEqual("999100", finding.vuln_id_from_tool) - self.assertEqual(1, finding.nb_occurences) - self.assertEqual("Info", finding.severity) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(443, endpoint.port) - self.assertEqual("www.tdh.com", endpoint.host) - self.assertIsNone(endpoint.path) - - def test_parse_file_xml_another(self): - testfile = open("unittests/scans/nikto/tdh.xml") - parser = NiktoParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(6, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Uncommon header 'x-cache' found, with contents: HIT", finding.title) - self.assertEqual("999100", finding.vuln_id_from_tool) - self.assertEqual(1, finding.nb_occurences) - self.assertEqual("Info", finding.severity) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(443, endpoint.port) - self.assertEqual("64.220.43.153", endpoint.host) - self.assertIsNone(endpoint.path) - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("Uncommon header 'x-cacheable' found, with contents: YES", finding.title) - self.assertEqual("999100", finding.vuln_id_from_tool) - self.assertEqual(1, finding.nb_occurences) - self.assertEqual("Info", finding.severity) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(443, endpoint.port) - self.assertEqual("64.220.43.153", endpoint.host) - self.assertIsNone(endpoint.path) - with self.subTest(i=5): - finding = findings[5] - self.assertEqual("The Content-Encoding header is set to \"deflate\" this may mean that the server is vulnerable to the BREACH attack.", finding.title) - self.assertEqual("999966", finding.vuln_id_from_tool) - self.assertEqual(1, finding.nb_occurences) - self.assertEqual("Info", finding.severity) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(443, endpoint.port) - self.assertEqual("64.220.43.153", endpoint.host) - self.assertIsNone(endpoint.path) + self.assertEqual(443, endpoint.port) + self.assertEqual("64.220.43.153", endpoint.host) + self.assertIsNone(endpoint.path) + with self.subTest(i=5): + finding = findings[5] + self.assertEqual("The Content-Encoding header is set to \"deflate\" this may mean that the server is vulnerable to the BREACH attack.", finding.title) + self.assertEqual("999966", finding.vuln_id_from_tool) + self.assertEqual(1, finding.nb_occurences) + self.assertEqual("Info", finding.severity) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(443, endpoint.port) + self.assertEqual("64.220.43.153", endpoint.host) + self.assertIsNone(endpoint.path) def test_parse_file_issue_9274(self): - testfile = open("unittests/scans/nikto/issue_9274.json") - parser = NiktoParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(8, len(findings)) + with open("unittests/scans/nikto/issue_9274.json") as testfile: + parser = NiktoParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(8, len(findings)) diff --git a/unittests/tools/test_nmap_parser.py b/unittests/tools/test_nmap_parser.py index 0852a3d3df..4cc6297642 100644 --- a/unittests/tools/test_nmap_parser.py +++ b/unittests/tools/test_nmap_parser.py @@ -8,126 +8,126 @@ class TestNmapParser(DojoTestCase): def test_parse_file_with_no_open_ports_has_no_findings(self): - testfile = open("unittests/scans/nmap/nmap_0port.xml") - parser = NmapParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(0, len(findings)) + with open("unittests/scans/nmap/nmap_0port.xml") as testfile: + parser = NmapParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(0, len(findings)) def test_parse_file_with_single_open_ports_has_single_finding(self): - testfile = open("unittests/scans/nmap/nmap_1port.xml") - parser = NmapParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) + with open("unittests/scans/nmap/nmap_1port.xml") as testfile: + parser = NmapParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Info", finding.severity) - self.assertEqual("Open port: 5432/tcp", finding.title) - self.assertEqual(datetime.datetime(2014, 3, 29, 14, 46, 56), finding.date) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual('localhost.localdomain', endpoint.host) - self.assertEqual(5432, endpoint.port) - self.assertEqual('tcp', endpoint.protocol) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Info", finding.severity) + self.assertEqual("Open port: 5432/tcp", finding.title) + self.assertEqual(datetime.datetime(2014, 3, 29, 14, 46, 56), finding.date) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual('localhost.localdomain', endpoint.host) + self.assertEqual(5432, endpoint.port) + self.assertEqual('tcp', endpoint.protocol) def test_parse_file_with_multiple_open_ports_has_multiple_finding(self): - testfile = open("unittests/scans/nmap/nmap_multiple_port.xml") - parser = NmapParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(13, len(findings)) + with open("unittests/scans/nmap/nmap_multiple_port.xml") as testfile: + parser = NmapParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(13, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Info", finding.severity) - self.assertEqual("Open port: 21/tcp", finding.title) - self.assertEqual(datetime.datetime(2016, 5, 16, 17, 56, 59), finding.date) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual('mocha2005.mochahost.com', endpoint.host) - self.assertEqual(21, endpoint.port) - self.assertEqual('tcp', endpoint.protocol) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Info", finding.severity) + self.assertEqual("Open port: 21/tcp", finding.title) + self.assertEqual(datetime.datetime(2016, 5, 16, 17, 56, 59), finding.date) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual('mocha2005.mochahost.com', endpoint.host) + self.assertEqual(21, endpoint.port) + self.assertEqual('tcp', endpoint.protocol) def test_parse_file_with_script_vulner(self): - testfile = open("unittests/scans/nmap/nmap_script_vulners.xml") - parser = NmapParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(3, len(findings)) + with open("unittests/scans/nmap/nmap_script_vulners.xml") as testfile: + parser = NmapParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(3, len(findings)) - self.assertEqual("Medium", findings[0].severity) - self.assertEqual(1, len(findings[0].unsaved_vulnerability_ids)) - self.assertEqual("CVE-2018-15919", findings[0].unsaved_vulnerability_ids[0]) - self.assertEqual("openssh", findings[0].component_name) - self.assertEqual("7.4", findings[0].component_version) - self.assertEqual(datetime.datetime(2020, 2, 17, 9, 7, 25), findings[0].date) + self.assertEqual("Medium", findings[0].severity) + self.assertEqual(1, len(findings[0].unsaved_vulnerability_ids)) + self.assertEqual("CVE-2018-15919", findings[0].unsaved_vulnerability_ids[0]) + self.assertEqual("openssh", findings[0].component_name) + self.assertEqual("7.4", findings[0].component_version) + self.assertEqual(datetime.datetime(2020, 2, 17, 9, 7, 25), findings[0].date) - self.assertEqual("Medium", findings[1].severity) - self.assertEqual(1, len(findings[0].unsaved_vulnerability_ids)) - self.assertEqual("CVE-2017-15906", findings[1].unsaved_vulnerability_ids[0]) - self.assertEqual("openssh", findings[1].component_name) - self.assertEqual("7.4", findings[1].component_version) - self.assertEqual(datetime.datetime(2020, 2, 17, 9, 7, 25), findings[1].date) + self.assertEqual("Medium", findings[1].severity) + self.assertEqual(1, len(findings[0].unsaved_vulnerability_ids)) + self.assertEqual("CVE-2017-15906", findings[1].unsaved_vulnerability_ids[0]) + self.assertEqual("openssh", findings[1].component_name) + self.assertEqual("7.4", findings[1].component_version) + self.assertEqual(datetime.datetime(2020, 2, 17, 9, 7, 25), findings[1].date) - self.assertEqual("Info", findings[2].severity) - self.assertEqual(datetime.datetime(2020, 2, 17, 9, 7, 25), findings[2].date) + self.assertEqual("Info", findings[2].severity) + self.assertEqual(datetime.datetime(2020, 2, 17, 9, 7, 25), findings[2].date) def test_parse_issue4406(self): - testfile = open("unittests/scans/nmap/issue4406.xml") - parser = NmapParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(67, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertEqual("openssh", finding.component_name) - self.assertEqual("7.4", finding.component_version) - self.assertEqual(datetime.datetime(2021, 4, 29, 9, 26, 36), finding.date) - self.assertEqual("MSF:ILITIES/UBUNTU-CVE-2019-6111/", finding.vuln_id_from_tool) - with self.subTest(i=22): - finding = findings[22] - self.assertEqual("Medium", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2019-6111", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("openssh", finding.component_name) - self.assertEqual("7.4", finding.component_version) - self.assertEqual(datetime.datetime(2021, 4, 29, 9, 26, 36), finding.date) - with self.subTest(i=27): - finding = findings[27] - self.assertEqual("Medium", finding.severity) - self.assertEqual("EXPLOITPACK:EBDBC5685E3276D648B4D14B75563283", finding.title) - self.assertEqual(datetime.datetime(2021, 4, 29, 9, 26, 36), finding.date) - self.assertEqual("EXPLOITPACK:EBDBC5685E3276D648B4D14B75563283", finding.vuln_id_from_tool) - with self.subTest(i=48): - finding = findings[48] - self.assertEqual("Info", finding.severity) - self.assertEqual("Open port: 9100/tcp", finding.title) - self.assertEqual(datetime.datetime(2021, 4, 29, 9, 26, 36), finding.date) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual('ip-10-250-195-71.eu-west-1.compute.internal', endpoint.host) - self.assertEqual(9100, endpoint.port) - self.assertEqual('tcp', endpoint.protocol) - with self.subTest(i=66): - finding = findings[66] - self.assertEqual("Info", finding.severity) - self.assertEqual("Open port: 31641/tcp", finding.title) - self.assertEqual(datetime.datetime(2021, 4, 29, 9, 26, 36), finding.date) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual('ip-10-250-195-71.eu-west-1.compute.internal', endpoint.host) - self.assertEqual(31641, endpoint.port) - self.assertEqual('tcp', endpoint.protocol) + with open("unittests/scans/nmap/issue4406.xml") as testfile: + parser = NmapParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(67, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertEqual("openssh", finding.component_name) + self.assertEqual("7.4", finding.component_version) + self.assertEqual(datetime.datetime(2021, 4, 29, 9, 26, 36), finding.date) + self.assertEqual("MSF:ILITIES/UBUNTU-CVE-2019-6111/", finding.vuln_id_from_tool) + with self.subTest(i=22): + finding = findings[22] + self.assertEqual("Medium", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2019-6111", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("openssh", finding.component_name) + self.assertEqual("7.4", finding.component_version) + self.assertEqual(datetime.datetime(2021, 4, 29, 9, 26, 36), finding.date) + with self.subTest(i=27): + finding = findings[27] + self.assertEqual("Medium", finding.severity) + self.assertEqual("EXPLOITPACK:EBDBC5685E3276D648B4D14B75563283", finding.title) + self.assertEqual(datetime.datetime(2021, 4, 29, 9, 26, 36), finding.date) + self.assertEqual("EXPLOITPACK:EBDBC5685E3276D648B4D14B75563283", finding.vuln_id_from_tool) + with self.subTest(i=48): + finding = findings[48] + self.assertEqual("Info", finding.severity) + self.assertEqual("Open port: 9100/tcp", finding.title) + self.assertEqual(datetime.datetime(2021, 4, 29, 9, 26, 36), finding.date) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual('ip-10-250-195-71.eu-west-1.compute.internal', endpoint.host) + self.assertEqual(9100, endpoint.port) + self.assertEqual('tcp', endpoint.protocol) + with self.subTest(i=66): + finding = findings[66] + self.assertEqual("Info", finding.severity) + self.assertEqual("Open port: 31641/tcp", finding.title) + self.assertEqual(datetime.datetime(2021, 4, 29, 9, 26, 36), finding.date) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual('ip-10-250-195-71.eu-west-1.compute.internal', endpoint.host) + self.assertEqual(31641, endpoint.port) + self.assertEqual('tcp', endpoint.protocol) diff --git a/unittests/tools/test_noseyparker_parser.py b/unittests/tools/test_noseyparker_parser.py index cb837ee23d..0e2c224b57 100644 --- a/unittests/tools/test_noseyparker_parser.py +++ b/unittests/tools/test_noseyparker_parser.py @@ -6,42 +6,39 @@ class TestNoseyParkerParser(TestCase): def test_noseyparker_parser__no_vulns(self): - testfile = open("unittests/scans/noseyparker/noseyparker_zero_vul.jsonl") - parser = NoseyParkerParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) - testfile.close() + with open("unittests/scans/noseyparker/noseyparker_zero_vul.jsonl") as testfile: + parser = NoseyParkerParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_noseyparker_parser_one_vuln(self): - testfile = open("unittests/scans/noseyparker/noseyparker_one_vul.jsonl") - parser = NoseyParkerParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - finding = findings[0] - self.assertEqual("app/schema/config.py", finding.file_path) - self.assertEqual("High", finding.severity) - self.assertEqual(798, finding.cwe) - self.assertEqual(1, len(findings)) + with open("unittests/scans/noseyparker/noseyparker_one_vul.jsonl") as testfile: + parser = NoseyParkerParser() + findings = parser.get_findings(testfile, Test()) + finding = findings[0] + self.assertEqual("app/schema/config.py", finding.file_path) + self.assertEqual("High", finding.severity) + self.assertEqual(798, finding.cwe) + self.assertEqual(1, len(findings)) def test_noseyparker_parser_many_vulns(self): # Testfile contains 5 lines (Middle 2 are duplicates and line #4 has 2 of the same exact matches) - testfile = open("unittests/scans/noseyparker/noseyparker_many_vul.jsonl") - parser = NoseyParkerParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - self.assertEqual("High", finding.severity) - self.assertEqual(798, finding.cwe) - self.assertEqual(3, len(findings)) + with open("unittests/scans/noseyparker/noseyparker_many_vul.jsonl") as testfile: + parser = NoseyParkerParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + self.assertEqual("High", finding.severity) + self.assertEqual(798, finding.cwe) + self.assertEqual(3, len(findings)) def test_noseyparker_parser_error(self): with self.assertRaises(ValueError) as context: - testfile = open("unittests/scans/noseyparker/empty_with_error.json") - parser = NoseyParkerParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(0, len(findings)) - self.assertTrue( - "Invalid Nosey Parker data, make sure to use Nosey Parker v0.16.0" in str(context.exception) - ) - self.assertTrue("ECONNREFUSED" in str(context.exception)) + with open("unittests/scans/noseyparker/empty_with_error.json") as testfile: + parser = NoseyParkerParser() + findings = parser.get_findings(testfile, Test()) + testfile.close() + self.assertEqual(0, len(findings)) + self.assertTrue( + "Invalid Nosey Parker data, make sure to use Nosey Parker v0.16.0" in str(context.exception) + ) + self.assertTrue("ECONNREFUSED" in str(context.exception)) diff --git a/unittests/tools/test_npm_audit_parser.py b/unittests/tools/test_npm_audit_parser.py index c1c23d306a..c716d53ad9 100644 --- a/unittests/tools/test_npm_audit_parser.py +++ b/unittests/tools/test_npm_audit_parser.py @@ -6,83 +6,77 @@ class TestNpmAuditParser(DojoTestCase): def test_npm_audit_parser_with_no_vuln_has_no_findings(self): - testfile = open(path.join(path.dirname(__file__), "../scans/npm_audit/no_vuln.json")) - parser = NpmAuditParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(0, len(findings)) + with open(path.join(path.dirname(__file__), "../scans/npm_audit/no_vuln.json")) as testfile: + parser = NpmAuditParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_npm_audit_parser_with_one_criticle_vuln_has_one_findings(self): - testfile = open(path.join(path.dirname(__file__), "../scans/npm_audit/one_vuln.json")) - parser = NpmAuditParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1, len(findings)) - self.assertEqual(94, findings[0].cwe) - self.assertEqual("growl", findings[0].component_name) - self.assertEqual("1.9.2", findings[0].component_version) + with open(path.join(path.dirname(__file__), "../scans/npm_audit/one_vuln.json")) as testfile: + parser = NpmAuditParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + self.assertEqual(94, findings[0].cwe) + self.assertEqual("growl", findings[0].component_name) + self.assertEqual("1.9.2", findings[0].component_version) def test_npm_audit_parser_with_many_vuln_has_many_findings(self): - testfile = open(path.join(path.dirname(__file__), "../scans/npm_audit/many_vuln.json")) - parser = NpmAuditParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(5, len(findings)) + with open(path.join(path.dirname(__file__), "../scans/npm_audit/many_vuln.json")) as testfile: + parser = NpmAuditParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(5, len(findings)) - for find in findings: - if find.file_path == "censored_by_npm_audit>send>mime": - self.assertEqual(1, len(find.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2017-16138", find.unsaved_vulnerability_ids[0]) - if find.file_path == "express>fresh": - self.assertEqual(1, len(find.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2017-16119", find.unsaved_vulnerability_ids[0]) - self.assertEqual('mime', findings[4].component_name) - self.assertEqual('1.3.4', findings[4].component_version) + for find in findings: + if find.file_path == "censored_by_npm_audit>send>mime": + self.assertEqual(1, len(find.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2017-16138", find.unsaved_vulnerability_ids[0]) + if find.file_path == "express>fresh": + self.assertEqual(1, len(find.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2017-16119", find.unsaved_vulnerability_ids[0]) + self.assertEqual('mime', findings[4].component_name) + self.assertEqual('1.3.4', findings[4].component_version) def test_npm_audit_parser_multiple_cwes_per_finding(self): # cwes formatted as escaped list: "cwe": "[\"CWE-346\",\"CWE-453\"]", - testfile = open(path.join(path.dirname(__file__), "../scans/npm_audit/multiple_cwes.json")) - parser = NpmAuditParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(41, len(findings)) - self.assertEqual(400, findings[0].cwe) - self.assertEqual(359, findings[12].cwe) + with open(path.join(path.dirname(__file__), "../scans/npm_audit/multiple_cwes.json")) as testfile: + parser = NpmAuditParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(41, len(findings)) + self.assertEqual(400, findings[0].cwe) + self.assertEqual(359, findings[12].cwe) def test_npm_audit_parser_multiple_cwes_per_finding_list(self): # cwes formatted as proper list: "cwe": ["CWE-918","CWE-1333"], - testfile = open(path.join(path.dirname(__file__), "../scans/npm_audit/multiple_cwes2.json")) - parser = NpmAuditParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(6, len(findings)) - self.assertEqual(918, findings[0].cwe) + with open(path.join(path.dirname(__file__), "../scans/npm_audit/multiple_cwes2.json")) as testfile: + parser = NpmAuditParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(6, len(findings)) + self.assertEqual(918, findings[0].cwe) def test_npm_audit_parser_with_one_criticle_vuln_has_null_as_cwe(self): - testfile = open(path.join(path.dirname(__file__), "../scans/npm_audit/cwe_null.json")) - parser = NpmAuditParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1, len(findings)) - self.assertEqual(1035, findings[0].cwe) - self.assertEqual("growl", findings[0].component_name) - self.assertEqual("1.9.2", findings[0].component_version) + with open(path.join(path.dirname(__file__), "../scans/npm_audit/cwe_null.json")) as testfile: + parser = NpmAuditParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + self.assertEqual(1035, findings[0].cwe) + self.assertEqual("growl", findings[0].component_name) + self.assertEqual("1.9.2", findings[0].component_version) def test_npm_audit_parser_empty_with_error(self): with self.assertRaises(ValueError) as context: - testfile = open(path.join(path.dirname(__file__), "../scans/npm_audit/empty_with_error.json")) - parser = NpmAuditParser() - parser.get_findings(testfile, Test()) - testfile.close() + with open(path.join(path.dirname(__file__), "../scans/npm_audit/empty_with_error.json")) as testfile: + parser = NpmAuditParser() + parser.get_findings(testfile, Test()) + self.assertIn("npm audit report contains errors:", str(context.exception)) self.assertIn("ENOAUDIT", str(context.exception)) def test_npm_audit_parser_many_vuln_npm7(self): with self.assertRaises(ValueError) as context: - testfile = open(path.join(path.dirname(__file__), "../scans/npm_audit/many_vuln_npm7.json")) - parser = NpmAuditParser() - parser.get_findings(testfile, Test()) - testfile.close() + with open(path.join(path.dirname(__file__), "../scans/npm_audit/many_vuln_npm7.json")) as testfile: + parser = NpmAuditParser() + parser.get_findings(testfile, Test()) + self.assertIn("npm7 with auditReportVersion 2 or higher not yet supported", str(context.exception)) def test_npm_audit_censored_hash(self): @@ -95,8 +89,7 @@ def test_npm_audit_censored_hash(self): self.assertEqual(censored_path, "censored_by_npm_audit>censored_by_npm_audit>lodash") def test_npm_audit_parser_issue_7897(self): - testfile = open(path.join(path.dirname(__file__), "../scans/npm_audit/issue_7897.json")) - parser = NpmAuditParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(5, len(findings)) + with open(path.join(path.dirname(__file__), "../scans/npm_audit/issue_7897.json")) as testfile: + parser = NpmAuditParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(5, len(findings)) diff --git a/unittests/tools/test_nuclei_parser.py b/unittests/tools/test_nuclei_parser.py index 432960dfb9..3ffdbd2915 100644 --- a/unittests/tools/test_nuclei_parser.py +++ b/unittests/tools/test_nuclei_parser.py @@ -8,233 +8,229 @@ class TestNucleiParser(DojoTestCase): def test_parse_no_empty(self): - testfile = open("unittests/scans/nuclei/empty.jsonl") - parser = NucleiParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/nuclei/empty.jsonl") as testfile: + parser = NucleiParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_no_findings(self): - testfile = open("unittests/scans/nuclei/no_findings.json") - parser = NucleiParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/nuclei/no_findings.json") as testfile: + parser = NucleiParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_issue_9201(self): - testfile = open("unittests/scans/nuclei/issue_9201.json") - parser = NucleiParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual("example.com", finding.unsaved_endpoints[0].host) + with open("unittests/scans/nuclei/issue_9201.json") as testfile: + parser = NucleiParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual("example.com", finding.unsaved_endpoints[0].host) def test_parse_many_findings(self): - testfile = open("unittests/scans/nuclei/many_findings.json") - parser = NucleiParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(16, len(findings)) - - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("OpenSSH 5.3 Detection", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertIn("network", finding.unsaved_tags) - self.assertIn("openssh", finding.unsaved_tags) - self.assertIsNotNone(finding.references) - self.assertEqual("nuclei-example.com", finding.unsaved_endpoints[0].host) - self.assertEqual(22, finding.unsaved_endpoints[0].port) - self.assertEqual("openssh5.3-detect", finding.vuln_id_from_tool) - - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("nginx version detect", finding.title) - self.assertEqual("Info", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertIsNone(finding.unsaved_tags) - self.assertIsNone(finding.references) - self.assertEqual(None, finding.unsaved_endpoints[0].path) - self.assertEqual("nuclei-example.com", finding.unsaved_endpoints[0].host) - self.assertEqual(443, finding.unsaved_endpoints[0].port) - self.assertEqual("nginx-version", finding.vuln_id_from_tool) - - with self.subTest(i=2): - finding = findings[2] - self.assertEqual("phpMyAdmin setup page", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertIsNotNone(finding.references) - self.assertIn("phpmyadmin", finding.unsaved_tags) - self.assertEqual("phpmyadmin/setup/index.php", finding.unsaved_endpoints[0].path) - self.assertEqual("nuclei-example.com", finding.unsaved_endpoints[0].host) - self.assertEqual(443, finding.unsaved_endpoints[0].port) - self.assertEqual("phpmyadmin-setup", finding.vuln_id_from_tool) - - with self.subTest(i=3): - finding = findings[3] - self.assertEqual("Wappalyzer Technology Detection", finding.title) - self.assertEqual("Info", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertIsNone(finding.references) - self.assertIsNone(finding.unsaved_tags) - self.assertEqual("WebGoat", finding.unsaved_endpoints[0].path) - self.assertEqual("127.0.0.1", finding.unsaved_endpoints[0].host) - self.assertEqual(8080, finding.unsaved_endpoints[0].port) - self.assertEqual("tech-detect", finding.vuln_id_from_tool) - - with self.subTest(i=4): - finding = findings[4] - self.assertEqual("Wappalyzer Technology Detection", finding.title) - self.assertEqual("Info", finding.severity) - self.assertEqual(2, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertIsNone(finding.references) - self.assertIsNone(finding.unsaved_tags) - self.assertEqual("WebGoat", finding.unsaved_endpoints[0].path) - self.assertEqual("127.0.0.1", finding.unsaved_endpoints[0].host) - self.assertEqual(8080, finding.unsaved_endpoints[0].port) - self.assertEqual("WebWolf", finding.unsaved_endpoints[1].path) - self.assertEqual("127.0.0.1", finding.unsaved_endpoints[1].host) - self.assertEqual(9090, finding.unsaved_endpoints[1].port) - self.assertEqual("tech-detect", finding.vuln_id_from_tool) - - with self.subTest(i=12): - finding = findings[12] - self.assertEqual("WAF Detection", finding.title) - self.assertEqual("Info", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertIsNone(finding.references) - self.assertIsNone(finding.unsaved_tags) - self.assertEqual(None, finding.unsaved_endpoints[0].path) - self.assertEqual("nuclei-example.com", finding.unsaved_endpoints[0].host) - self.assertEqual(443, finding.unsaved_endpoints[0].port) - self.assertEqual("waf-detect", finding.vuln_id_from_tool) - - with self.subTest(i=14): - finding = findings[14] - self.assertEqual("phpMyAdmin Panel", finding.title) - self.assertEqual("Info", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertIsNone(finding.references) - self.assertIn("panel", finding.unsaved_tags) - self.assertEqual("phpmyadmin/", finding.unsaved_endpoints[0].path) - self.assertEqual("nuclei-example.com", finding.unsaved_endpoints[0].host) - self.assertEqual(443, finding.unsaved_endpoints[0].port) - self.assertEqual("phpmyadmin-panel", finding.vuln_id_from_tool) - - with self.subTest(i=15): - finding = findings[15] - self.assertEqual("MySQL DB with enabled native password", finding.title) - self.assertEqual("Info", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertIsNone(finding.references) - self.assertIn("network", finding.unsaved_tags) - self.assertIn("mysql", finding.unsaved_tags) - self.assertIn("bruteforce", finding.unsaved_tags) - self.assertIn("db", finding.unsaved_tags) - self.assertEqual(None, finding.unsaved_endpoints[0].path) - self.assertEqual("nuclei-example.com", finding.unsaved_endpoints[0].host) - self.assertEqual(3306, finding.unsaved_endpoints[0].port) - self.assertEqual("mysql-native-password-bruteforce", finding.vuln_id_from_tool) + with open("unittests/scans/nuclei/many_findings.json") as testfile: + parser = NucleiParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(16, len(findings)) + + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("OpenSSH 5.3 Detection", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertIn("network", finding.unsaved_tags) + self.assertIn("openssh", finding.unsaved_tags) + self.assertIsNotNone(finding.references) + self.assertEqual("nuclei-example.com", finding.unsaved_endpoints[0].host) + self.assertEqual(22, finding.unsaved_endpoints[0].port) + self.assertEqual("openssh5.3-detect", finding.vuln_id_from_tool) + + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("nginx version detect", finding.title) + self.assertEqual("Info", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertIsNone(finding.unsaved_tags) + self.assertIsNone(finding.references) + self.assertEqual(None, finding.unsaved_endpoints[0].path) + self.assertEqual("nuclei-example.com", finding.unsaved_endpoints[0].host) + self.assertEqual(443, finding.unsaved_endpoints[0].port) + self.assertEqual("nginx-version", finding.vuln_id_from_tool) + + with self.subTest(i=2): + finding = findings[2] + self.assertEqual("phpMyAdmin setup page", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertIsNotNone(finding.references) + self.assertIn("phpmyadmin", finding.unsaved_tags) + self.assertEqual("phpmyadmin/setup/index.php", finding.unsaved_endpoints[0].path) + self.assertEqual("nuclei-example.com", finding.unsaved_endpoints[0].host) + self.assertEqual(443, finding.unsaved_endpoints[0].port) + self.assertEqual("phpmyadmin-setup", finding.vuln_id_from_tool) + + with self.subTest(i=3): + finding = findings[3] + self.assertEqual("Wappalyzer Technology Detection", finding.title) + self.assertEqual("Info", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertIsNone(finding.references) + self.assertIsNone(finding.unsaved_tags) + self.assertEqual("WebGoat", finding.unsaved_endpoints[0].path) + self.assertEqual("127.0.0.1", finding.unsaved_endpoints[0].host) + self.assertEqual(8080, finding.unsaved_endpoints[0].port) + self.assertEqual("tech-detect", finding.vuln_id_from_tool) + + with self.subTest(i=4): + finding = findings[4] + self.assertEqual("Wappalyzer Technology Detection", finding.title) + self.assertEqual("Info", finding.severity) + self.assertEqual(2, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertIsNone(finding.references) + self.assertIsNone(finding.unsaved_tags) + self.assertEqual("WebGoat", finding.unsaved_endpoints[0].path) + self.assertEqual("127.0.0.1", finding.unsaved_endpoints[0].host) + self.assertEqual(8080, finding.unsaved_endpoints[0].port) + self.assertEqual("WebWolf", finding.unsaved_endpoints[1].path) + self.assertEqual("127.0.0.1", finding.unsaved_endpoints[1].host) + self.assertEqual(9090, finding.unsaved_endpoints[1].port) + self.assertEqual("tech-detect", finding.vuln_id_from_tool) + + with self.subTest(i=12): + finding = findings[12] + self.assertEqual("WAF Detection", finding.title) + self.assertEqual("Info", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertIsNone(finding.references) + self.assertIsNone(finding.unsaved_tags) + self.assertEqual(None, finding.unsaved_endpoints[0].path) + self.assertEqual("nuclei-example.com", finding.unsaved_endpoints[0].host) + self.assertEqual(443, finding.unsaved_endpoints[0].port) + self.assertEqual("waf-detect", finding.vuln_id_from_tool) + + with self.subTest(i=14): + finding = findings[14] + self.assertEqual("phpMyAdmin Panel", finding.title) + self.assertEqual("Info", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertIsNone(finding.references) + self.assertIn("panel", finding.unsaved_tags) + self.assertEqual("phpmyadmin/", finding.unsaved_endpoints[0].path) + self.assertEqual("nuclei-example.com", finding.unsaved_endpoints[0].host) + self.assertEqual(443, finding.unsaved_endpoints[0].port) + self.assertEqual("phpmyadmin-panel", finding.vuln_id_from_tool) + + with self.subTest(i=15): + finding = findings[15] + self.assertEqual("MySQL DB with enabled native password", finding.title) + self.assertEqual("Info", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertIsNone(finding.references) + self.assertIn("network", finding.unsaved_tags) + self.assertIn("mysql", finding.unsaved_tags) + self.assertIn("bruteforce", finding.unsaved_tags) + self.assertIn("db", finding.unsaved_tags) + self.assertEqual(None, finding.unsaved_endpoints[0].path) + self.assertEqual("nuclei-example.com", finding.unsaved_endpoints[0].host) + self.assertEqual(3306, finding.unsaved_endpoints[0].port) + self.assertEqual("mysql-native-password-bruteforce", finding.vuln_id_from_tool) def test_parse_many_findings_new(self): - testfile = open("unittests/scans/nuclei/many_findings_new.json") - parser = NucleiParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - - self.assertEqual(2, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("OpenSSH Username Enumeration v7.7", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.description) - self.assertIn("network", finding.unsaved_tags) - self.assertIn("openssh", finding.unsaved_tags) - self.assertIn("cve", finding.unsaved_tags) - self.assertIsNotNone(finding.references) - self.assertEqual("nuclei-example.com", finding.unsaved_endpoints[0].host) - self.assertEqual(22, finding.unsaved_endpoints[0].port) - self.assertEqual("CVE-2018-15473", finding.vuln_id_from_tool) - vulnerability_ids = finding.unsaved_vulnerability_ids - self.assertEqual(1, len(vulnerability_ids)) - self.assertIn('CVE-2018-15473', vulnerability_ids) - self.assertEqual(362, finding.cwe) - self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", finding.cvssv3) - self.assertEqual(5.3, finding.cvssv3_score) - - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("Exposed Prometheus metrics", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(1, finding.nb_occurences) - self.assertEqual('', finding.description) - self.assertIn("config", finding.unsaved_tags) - self.assertIn("exposure", finding.unsaved_tags) - self.assertIn("prometheus", finding.unsaved_tags) - self.assertIsNotNone(finding.references) - self.assertEqual("prometheus-metrics", finding.vuln_id_from_tool) + with open("unittests/scans/nuclei/many_findings_new.json") as testfile: + parser = NucleiParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + + self.assertEqual(2, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("OpenSSH Username Enumeration v7.7", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.description) + self.assertIn("network", finding.unsaved_tags) + self.assertIn("openssh", finding.unsaved_tags) + self.assertIn("cve", finding.unsaved_tags) + self.assertIsNotNone(finding.references) + self.assertEqual("nuclei-example.com", finding.unsaved_endpoints[0].host) + self.assertEqual(22, finding.unsaved_endpoints[0].port) + self.assertEqual("CVE-2018-15473", finding.vuln_id_from_tool) + vulnerability_ids = finding.unsaved_vulnerability_ids + self.assertEqual(1, len(vulnerability_ids)) + self.assertIn('CVE-2018-15473', vulnerability_ids) + self.assertEqual(362, finding.cwe) + self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", finding.cvssv3) + self.assertEqual(5.3, finding.cvssv3_score) + + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("Exposed Prometheus metrics", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(1, finding.nb_occurences) + self.assertEqual('', finding.description) + self.assertIn("config", finding.unsaved_tags) + self.assertIn("exposure", finding.unsaved_tags) + self.assertIn("prometheus", finding.unsaved_tags) + self.assertIsNotNone(finding.references) + self.assertEqual("prometheus-metrics", finding.vuln_id_from_tool) def test_parse_many_findings_third(self): - testfile = open("unittests/scans/nuclei/many_findings_third.json") - parser = NucleiParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - - self.assertEqual(2, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("HTTP Missing Security Headers", finding.title) - self.assertEqual("Info", finding.severity) - self.assertIsNotNone(finding.description) - self.assertIsNotNone(finding.unsaved_request) - self.assertIsNotNone(finding.unsaved_response) - self.assertIsNotNone(finding.steps_to_reproduce) - self.assertEqual(3, len(finding.unsaved_tags)) - self.assertEqual("example.com", finding.unsaved_endpoints[0].host) - self.assertEqual(443, finding.unsaved_endpoints[0].port) - self.assertEqual("http-missing-security-headers", finding.vuln_id_from_tool) - self.assertEqual("x-content-type-options", finding.component_name) - self.assertEqual(finding.date, - datetime(2023, 3, 13, 11, 2, 11, 829446, tzinfo=tzoffset(None, 10800))) - - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("favicon-detection", finding.title) - self.assertEqual("Info", finding.severity) - self.assertIsNotNone(finding.steps_to_reproduce) - self.assertEqual(4, finding.references.count("\n")) - self.assertEqual("favicon-detect", finding.vuln_id_from_tool) - self.assertEqual("asp.net-favicon", finding.component_name) + with open("unittests/scans/nuclei/many_findings_third.json") as testfile: + parser = NucleiParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + + self.assertEqual(2, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("HTTP Missing Security Headers", finding.title) + self.assertEqual("Info", finding.severity) + self.assertIsNotNone(finding.description) + self.assertIsNotNone(finding.unsaved_request) + self.assertIsNotNone(finding.unsaved_response) + self.assertIsNotNone(finding.steps_to_reproduce) + self.assertEqual(3, len(finding.unsaved_tags)) + self.assertEqual("example.com", finding.unsaved_endpoints[0].host) + self.assertEqual(443, finding.unsaved_endpoints[0].port) + self.assertEqual("http-missing-security-headers", finding.vuln_id_from_tool) + self.assertEqual("x-content-type-options", finding.component_name) + self.assertEqual(finding.date, + datetime(2023, 3, 13, 11, 2, 11, 829446, tzinfo=tzoffset(None, 10800))) + + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("favicon-detection", finding.title) + self.assertEqual("Info", finding.severity) + self.assertIsNotNone(finding.steps_to_reproduce) + self.assertEqual(4, finding.references.count("\n")) + self.assertEqual("favicon-detect", finding.vuln_id_from_tool) + self.assertEqual("asp.net-favicon", finding.component_name) def test_parse_many_findings_v3(self): - testfile = open("unittests/scans/nuclei/multiple_v3.json") - parser = NucleiParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(5, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Info", finding.severity) + with open("unittests/scans/nuclei/multiple_v3.json") as testfile: + parser = NucleiParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(5, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Info", finding.severity) diff --git a/unittests/tools/test_pmd_parser.py b/unittests/tools/test_pmd_parser.py index fa1f911a07..75ecb05083 100644 --- a/unittests/tools/test_pmd_parser.py +++ b/unittests/tools/test_pmd_parser.py @@ -6,21 +6,21 @@ class TestPMDParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/pmd/pmd_no_vuln.csv") - parser = PmdParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/pmd/pmd_no_vuln.csv") as testfile: + parser = PmdParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_findings(self): - testfile = open("unittests/scans/pmd/pmd_one_vuln.csv") - parser = PmdParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) + with open("unittests/scans/pmd/pmd_one_vuln.csv") as testfile: + parser = PmdParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) def test_parse_file_with_multiple_vuln_has_multiple_finding(self): - testfile = open("unittests/scans/pmd/pmd_many_vulns.csv") - parser = PmdParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(16, len(findings)) - self.assertEqual("PMD rule UseUtilityClass", findings[0].title) - self.assertEqual("Medium", findings[0].severity) + with open("unittests/scans/pmd/pmd_many_vulns.csv") as testfile: + parser = PmdParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(16, len(findings)) + self.assertEqual("PMD rule UseUtilityClass", findings[0].title) + self.assertEqual("Medium", findings[0].severity) diff --git a/unittests/tools/test_pwn_sast_parser.py b/unittests/tools/test_pwn_sast_parser.py index 4c1a2e2e24..7183169bab 100644 --- a/unittests/tools/test_pwn_sast_parser.py +++ b/unittests/tools/test_pwn_sast_parser.py @@ -6,37 +6,37 @@ class TestPWNSASTParser(DojoTestCase): def test_parse_no_findings(self): - testfile = open("unittests/scans/pwn_sast/no_findings.json") - parser = PWNSASTParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/pwn_sast/no_findings.json") as testfile: + parser = PWNSASTParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_one_finding(self): - testfile = open("unittests/scans/pwn_sast/one_finding.json") - parser = PWNSASTParser() - findings = parser.get_findings(testfile, Test()) - self.assertIsInstance(findings, list) - self.assertEqual(1, len(findings)) + with open("unittests/scans/pwn_sast/one_finding.json") as testfile: + parser = PWNSASTParser() + findings = parser.get_findings(testfile, Test()) + self.assertIsInstance(findings, list) + self.assertEqual(1, len(findings)) def test_parse_many_finding(self): - testfile = open("unittests/scans/pwn_sast/many_findings.json") - parser = PWNSASTParser() - findings = parser.get_findings(testfile, Test()) - self.assertIsInstance(findings, list) - self.assertEqual(3, len(findings)) + with open("unittests/scans/pwn_sast/many_findings.json") as testfile: + parser = PWNSASTParser() + findings = parser.get_findings(testfile, Test()) + self.assertIsInstance(findings, list) + self.assertEqual(3, len(findings)) def test_one_dup_finding(self): - testfile = open("unittests/scans/pwn_sast/one_dup_finding.json") - parser = PWNSASTParser() - findings = parser.get_findings(testfile, Test()) - self.assertIsInstance(findings, list) - self.assertEqual(1, len(findings)) + with open("unittests/scans/pwn_sast/one_dup_finding.json") as testfile: + parser = PWNSASTParser() + findings = parser.get_findings(testfile, Test()) + self.assertIsInstance(findings, list) + self.assertEqual(1, len(findings)) def test_title_is_not_none(self): - testfile = open("unittests/scans/pwn_sast/one_finding.json") - parser = PWNSASTParser() - findings = parser.get_findings(testfile, Test()) - self.assertIsInstance(findings, list) - for finding in findings: - self.assertIsNotNone(finding.title) - self.assertIsNotNone(finding.unique_id_from_tool) + with open("unittests/scans/pwn_sast/one_finding.json") as testfile: + parser = PWNSASTParser() + findings = parser.get_findings(testfile, Test()) + self.assertIsInstance(findings, list) + for finding in findings: + self.assertIsNotNone(finding.title) + self.assertIsNotNone(finding.unique_id_from_tool) diff --git a/unittests/tools/test_qualys_infrascan_webgui_parser.py b/unittests/tools/test_qualys_infrascan_webgui_parser.py index 76a65df234..15dfa12d76 100644 --- a/unittests/tools/test_qualys_infrascan_webgui_parser.py +++ b/unittests/tools/test_qualys_infrascan_webgui_parser.py @@ -11,70 +11,70 @@ class TestQualysInfrascanWebguiParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/qualys_infrascan_webgui/qualys_infrascan_webgui_0.xml" - ) - parser = QualysInfrascanWebguiParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + ) as testfile: + parser = QualysInfrascanWebguiParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) # Sample with One Test # + also verify data with one test def test_parse_file_with_one_vuln_has_one_findings(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/qualys_infrascan_webgui/qualys_infrascan_webgui_1.xml" - ) - parser = QualysInfrascanWebguiParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) + ) as testfile: + parser = QualysInfrascanWebguiParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("Oracle Java SE Critical Patch Update - January 2015", finding.title) - self.assertEqual("Critical", finding.severity) # Negligible is translated to Informational - self.assertEqual(datetime(2019, 4, 2, 10, 14, 53, tzinfo=pytz.utc), finding.date) + finding = findings[0] + self.assertEqual("Oracle Java SE Critical Patch Update - January 2015", finding.title) + self.assertEqual("Critical", finding.severity) # Negligible is translated to Informational + self.assertEqual(datetime(2019, 4, 2, 10, 14, 53, tzinfo=pytz.utc), finding.date) # Sample with Multiple Test def test_parse_file_with_multiple_vuln_has_multiple_findings(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/qualys_infrascan_webgui/qualys_infrascan_webgui_multiple.xml" - ) - parser = QualysInfrascanWebguiParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(6, len(findings)) - # finding 0 - finding = findings[0] - self.assertEqual("UDP Constant IP Identification Field Fingerprinting Vulnerability", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(datetime(2019, 4, 2, 10, 14, 53, tzinfo=pytz.utc), finding.date) - # finding 4 - finding = findings[4] - self.assertEqual("Hidden RPC Services", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(datetime(2019, 4, 2, 10, 14, 53, tzinfo=pytz.utc), finding.date) - self.assertEqual("Some impact\n\n", finding.impact) + ) as testfile: + parser = QualysInfrascanWebguiParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(6, len(findings)) + # finding 0 + finding = findings[0] + self.assertEqual("UDP Constant IP Identification Field Fingerprinting Vulnerability", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(datetime(2019, 4, 2, 10, 14, 53, tzinfo=pytz.utc), finding.date) + # finding 4 + finding = findings[4] + self.assertEqual("Hidden RPC Services", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(datetime(2019, 4, 2, 10, 14, 53, tzinfo=pytz.utc), finding.date) + self.assertEqual("Some impact\n\n", finding.impact) # Sample with Multiple Test def test_parse_file_with_finding_no_dns(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/qualys_infrascan_webgui/qualys_infrascan_webgui_3.xml" - ) - parser = QualysInfrascanWebguiParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - # finding 0 - finding = findings[0] - self.assertEqual("UDP Constant IP Identification Field Fingerprinting Vulnerability", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(datetime(2019, 4, 2, 10, 14, 53, tzinfo=pytz.utc), finding.date) - self.assertEqual(1, len(finding.unsaved_endpoints)) - unsaved_endpoint = finding.unsaved_endpoints[0] - self.assertEqual('10.1.10.1', unsaved_endpoint.host) + ) as testfile: + parser = QualysInfrascanWebguiParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + # finding 0 + finding = findings[0] + self.assertEqual("UDP Constant IP Identification Field Fingerprinting Vulnerability", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(datetime(2019, 4, 2, 10, 14, 53, tzinfo=pytz.utc), finding.date) + self.assertEqual(1, len(finding.unsaved_endpoints)) + unsaved_endpoint = finding.unsaved_endpoints[0] + self.assertEqual('10.1.10.1', unsaved_endpoint.host) diff --git a/unittests/tools/test_qualys_parser.py b/unittests/tools/test_qualys_parser.py index bdce9d3e51..df22041ba1 100644 --- a/unittests/tools/test_qualys_parser.py +++ b/unittests/tools/test_qualys_parser.py @@ -16,12 +16,12 @@ def test_parse_file_with_no_vuln_has_no_findings(self): self.parse_file_with_no_vuln_has_no_findings() def parse_file_with_no_vuln_has_no_findings(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/qualys/empty.xml" - ) - parser = QualysParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + ) as testfile: + parser = QualysParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) @override_settings(USE_FIRST_SEEN=True) def test_parse_file_with_multiple_vuln_has_multiple_findings_first_seen(self): @@ -33,44 +33,44 @@ def test_parse_file_with_multiple_vuln_has_multiple_findings(self): self.assertEqual(datetime.datetime(2019, 7, 31).date(), finding.date) def parse_file_with_multiple_vuln_has_multiple_findings(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/qualys/Qualys_Sample_Report.xml" - ) - parser = QualysParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(301, len(findings)) - - finding = findings[0] - self.assertEqual( - finding.title, "QID-6 | DNS Host Name" - ) - self.assertEqual( - finding.severity, "Informational" - ) - self.assertEqual( - finding.unsaved_endpoints[0].host, "demo13.s02.sjc01.qualys.com" - ) - for finding in findings: - if finding.unsaved_endpoints[0].host == "demo14.s02.sjc01.qualys.com" and finding.title == "QID-370876 | AMD Processors Multiple Security Vulnerabilities (RYZENFALL/MASTERKEY/CHIMERA-FW/FALLOUT)": - finding_cvssv3_score = finding - if finding.unsaved_endpoints[0].host == "demo13.s02.sjc01.qualys.com" and finding.title == "QID-370876 | AMD Processors Multiple Security Vulnerabilities (RYZENFALL/MASTERKEY/CHIMERA-FW/FALLOUT)": - finding_cvssv3_vector = finding - self.assertEqual( - # CVSS_FINAL is defined without a cvssv3 vector - finding_cvssv3_score.cvssv3, None - ) - self.assertEqual( - finding_cvssv3_score.severity, "High" - ) - self.assertEqual(finding_cvssv3_vector.cvssv3, - "CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H") - self.assertEqual( - finding_cvssv3_vector.severity, "Critical" - ) - return finding + ) as testfile: + parser = QualysParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(301, len(findings)) + + finding = findings[0] + self.assertEqual( + finding.title, "QID-6 | DNS Host Name" + ) + self.assertEqual( + finding.severity, "Informational" + ) + self.assertEqual( + finding.unsaved_endpoints[0].host, "demo13.s02.sjc01.qualys.com" + ) + for finding in findings: + if finding.unsaved_endpoints[0].host == "demo14.s02.sjc01.qualys.com" and finding.title == "QID-370876 | AMD Processors Multiple Security Vulnerabilities (RYZENFALL/MASTERKEY/CHIMERA-FW/FALLOUT)": + finding_cvssv3_score = finding + if finding.unsaved_endpoints[0].host == "demo13.s02.sjc01.qualys.com" and finding.title == "QID-370876 | AMD Processors Multiple Security Vulnerabilities (RYZENFALL/MASTERKEY/CHIMERA-FW/FALLOUT)": + finding_cvssv3_vector = finding + self.assertEqual( + # CVSS_FINAL is defined without a cvssv3 vector + finding_cvssv3_score.cvssv3, None + ) + self.assertEqual( + finding_cvssv3_score.severity, "High" + ) + self.assertEqual(finding_cvssv3_vector.cvssv3, + "CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H") + self.assertEqual( + finding_cvssv3_vector.severity, "Critical" + ) + return finding @override_settings(USE_FIRST_SEEN=True) def test_parse_file_with_no_vuln_has_no_findings_csv_first_seen(self): @@ -80,12 +80,12 @@ def test_parse_file_with_no_vuln_has_no_findings_csv(self): self.parse_file_with_no_vuln_has_no_findings_csv() def parse_file_with_no_vuln_has_no_findings_csv(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/qualys/empty.csv" - ) - parser = QualysParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + ) as testfile: + parser = QualysParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) @override_settings(USE_FIRST_SEEN=True) def test_parse_file_with_multiple_vuln_has_multiple_findings_csv_first_seen(self): @@ -97,82 +97,82 @@ def test_parse_file_with_multiple_vuln_has_multiple_findings_csv(self): self.assertEqual(datetime.datetime(2021, 5, 25).date(), finding.date) def parse_file_with_multiple_vuln_has_multiple_findings_csv(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/qualys/Qualys_Sample_Report.csv" - ) - parser = QualysParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(3, len(findings)) - - finding = findings[0] - self.assertEqual( - finding.title, - "QID-105971 | EOL/Obsolete Software: Microsoft ASP.NET 1.0 Detected") - self.assertEqual( - finding.severity, "Critical" - ) - self.assertEqual( - finding.unsaved_endpoints[0].host, "ip-10-98-57-180.eu-west-1.compute.internal" - ) - - for finding in findings: - if finding.unsaved_endpoints[0].host == "ip-10-98-57-180.eu-west-1.compute.internal" and finding.title == "QID-105971 | EOL/Obsolete Software: Microsoft ASP.NET 1.0 Detected": - - self.assertEqual( - finding.severity, "Critical" - ) - self.assertEqual( - finding.cvssv3, - "CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H/E:U/RL:U/RC:C") - self.assertEqual( - finding.severity, "Critical" - ) - - return findings[0] + ) as testfile: + parser = QualysParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(3, len(findings)) + + finding = findings[0] + self.assertEqual( + finding.title, + "QID-105971 | EOL/Obsolete Software: Microsoft ASP.NET 1.0 Detected") + self.assertEqual( + finding.severity, "Critical" + ) + self.assertEqual( + finding.unsaved_endpoints[0].host, "ip-10-98-57-180.eu-west-1.compute.internal" + ) + + for finding in findings: + if finding.unsaved_endpoints[0].host == "ip-10-98-57-180.eu-west-1.compute.internal" and finding.title == "QID-105971 | EOL/Obsolete Software: Microsoft ASP.NET 1.0 Detected": + + self.assertEqual( + finding.severity, "Critical" + ) + self.assertEqual( + finding.cvssv3, + "CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H/E:U/RL:U/RC:C") + self.assertEqual( + finding.severity, "Critical" + ) + + return findings[0] def test_parse_file_monthly_pci_issue6932(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/qualys/monthly_pci_issue6932.csv" - ) - parser = QualysParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) + ) as testfile: + parser = QualysParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) def test_parse_file_with_cvss_values_and_scores(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/qualys/Qualys_Sample_Report.xml" - ) - parser = QualysParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - if finding.unsaved_endpoints[0].host == "demo14.s02.sjc01.qualys.com" and finding.title == "QID-370876 | AMD Processors Multiple Security Vulnerabilities (RYZENFALL/MASTERKEY/CHIMERA-FW/FALLOUT)": - finding_cvssv3_score = finding - if finding.unsaved_endpoints[0].host == "demo13.s02.sjc01.qualys.com" and finding.title == "QID-370876 | AMD Processors Multiple Security Vulnerabilities (RYZENFALL/MASTERKEY/CHIMERA-FW/FALLOUT)": - finding_no_cvssv3_at_detection = finding - if finding.unsaved_endpoints[0].host == "demo14.s02.sjc01.qualys.com" and finding.title == "QID-121695 | NTP \"monlist\" Feature Denial of Service Vulnerability": - finding_no_cvssv3 = finding - # The CVSS Vector is not used from the Knowledgebase - self.assertEqual( - # CVSS_FINAL is defined without a cvssv3 vector - finding_cvssv3_score.cvssv3, None - ) - # Nevertheless the CVSSv3 Score should be set - self.assertEqual( - finding_cvssv3_score.cvssv3_score, 8.2 - ) - # If no cvss information is present in detection and not in knowledgebase values should be empty - self.assertEqual( - finding_no_cvssv3.cvssv3, None - ) - self.assertEqual( - finding_no_cvssv3.cvssv3_score, None - ) - # No CVSS Values available in detection and it uses the knowledgebase then - self.assertEqual(finding_no_cvssv3_at_detection.cvssv3, - "CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H") - self.assertEqual( - finding_no_cvssv3_at_detection.cvssv3_score, 9.0 - ) + ) as testfile: + parser = QualysParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + if finding.unsaved_endpoints[0].host == "demo14.s02.sjc01.qualys.com" and finding.title == "QID-370876 | AMD Processors Multiple Security Vulnerabilities (RYZENFALL/MASTERKEY/CHIMERA-FW/FALLOUT)": + finding_cvssv3_score = finding + if finding.unsaved_endpoints[0].host == "demo13.s02.sjc01.qualys.com" and finding.title == "QID-370876 | AMD Processors Multiple Security Vulnerabilities (RYZENFALL/MASTERKEY/CHIMERA-FW/FALLOUT)": + finding_no_cvssv3_at_detection = finding + if finding.unsaved_endpoints[0].host == "demo14.s02.sjc01.qualys.com" and finding.title == "QID-121695 | NTP \"monlist\" Feature Denial of Service Vulnerability": + finding_no_cvssv3 = finding + # The CVSS Vector is not used from the Knowledgebase + self.assertEqual( + # CVSS_FINAL is defined without a cvssv3 vector + finding_cvssv3_score.cvssv3, None + ) + # Nevertheless the CVSSv3 Score should be set + self.assertEqual( + finding_cvssv3_score.cvssv3_score, 8.2 + ) + # If no cvss information is present in detection and not in knowledgebase values should be empty + self.assertEqual( + finding_no_cvssv3.cvssv3, None + ) + self.assertEqual( + finding_no_cvssv3.cvssv3_score, None + ) + # No CVSS Values available in detection and it uses the knowledgebase then + self.assertEqual(finding_no_cvssv3_at_detection.cvssv3, + "CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H") + self.assertEqual( + finding_no_cvssv3_at_detection.cvssv3_score, 9.0 + ) diff --git a/unittests/tools/test_redhatsatellite_parser.py b/unittests/tools/test_redhatsatellite_parser.py index b1c2771bcf..197dbad657 100644 --- a/unittests/tools/test_redhatsatellite_parser.py +++ b/unittests/tools/test_redhatsatellite_parser.py @@ -6,22 +6,22 @@ class TestRedHatSatelliteParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/redhatsatellite/no_findings.json") - parser = RedHatSatelliteParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/redhatsatellite/no_findings.json") as testfile: + parser = RedHatSatelliteParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_one_finding(self): - testfile = open("unittests/scans/redhatsatellite/one_finding.json") - parser = RedHatSatelliteParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) + with open("unittests/scans/redhatsatellite/one_finding.json") as testfile: + parser = RedHatSatelliteParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) def test_parse_file_with_multiple_findingse(self): - testfile = open("unittests/scans/redhatsatellite/many_findings.json") - parser = RedHatSatelliteParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(3, len(findings)) - self.assertEqual("RHSA-1966:12313", findings[0].unsaved_vulnerability_ids[0]) - self.assertEqual("CVE-1990-1", findings[0].unsaved_vulnerability_ids[1]) - self.assertEqual("CVE-1990-2", findings[0].unsaved_vulnerability_ids[2]) + with open("unittests/scans/redhatsatellite/many_findings.json") as testfile: + parser = RedHatSatelliteParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(3, len(findings)) + self.assertEqual("RHSA-1966:12313", findings[0].unsaved_vulnerability_ids[0]) + self.assertEqual("CVE-1990-1", findings[0].unsaved_vulnerability_ids[1]) + self.assertEqual("CVE-1990-2", findings[0].unsaved_vulnerability_ids[2]) diff --git a/unittests/tools/test_retirejs_parser.py b/unittests/tools/test_retirejs_parser.py index 4961b93bac..eb56ba0648 100644 --- a/unittests/tools/test_retirejs_parser.py +++ b/unittests/tools/test_retirejs_parser.py @@ -5,38 +5,38 @@ class TestRetireJsParser(DojoTestCase): def test_parse(self): - testfile = open("unittests/scans/retirejs/latest.json") - parser = RetireJsParser() - findings = parser.get_findings(testfile, Test()) - self.assertIsInstance(findings, list) - self.assertEqual(23, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual( - "Quoteless attributes in templates can lead to XSS (handlebars, 3.0.0)", - finding.title, - ) - self.assertEqual("Medium", finding.severity) - self.assertEqual("handlebars", finding.component_name) - self.assertEqual("3.0.0", finding.component_version) - self.assertEqual("/home/damien/dd/.venv/report/scout2-report/inc-handlebars/handlebars-v3.0.0.js", finding.file_path) - with self.subTest(i=10): - finding = findings[10] - self.assertEqual( - "XSS in data-container property of tooltip (bootstrap, 3.0.3)", - finding.title, - ) - self.assertEqual("Medium", finding.severity) - self.assertEqual("bootstrap", finding.component_name) - self.assertEqual("3.0.3", finding.component_version) - self.assertEqual("/home/damien/dd/.venv/report/scout2-report/inc-bootstrap/js/bootstrap.min.js", finding.file_path) - with self.subTest(i=22): - finding = findings[22] - self.assertEqual( - "Regex in its jQuery.htmlPrefilter sometimes may introduce XSS (jquery, 1.8.0)", - finding.title, - ) - self.assertEqual("Medium", finding.severity) - self.assertEqual("jquery", finding.component_name) - self.assertEqual("1.8.0", finding.component_version) - self.assertEqual("/home/damien/dd/.venv/lib/python3.9/site-packages/tastypie_swagger/static/tastypie_swagger/js/lib/jquery-1.8.0.min.js", finding.file_path) + with open("unittests/scans/retirejs/latest.json") as testfile: + parser = RetireJsParser() + findings = parser.get_findings(testfile, Test()) + self.assertIsInstance(findings, list) + self.assertEqual(23, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual( + "Quoteless attributes in templates can lead to XSS (handlebars, 3.0.0)", + finding.title, + ) + self.assertEqual("Medium", finding.severity) + self.assertEqual("handlebars", finding.component_name) + self.assertEqual("3.0.0", finding.component_version) + self.assertEqual("/home/damien/dd/.venv/report/scout2-report/inc-handlebars/handlebars-v3.0.0.js", finding.file_path) + with self.subTest(i=10): + finding = findings[10] + self.assertEqual( + "XSS in data-container property of tooltip (bootstrap, 3.0.3)", + finding.title, + ) + self.assertEqual("Medium", finding.severity) + self.assertEqual("bootstrap", finding.component_name) + self.assertEqual("3.0.3", finding.component_version) + self.assertEqual("/home/damien/dd/.venv/report/scout2-report/inc-bootstrap/js/bootstrap.min.js", finding.file_path) + with self.subTest(i=22): + finding = findings[22] + self.assertEqual( + "Regex in its jQuery.htmlPrefilter sometimes may introduce XSS (jquery, 1.8.0)", + finding.title, + ) + self.assertEqual("Medium", finding.severity) + self.assertEqual("jquery", finding.component_name) + self.assertEqual("1.8.0", finding.component_version) + self.assertEqual("/home/damien/dd/.venv/lib/python3.9/site-packages/tastypie_swagger/static/tastypie_swagger/js/lib/jquery-1.8.0.min.js", finding.file_path) diff --git a/unittests/tools/test_risk_recon_parser.py b/unittests/tools/test_risk_recon_parser.py index d2394d1dfa..9c402b98af 100644 --- a/unittests/tools/test_risk_recon_parser.py +++ b/unittests/tools/test_risk_recon_parser.py @@ -8,27 +8,27 @@ class TestRiskReconAPIParser(DojoTestCase): def test_api_with_bad_url(self): - testfile = open("unittests/scans/risk_recon/bad_url.json") - with self.assertRaises(Exception): - parser = RiskReconParser() - parser.get_findings(testfile, Test()) + with open("unittests/scans/risk_recon/bad_url.json") as testfile: + with self.assertRaises(Exception): + parser = RiskReconParser() + parser.get_findings(testfile, Test()) def test_api_with_bad_key(self): - testfile = open("unittests/scans/risk_recon/bad_key.json") - with self.assertRaises(Exception): - parser = RiskReconParser() - parser.get_findings(testfile, Test()) + with open("unittests/scans/risk_recon/bad_key.json") as testfile: + with self.assertRaises(Exception): + parser = RiskReconParser() + parser.get_findings(testfile, Test()) def test_parser_without_api(self): - testfile = open("unittests/scans/risk_recon/findings.json") - parser = RiskReconParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(2, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual(datetime.date(2017, 3, 17), finding.date.date()) - self.assertEqual("ff2bbdbfc2b6fddc061ed96b1fasfwefb", finding.unique_id_from_tool) - with self.subTest(i=1): - finding = findings[1] - self.assertEqual(datetime.date(2017, 3, 17), finding.date.date()) - self.assertEqual("ff2bbdbfc2b6gsrgwergwe6b1fasfwefb", finding.unique_id_from_tool) + with open("unittests/scans/risk_recon/findings.json") as testfile: + parser = RiskReconParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(2, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual(datetime.date(2017, 3, 17), finding.date.date()) + self.assertEqual("ff2bbdbfc2b6fddc061ed96b1fasfwefb", finding.unique_id_from_tool) + with self.subTest(i=1): + finding = findings[1] + self.assertEqual(datetime.date(2017, 3, 17), finding.date.date()) + self.assertEqual("ff2bbdbfc2b6gsrgwergwe6b1fasfwefb", finding.unique_id_from_tool) diff --git a/unittests/tools/test_rusty_hog_parser.py b/unittests/tools/test_rusty_hog_parser.py index 4cf17c7da6..9d73d3e92b 100644 --- a/unittests/tools/test_rusty_hog_parser.py +++ b/unittests/tools/test_rusty_hog_parser.py @@ -5,118 +5,118 @@ class TestRustyhogParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_finding_choctawhog(self): - testfile = open("unittests/scans/rusty_hog/choctawhog_no_vuln.json") - parser = RustyhogParser() - findings = parser.get_items(testfile, "Rusty Hog", Test()) # The outputfile is empty. A subscanner can't be classified - self.assertEqual(0, len(findings)) + with open("unittests/scans/rusty_hog/choctawhog_no_vuln.json") as testfile: + parser = RustyhogParser() + findings = parser.get_items(testfile, "Rusty Hog", Test()) # The outputfile is empty. A subscanner can't be classified + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_finding_choctawhog(self): - testfile = open("unittests/scans/rusty_hog/choctawhog_one_vuln.json") - parser = RustyhogParser() - findings = parser.get_items(testfile, "Choctaw Hog", Test()) - self.assertEqual(1, len(findings)) + with open("unittests/scans/rusty_hog/choctawhog_one_vuln.json") as testfile: + parser = RustyhogParser() + findings = parser.get_items(testfile, "Choctaw Hog", Test()) + self.assertEqual(1, len(findings)) def test_parse_file_with_multiple_vuln_has_multiple_finding_choctawhog(self): - testfile = open("unittests/scans/rusty_hog/choctawhog_many_vulns.json") - parser = RustyhogParser() - findings = parser.get_items(testfile, "Choctaw Hog", Test()) - self.assertEqual(13, len(findings)) + with open("unittests/scans/rusty_hog/choctawhog_many_vulns.json") as testfile: + parser = RustyhogParser() + findings = parser.get_items(testfile, "Choctaw Hog", Test()) + self.assertEqual(13, len(findings)) def test_parse_file_with_multiple_vuln_has_multiple_finding_choctawhog_content(self): - testfile = open("unittests/scans/rusty_hog/choctawhog_many_vulns.json") - parser = RustyhogParser() - findings = parser.get_items(testfile, "Choctaw Hog", Test()) - self.assertEqual(findings[0].title, "Email address found in Git path .github/workflows/main.yml (a7bce96377c4ff2ac16cd51fb0da7fe7ea678829)") - self.assertIn("**This string was found:** ['dojo-helpers@this-repo.com']", findings[0].description) - self.assertIn("**Commit message:** removing action", findings[0].description) - self.assertIn("**Commit hash:** a7bce96377c4ff2ac16cd51fb0da7fe7ea678829", findings[0].description) - self.assertIn("**Parent commit hash:** d8b2f39e826321896a3c7c474fc40dfc0d1fc586", findings[0].description) - self.assertIn("**Old and new file IDs:** 2aba123d6e872777c8cf39ee34664d70e0b90ff0 - 0000000000000000000000000000000000000000", findings[0].description) - self.assertIn("**Date:** 2020-04-15 12:47:20", findings[0].description) - self.assertIn("Please ensure no secret material nor confidential information is kept in clear within git repositories.", findings[0].mitigation) + with open("unittests/scans/rusty_hog/choctawhog_many_vulns.json") as testfile: + parser = RustyhogParser() + findings = parser.get_items(testfile, "Choctaw Hog", Test()) + self.assertEqual(findings[0].title, "Email address found in Git path .github/workflows/main.yml (a7bce96377c4ff2ac16cd51fb0da7fe7ea678829)") + self.assertIn("**This string was found:** ['dojo-helpers@this-repo.com']", findings[0].description) + self.assertIn("**Commit message:** removing action", findings[0].description) + self.assertIn("**Commit hash:** a7bce96377c4ff2ac16cd51fb0da7fe7ea678829", findings[0].description) + self.assertIn("**Parent commit hash:** d8b2f39e826321896a3c7c474fc40dfc0d1fc586", findings[0].description) + self.assertIn("**Old and new file IDs:** 2aba123d6e872777c8cf39ee34664d70e0b90ff0 - 0000000000000000000000000000000000000000", findings[0].description) + self.assertIn("**Date:** 2020-04-15 12:47:20", findings[0].description) + self.assertIn("Please ensure no secret material nor confidential information is kept in clear within git repositories.", findings[0].mitigation) def test_parse_file_with_no_vuln_has_no_finding_duorchog(self): - testfile = open("unittests/scans/rusty_hog/durochog_no_vuln.json") - parser = RustyhogParser() - findings = parser.get_items(testfile, "Rusty Hog", Test()) # The outputfile is empty. A subscanner can't be classified - self.assertEqual(0, len(findings)) + with open("unittests/scans/rusty_hog/durochog_no_vuln.json") as testfile: + parser = RustyhogParser() + findings = parser.get_items(testfile, "Rusty Hog", Test()) # The outputfile is empty. A subscanner can't be classified + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_finding_durochog(self): - testfile = open("unittests/scans/rusty_hog/durochog_one_vuln.json") - parser = RustyhogParser() - findings = parser.get_items(testfile, "Duroc Hog", Test()) - self.assertEqual(1, len(findings)) + with open("unittests/scans/rusty_hog/durochog_one_vuln.json") as testfile: + parser = RustyhogParser() + findings = parser.get_items(testfile, "Duroc Hog", Test()) + self.assertEqual(1, len(findings)) def test_parse_file_with_multiple_vuln_has_multiple_finding_durochog(self): - testfile = open("unittests/scans/rusty_hog/durochog_many_vulns.json") - parser = RustyhogParser() - findings = parser.get_items(testfile, "Duroc Hog", Test()) - self.assertEqual(4, len(findings)) + with open("unittests/scans/rusty_hog/durochog_many_vulns.json") as testfile: + parser = RustyhogParser() + findings = parser.get_items(testfile, "Duroc Hog", Test()) + self.assertEqual(4, len(findings)) def test_parse_file_with_multiple_vuln_has_multiple_finding_durochog_content(self): - testfile = open("unittests/scans/rusty_hog/durochog_many_vulns.json") - parser = RustyhogParser() - findings = parser.get_items(testfile, "Duroc Hog", Test()) - self.assertEqual(findings[0].title, "password (Password) found in path /scan_folder/unittests/scans/sonarqube/sonar-no-finding.html") - self.assertIn("**This string was found:** ['password = getEncryptedPass()']", findings[0].description) - self.assertIn("**Path of Issue:** /scan_folder/unittests/scans/sonarqube/sonar-no-finding.html", findings[0].description) - self.assertIn("**Linenum of Issue:** 7712", findings[0].description) - self.assertIn("**Diff:** $password = getEncryptedPass();", findings[0].description) - self.assertIn("Please ensure no secret material nor confidential information is kept in clear within directories, files, and archives.", findings[0].mitigation) + with open("unittests/scans/rusty_hog/durochog_many_vulns.json") as testfile: + parser = RustyhogParser() + findings = parser.get_items(testfile, "Duroc Hog", Test()) + self.assertEqual(findings[0].title, "password (Password) found in path /scan_folder/unittests/scans/sonarqube/sonar-no-finding.html") + self.assertIn("**This string was found:** ['password = getEncryptedPass()']", findings[0].description) + self.assertIn("**Path of Issue:** /scan_folder/unittests/scans/sonarqube/sonar-no-finding.html", findings[0].description) + self.assertIn("**Linenum of Issue:** 7712", findings[0].description) + self.assertIn("**Diff:** $password = getEncryptedPass();", findings[0].description) + self.assertIn("Please ensure no secret material nor confidential information is kept in clear within directories, files, and archives.", findings[0].mitigation) def test_parse_file_with_no_vuln_has_no_finding_gottingenhog(self): - testfile = open("unittests/scans/rusty_hog/gottingenhog_no_vuln.json") - parser = RustyhogParser() - findings = parser.get_items(testfile, "Rusty Hog", Test()) # The outputfile is empty. A subscanner can't be classified - self.assertEqual(0, len(findings)) + with open("unittests/scans/rusty_hog/gottingenhog_no_vuln.json") as testfile: + parser = RustyhogParser() + findings = parser.get_items(testfile, "Rusty Hog", Test()) # The outputfile is empty. A subscanner can't be classified + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_finding_gottingenhog(self): - testfile = open("unittests/scans/rusty_hog/gottingenhog_one_vuln.json") - parser = RustyhogParser() - findings = parser.get_items(testfile, "Gottingen Hog", Test()) - self.assertEqual(1, len(findings)) + with open("unittests/scans/rusty_hog/gottingenhog_one_vuln.json") as testfile: + parser = RustyhogParser() + findings = parser.get_items(testfile, "Gottingen Hog", Test()) + self.assertEqual(1, len(findings)) def test_parse_file_with_multiple_vuln_has_multiple_finding_gottingenhog(self): - testfile = open("unittests/scans/rusty_hog/gottingenhog_many_vulns.json") - parser = RustyhogParser() - findings = parser.get_items(testfile, "Gottingen Hog", Test()) - self.assertEqual(10, len(findings)) + with open("unittests/scans/rusty_hog/gottingenhog_many_vulns.json") as testfile: + parser = RustyhogParser() + findings = parser.get_items(testfile, "Gottingen Hog", Test()) + self.assertEqual(10, len(findings)) def test_parse_file_with_multiple_vuln_has_multiple_finding_gottingenhog_content(self): - testfile = open("unittests/scans/rusty_hog/gottingenhog_many_vulns.json") - parser = RustyhogParser() - findings = parser.get_items(testfile, "Gottingen Hog", Test()) - self.assertEqual(findings[0].title, "password found in Jira ID TEST-123 (Issue Description)") - self.assertIn("**This string was found:** ['password: jeans']", findings[0].description) - self.assertIn("**JIRA Issue ID:** TEST-123", findings[0].description) - self.assertIn("**JIRA location:** Issue Description", findings[0].description) - self.assertIn("**JIRA url:** [https://jira.com/browse/TEST-123](https://jira.com/browse/TEST-123)", findings[0].description) - self.assertIn("Please ensure no secret material nor confidential information is kept in clear within JIRA Tickets.", findings[0].mitigation) + with open("unittests/scans/rusty_hog/gottingenhog_many_vulns.json") as testfile: + parser = RustyhogParser() + findings = parser.get_items(testfile, "Gottingen Hog", Test()) + self.assertEqual(findings[0].title, "password found in Jira ID TEST-123 (Issue Description)") + self.assertIn("**This string was found:** ['password: jeans']", findings[0].description) + self.assertIn("**JIRA Issue ID:** TEST-123", findings[0].description) + self.assertIn("**JIRA location:** Issue Description", findings[0].description) + self.assertIn("**JIRA url:** [https://jira.com/browse/TEST-123](https://jira.com/browse/TEST-123)", findings[0].description) + self.assertIn("Please ensure no secret material nor confidential information is kept in clear within JIRA Tickets.", findings[0].mitigation) def test_parse_file_with_no_vuln_has_no_finding_essexhog(self): - testfile = open("unittests/scans/rusty_hog/essexhog_no_vuln.json") - parser = RustyhogParser() - findings = parser.get_items(testfile, "Rusty Hog", Test()) # The outputfile is empty. A subscanner can't be classified - self.assertEqual(0, len(findings)) + with open("unittests/scans/rusty_hog/essexhog_no_vuln.json") as testfile: + parser = RustyhogParser() + findings = parser.get_items(testfile, "Rusty Hog", Test()) # The outputfile is empty. A subscanner can't be classified + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_finding_essexhog(self): - testfile = open("unittests/scans/rusty_hog/essexhog_one_vuln.json") - parser = RustyhogParser() - findings = parser.get_items(testfile, "Essex Hog", Test()) - self.assertEqual(1, len(findings)) + with open("unittests/scans/rusty_hog/essexhog_one_vuln.json") as testfile: + parser = RustyhogParser() + findings = parser.get_items(testfile, "Essex Hog", Test()) + self.assertEqual(1, len(findings)) def test_parse_file_with_multiple_vuln_has_multiple_finding_essexhog(self): - testfile = open("unittests/scans/rusty_hog/essexhog_many_vulns.json") - parser = RustyhogParser() - findings = parser.get_items(testfile, "Essex Hog", Test()) - self.assertEqual(3, len(findings)) + with open("unittests/scans/rusty_hog/essexhog_many_vulns.json") as testfile: + parser = RustyhogParser() + findings = parser.get_items(testfile, "Essex Hog", Test()) + self.assertEqual(3, len(findings)) def test_parse_file_with_multiple_vuln_has_multiple_finding_essexhog_content(self): - testfile = open("unittests/scans/rusty_hog/essexhog_many_vulns.json") - parser = RustyhogParser() - findings = parser.get_items(testfile, "Essex Hog", Test()) - self.assertEqual(findings[0].title, "SSH (EC) private key found in Confluence Page ID 12345") - self.assertIn("-----BEGIN EC PRIVATE KEY-----", findings[0].description) - self.assertIn("**Confluence URL:** [https://confluence.com/pages/viewpage.action?pageId=12345](https://confluence.com/pages/viewpage.action?pageId=12345)", findings[0].description) - self.assertIn("**Confluence Page ID:** 12345", findings[0].description) - self.assertIn("Please ensure no secret material nor confidential information is kept in clear within Confluence Pages.", findings[0].mitigation) + with open("unittests/scans/rusty_hog/essexhog_many_vulns.json") as testfile: + parser = RustyhogParser() + findings = parser.get_items(testfile, "Essex Hog", Test()) + self.assertEqual(findings[0].title, "SSH (EC) private key found in Confluence Page ID 12345") + self.assertIn("-----BEGIN EC PRIVATE KEY-----", findings[0].description) + self.assertIn("**Confluence URL:** [https://confluence.com/pages/viewpage.action?pageId=12345](https://confluence.com/pages/viewpage.action?pageId=12345)", findings[0].description) + self.assertIn("**Confluence Page ID:** 12345", findings[0].description) + self.assertIn("Please ensure no secret material nor confidential information is kept in clear within Confluence Pages.", findings[0].mitigation) diff --git a/unittests/tools/test_sarif_parser.py b/unittests/tools/test_sarif_parser.py index 8902f84630..b4ceb56927 100644 --- a/unittests/tools/test_sarif_parser.py +++ b/unittests/tools/test_sarif_parser.py @@ -17,40 +17,40 @@ def common_checks(self, finding): self.assertEqual(False, finding.dynamic_finding) # by specification def test_example_report(self): - testfile = open( + with open( path.join( get_unit_tests_path() + "/scans/sarif/DefectDojo_django-DefectDojo__2020-12-11_13 42 10__export.sarif" ) - ) - parser = SarifParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(510, len(findings)) - for finding in findings: - self.common_checks(finding) + )as testfile: + parser = SarifParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(510, len(findings)) + for finding in findings: + self.common_checks(finding) def test_suppression_report(self): """test report file having different suppression definitions""" - testfile = open(path.join(path.dirname(__file__), "../scans/sarif/suppression_test.sarif")) - parser = SarifParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - if finding.title == "Suppressed": - self.assertEqual(True, finding.false_p) - self.assertEqual(False, finding.active) - else: - self.assertEqual(False, finding.false_p) - self.assertEqual(True, finding.active) + with open(path.join(path.dirname(__file__), "../scans/sarif/suppression_test.sarif")) as testfile: + parser = SarifParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + if finding.title == "Suppressed": + self.assertEqual(True, finding.false_p) + self.assertEqual(False, finding.active) + else: + self.assertEqual(False, finding.false_p) + self.assertEqual(True, finding.active) def test_example2_report(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sarif/appendix_k.sarif")) - parser = SarifParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - item = findings[0] - self.assertEqual("collections/list.h", item.file_path) - self.assertEqual(15, item.line) - self.assertEqual("High", item.severity) - description = """**Result message:** Variable "ptr" was used without being initialized. It was declared [here](0). + with open(path.join(path.dirname(__file__), "../scans/sarif/appendix_k.sarif")) as testfile: + parser = SarifParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + item = findings[0] + self.assertEqual("collections/list.h", item.file_path) + self.assertEqual(15, item.line) + self.assertEqual("High", item.severity) + description = """**Result message:** Variable "ptr" was used without being initialized. It was declared [here](0). **Snippet:** ```add_core(ptr, offset, val); return;``` @@ -62,463 +62,463 @@ def test_example2_report(self): 2. collections/list.h:L15\t-\toffset = (y + z) * q + 1; 3. collections/list.h:L25\t-\tadd_core(ptr, offset, val) \tUninitialized variable `ptr` passed to method `add_core`.""" - self.assertEqual(description, item.description) - self.assertEqual(datetime.datetime(2016, 7, 16, 14, 19, 1, tzinfo=datetime.timezone.utc), item.date) - for finding in findings: - self.common_checks(finding) + self.assertEqual(description, item.description) + self.assertEqual(datetime.datetime(2016, 7, 16, 14, 19, 1, tzinfo=datetime.timezone.utc), item.date) + for finding in findings: + self.common_checks(finding) def test_example_k1_report(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sarif/appendix_k1.sarif")) - parser = SarifParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open(path.join(path.dirname(__file__), "../scans/sarif/appendix_k1.sarif")) as testfile: + parser = SarifParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_example_k2_report(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sarif/appendix_k2.sarif")) - parser = SarifParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - item = findings[0] - self.assertEqual('Variable "count" was used without being initialized.', item.title) - self.assertEqual("src/collections/list.cpp", item.file_path) - self.assertEqual(15, item.line) - description = """**Result message:** Variable "count" was used without being initialized. + with open(path.join(path.dirname(__file__), "../scans/sarif/appendix_k2.sarif")) as testfile: + parser = SarifParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + item = findings[0] + self.assertEqual('Variable "count" was used without being initialized.', item.title) + self.assertEqual("src/collections/list.cpp", item.file_path) + self.assertEqual(15, item.line) + description = """**Result message:** Variable "count" was used without being initialized. **Rule full description:** A variable was used without being initialized. This can result in runtime errors such as null reference exceptions.""" - self.assertEqual(description, item.description) - for finding in findings: - self.common_checks(finding) + self.assertEqual(description, item.description) + for finding in findings: + self.common_checks(finding) def test_example_k3_report(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sarif/appendix_k3.sarif")) - parser = SarifParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - item = findings[0] - self.assertEqual('The insecure method "Crypto.Sha1.Encrypt" should not be used.', item.title) - for finding in findings: - self.common_checks(finding) + with open(path.join(path.dirname(__file__), "../scans/sarif/appendix_k3.sarif")) as testfile: + parser = SarifParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + item = findings[0] + self.assertEqual('The insecure method "Crypto.Sha1.Encrypt" should not be used.', item.title) + for finding in findings: + self.common_checks(finding) def test_example_k4_report_mitigation(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sarif/appendix_k4.sarif")) - parser = SarifParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - for finding in findings: - self.common_checks(finding) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual( - 'Variable "ptr" was used without being initialized. It was declared [here](0).', finding.title - ) - self.assertEqual("C2001", finding.vuln_id_from_tool) - self.assertEqual("collections/list.h", finding.file_path) - self.assertEqual("Initialize the variable to null", finding.mitigation) + with open(path.join(path.dirname(__file__), "../scans/sarif/appendix_k4.sarif")) as testfile: + parser = SarifParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + for finding in findings: + self.common_checks(finding) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual( + 'Variable "ptr" was used without being initialized. It was declared [here](0).', finding.title + ) + self.assertEqual("C2001", finding.vuln_id_from_tool) + self.assertEqual("collections/list.h", finding.file_path) + self.assertEqual("Initialize the variable to null", finding.mitigation) def test_example_report_ms(self): """Report file come from Microsoft SARIF sdk on GitHub""" - testfile = open(path.join(path.dirname(__file__), "../scans/sarif/SuppressionTestCurrent.sarif")) - parser = SarifParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(4, len(findings)) - item = findings[0] - self.assertEqual("New suppressed result.", item.title) - for finding in findings: - self.common_checks(finding) + with open(path.join(path.dirname(__file__), "../scans/sarif/SuppressionTestCurrent.sarif")) as testfile: + parser = SarifParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(4, len(findings)) + item = findings[0] + self.assertEqual("New suppressed result.", item.title) + for finding in findings: + self.common_checks(finding) def test_example_report_semgrep(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sarif/semgrepowasp-benchmark-sample.sarif")) - test = Test() - parser = SarifParser() - findings = parser.get_findings(testfile, test) - self.assertEqual(1768, len(findings)) - item = findings[0] - self.assertEqual( - "src/main/java/org/owasp/benchmark/testcode/BenchmarkTest02660.java", - item.file_path, - ) - for finding in findings: - self.common_checks(finding) - - def test_example_report_scanlift_dependency_check(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sarif/dependency_check.sarif")) - parser = SarifParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(13, len(findings)) - # finding 0 - item = findings[0] - self.assertEqual( - "file:////src/.venv/lib/python3.9/site-packages/tastypie_swagger/static/tastypie_swagger/js/lib/handlebars-1.0.0.js", - item.file_path, - ) - # finding 6 - item = findings[6] - self.assertEqual( - "CVE-2019-11358 - jQuery before 3.4.0, as used in Drupal, Backdrop CMS, and other products, mishandles jQuery.extend(true, {}, ...) because of [...]", - item.title, - ) - self.assertEqual("High", item.severity) - self.assertEqual(1, len(item.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2019-11358", item.unsaved_vulnerability_ids[0]) - for finding in findings: - self.common_checks(finding) - - def test_example_report_scanlift_bash(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sarif/bash-report.sarif")) - parser = SarifParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(27, len(findings)) - # finding 0 - item = findings[0] - self.assertEqual( - "file:///home/damien/dd/docker/setEnv.sh", - item.file_path, - ) - self.assertIsNone(item.unsaved_vulnerability_ids) - self.assertEqual(datetime.datetime(2021, 3, 8, 15, 39, 40, tzinfo=datetime.timezone.utc), item.date) - # finding 6 - with self.subTest(i=6): - finding = findings[6] - self.assertEqual( - "Decimals are not supported. Either use integers only, or use bc or awk to compare.", - finding.title, - ) - self.assertEqual("Info", finding.severity) - self.assertIsNone(finding.unsaved_vulnerability_ids) - self.assertEqual( - "scanFileHash:5b05533780915bfc|scanPrimaryLocationHash:4d655189c485c086", - finding.unique_id_from_tool, - ) - for finding in findings: - self.common_checks(finding) - - def test_example_report_taint_python(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sarif/taint-python-report.sarif")) - parser = SarifParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(11, len(findings)) - for finding in findings: - self.common_checks(finding) - # finding 0 - with self.subTest(i=0): + with open(path.join(path.dirname(__file__), "../scans/sarif/semgrepowasp-benchmark-sample.sarif")) as testfile: + test = Test() + parser = SarifParser() + findings = parser.get_findings(testfile, test) + self.assertEqual(1768, len(findings)) item = findings[0] self.assertEqual( - "file:///home/damien/dd/dojo/tools/veracode/parser.py", + "src/main/java/org/owasp/benchmark/testcode/BenchmarkTest02660.java", item.file_path, ) - self.assertIsNone(item.unsaved_vulnerability_ids) - self.assertEqual(datetime.datetime(2021, 3, 8, 15, 46, 16, tzinfo=datetime.timezone.utc), item.date) - self.assertEqual( - "scanFileHash:4bc9f13947613303|scanPrimaryLocationHash:1a8bbb28fe7380df|scanTagsHash:21de8f8d0eb8d9b2", - finding.unique_id_from_tool, - ) - # finding 2 - with self.subTest(i=2): - item = findings[2] + for finding in findings: + self.common_checks(finding) + + def test_example_report_scanlift_dependency_check(self): + with open(path.join(path.dirname(__file__), "../scans/sarif/dependency_check.sarif")) as testfile: + parser = SarifParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(13, len(findings)) + # finding 0 + item = findings[0] self.assertEqual( - "file:///home/damien/dd/dojo/tools/qualys_infrascan_webgui/parser.py", + "file:////src/.venv/lib/python3.9/site-packages/tastypie_swagger/static/tastypie_swagger/js/lib/handlebars-1.0.0.js", item.file_path, ) - self.assertEqual(169, item.line) # finding 6 item = findings[6] self.assertEqual( - "XML injection with user data from `filename in parser_helper.py:167` is used for parsing XML at `parser_helper.py:23`.", + "CVE-2019-11358 - jQuery before 3.4.0, as used in Drupal, Backdrop CMS, and other products, mishandles jQuery.extend(true, {}, ...) because of [...]", item.title, ) self.assertEqual("High", item.severity) - self.assertIsNone(item.unsaved_vulnerability_ids) + self.assertEqual(1, len(item.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2019-11358", item.unsaved_vulnerability_ids[0]) + for finding in findings: + self.common_checks(finding) + + def test_example_report_scanlift_bash(self): + with open(path.join(path.dirname(__file__), "../scans/sarif/bash-report.sarif")) as testfile: + parser = SarifParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(27, len(findings)) + # finding 0 + item = findings[0] self.assertEqual( - "scanFileHash:4bc9f13947613303|scanPrimaryLocationHash:1a8bbb28fe7380df|scanTagsHash:21de8f8d0eb8d9b2", - finding.unique_id_from_tool, + "file:///home/damien/dd/docker/setEnv.sh", + item.file_path, ) + self.assertIsNone(item.unsaved_vulnerability_ids) + self.assertEqual(datetime.datetime(2021, 3, 8, 15, 39, 40, tzinfo=datetime.timezone.utc), item.date) + # finding 6 + with self.subTest(i=6): + finding = findings[6] + self.assertEqual( + "Decimals are not supported. Either use integers only, or use bc or awk to compare.", + finding.title, + ) + self.assertEqual("Info", finding.severity) + self.assertIsNone(finding.unsaved_vulnerability_ids) + self.assertEqual( + "scanFileHash:5b05533780915bfc|scanPrimaryLocationHash:4d655189c485c086", + finding.unique_id_from_tool, + ) + for finding in findings: + self.common_checks(finding) + + def test_example_report_taint_python(self): + with open(path.join(path.dirname(__file__), "../scans/sarif/taint-python-report.sarif")) as testfile: + parser = SarifParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(11, len(findings)) + for finding in findings: + self.common_checks(finding) + # finding 0 + with self.subTest(i=0): + item = findings[0] + self.assertEqual( + "file:///home/damien/dd/dojo/tools/veracode/parser.py", + item.file_path, + ) + self.assertIsNone(item.unsaved_vulnerability_ids) + self.assertEqual(datetime.datetime(2021, 3, 8, 15, 46, 16, tzinfo=datetime.timezone.utc), item.date) + self.assertEqual( + "scanFileHash:4bc9f13947613303|scanPrimaryLocationHash:1a8bbb28fe7380df|scanTagsHash:21de8f8d0eb8d9b2", + finding.unique_id_from_tool, + ) + # finding 2 + with self.subTest(i=2): + item = findings[2] + self.assertEqual( + "file:///home/damien/dd/dojo/tools/qualys_infrascan_webgui/parser.py", + item.file_path, + ) + self.assertEqual(169, item.line) + # finding 6 + item = findings[6] + self.assertEqual( + "XML injection with user data from `filename in parser_helper.py:167` is used for parsing XML at `parser_helper.py:23`.", + item.title, + ) + self.assertEqual("High", item.severity) + self.assertIsNone(item.unsaved_vulnerability_ids) + self.assertEqual( + "scanFileHash:4bc9f13947613303|scanPrimaryLocationHash:1a8bbb28fe7380df|scanTagsHash:21de8f8d0eb8d9b2", + finding.unique_id_from_tool, + ) def test_njsscan(self): """Generated with opensecurity/njsscan (https://github.com/ajinabraham/njsscan)""" - testfile = open(path.join(path.dirname(__file__), "../scans/sarif/njsscan.sarif")) - parser = SarifParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(2, len(findings)) - # finding 0 - finding = findings[0] - self.assertEqual( - "file:///src/index.js", - finding.file_path, - ) - self.assertIsNone(finding.unsaved_vulnerability_ids) - self.assertEqual(datetime.datetime(2021, 3, 23, 0, 10, 48, tzinfo=datetime.timezone.utc), finding.date) - self.assertEqual(327, finding.cwe) - # finding 1 - finding = findings[1] - self.assertEqual( - "file:///src/index.js", - finding.file_path, - ) - self.assertEqual(235, finding.line) - self.assertEqual(datetime.datetime(2021, 3, 23, 0, 10, 48, tzinfo=datetime.timezone.utc), finding.date) - self.assertEqual(798, finding.cwe) - for finding in findings: - self.common_checks(finding) - - def test_dockle(self): - """Generated with goodwithtech/dockle (https://github.com/goodwithtech/dockle)""" - testfile = open(path.join(path.dirname(__file__), "../scans/sarif/dockle_0_3_15.sarif")) - parser = SarifParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(4, len(findings)) - for finding in findings: - self.common_checks(finding) - with self.subTest(i=0): + with open(path.join(path.dirname(__file__), "../scans/sarif/njsscan.sarif")) as testfile: + parser = SarifParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(2, len(findings)) + # finding 0 finding = findings[0] - self.assertEqual("CIS-DI-0010", finding.vuln_id_from_tool) - self.assertEqual("High", finding.severity) - description = """**Result message:** Suspicious ENV key found : DD_ADMIN_PASSWORD, Suspicious ENV key found : DD_CELERY_BROKER_PASSWORD, Suspicious ENV key found : DD_DATABASE_PASSWORD -**Rule short description:** Do not store credential in ENVIRONMENT vars/files""" - self.assertEqual(description, finding.description) self.assertEqual( - "https://github.com/goodwithtech/dockle/blob/master/CHECKPOINT.md#CIS-DI-0010", finding.references + "file:///src/index.js", + finding.file_path, ) - with self.subTest(i=1): + self.assertIsNone(finding.unsaved_vulnerability_ids) + self.assertEqual(datetime.datetime(2021, 3, 23, 0, 10, 48, tzinfo=datetime.timezone.utc), finding.date) + self.assertEqual(327, finding.cwe) + # finding 1 finding = findings[1] - self.assertEqual("CIS-DI-0005", finding.vuln_id_from_tool) - self.assertEqual("Info", finding.severity) - description = """**Result message:** export DOCKER_CONTENT_TRUST=1 before docker pull/build -**Rule short description:** Enable Content trust for Docker""" - self.assertEqual(description, finding.description) self.assertEqual( - "https://github.com/goodwithtech/dockle/blob/master/CHECKPOINT.md#CIS-DI-0005", finding.references + "file:///src/index.js", + finding.file_path, ) - with self.subTest(i=2): - finding = findings[2] - self.assertEqual("CIS-DI-0006", finding.vuln_id_from_tool) - self.assertEqual("Info", finding.severity) - description = """**Result message:** not found HEALTHCHECK statement + self.assertEqual(235, finding.line) + self.assertEqual(datetime.datetime(2021, 3, 23, 0, 10, 48, tzinfo=datetime.timezone.utc), finding.date) + self.assertEqual(798, finding.cwe) + for finding in findings: + self.common_checks(finding) + + def test_dockle(self): + """Generated with goodwithtech/dockle (https://github.com/goodwithtech/dockle)""" + with open(path.join(path.dirname(__file__), "../scans/sarif/dockle_0_3_15.sarif")) as testfile: + parser = SarifParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(4, len(findings)) + for finding in findings: + self.common_checks(finding) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("CIS-DI-0010", finding.vuln_id_from_tool) + self.assertEqual("High", finding.severity) + description = """**Result message:** Suspicious ENV key found : DD_ADMIN_PASSWORD, Suspicious ENV key found : DD_CELERY_BROKER_PASSWORD, Suspicious ENV key found : DD_DATABASE_PASSWORD +**Rule short description:** Do not store credential in ENVIRONMENT vars/files""" + self.assertEqual(description, finding.description) + self.assertEqual( + "https://github.com/goodwithtech/dockle/blob/master/CHECKPOINT.md#CIS-DI-0010", finding.references + ) + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("CIS-DI-0005", finding.vuln_id_from_tool) + self.assertEqual("Info", finding.severity) + description = """**Result message:** export DOCKER_CONTENT_TRUST=1 before docker pull/build +**Rule short description:** Enable Content trust for Docker""" + self.assertEqual(description, finding.description) + self.assertEqual( + "https://github.com/goodwithtech/dockle/blob/master/CHECKPOINT.md#CIS-DI-0005", finding.references + ) + with self.subTest(i=2): + finding = findings[2] + self.assertEqual("CIS-DI-0006", finding.vuln_id_from_tool) + self.assertEqual("Info", finding.severity) + description = """**Result message:** not found HEALTHCHECK statement **Rule short description:** Add HEALTHCHECK instruction to the container image""" - self.assertEqual(description, finding.description) - self.assertEqual( - "https://github.com/goodwithtech/dockle/blob/master/CHECKPOINT.md#CIS-DI-0006", finding.references - ) - with self.subTest(i=3): - finding = findings[3] - self.assertEqual("CIS-DI-0008", finding.vuln_id_from_tool) - self.assertEqual("Info", finding.severity) - description = """**Result message:** setuid file: urwxr-xr-x usr/bin/chfn, setuid file: urwxr-xr-x usr/bin/chsh, setuid file: urwxr-xr-x usr/bin/passwd, setuid file: urwxr-xr-x bin/umount, setuid file: urwxr-xr-x bin/mount, setgid file: grwxr-xr-x usr/bin/wall, setgid file: grwxr-xr-x usr/bin/expiry, setuid file: urwxr-xr-x bin/su, setgid file: grwxr-xr-x sbin/unix_chkpwd, setuid file: urwxr-xr-x usr/bin/gpasswd, setgid file: grwxr-xr-x usr/bin/chage, setuid file: urwxr-xr-x usr/bin/newgrp + self.assertEqual(description, finding.description) + self.assertEqual( + "https://github.com/goodwithtech/dockle/blob/master/CHECKPOINT.md#CIS-DI-0006", finding.references + ) + with self.subTest(i=3): + finding = findings[3] + self.assertEqual("CIS-DI-0008", finding.vuln_id_from_tool) + self.assertEqual("Info", finding.severity) + description = """**Result message:** setuid file: urwxr-xr-x usr/bin/chfn, setuid file: urwxr-xr-x usr/bin/chsh, setuid file: urwxr-xr-x usr/bin/passwd, setuid file: urwxr-xr-x bin/umount, setuid file: urwxr-xr-x bin/mount, setgid file: grwxr-xr-x usr/bin/wall, setgid file: grwxr-xr-x usr/bin/expiry, setuid file: urwxr-xr-x bin/su, setgid file: grwxr-xr-x sbin/unix_chkpwd, setuid file: urwxr-xr-x usr/bin/gpasswd, setgid file: grwxr-xr-x usr/bin/chage, setuid file: urwxr-xr-x usr/bin/newgrp **Rule short description:** Confirm safety of setuid/setgid files""" - self.assertEqual(description, finding.description) - self.assertEqual( - "https://github.com/goodwithtech/dockle/blob/master/CHECKPOINT.md#CIS-DI-0008", finding.references - ) + self.assertEqual(description, finding.description) + self.assertEqual( + "https://github.com/goodwithtech/dockle/blob/master/CHECKPOINT.md#CIS-DI-0008", finding.references + ) def test_mobsfscan(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sarif/mobsfscan.json")) - parser = SarifParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(9, len(findings)) - for finding in findings: - self.common_checks(finding) + with open(path.join(path.dirname(__file__), "../scans/sarif/mobsfscan.json")) as testfile: + parser = SarifParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(9, len(findings)) + for finding in findings: + self.common_checks(finding) def test_gitleaks(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sarif/gitleaks_7.5.0.sarif")) - parser = SarifParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(8, len(findings)) - for finding in findings: - self.common_checks(finding) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("AWS Access Key secret detected", finding.title) - self.assertEqual("Medium", finding.severity) - description = """**Result message:** AWS Access Key secret detected + with open(path.join(path.dirname(__file__), "../scans/sarif/gitleaks_7.5.0.sarif")) as testfile: + parser = SarifParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(8, len(findings)) + for finding in findings: + self.common_checks(finding) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("AWS Access Key secret detected", finding.title) + self.assertEqual("Medium", finding.severity) + description = """**Result message:** AWS Access Key secret detected **Snippet:** ``` \"raw_source_code_extract\": \"AKIAIOSFODNN7EXAMPLE\",```""" - self.assertEqual(description, finding.description) - self.assertEqual( - "dojo/unittests/scans/gitlab_secret_detection_report/gitlab_secret_detection_report_1_vuln.json", - finding.file_path, - ) - self.assertEqual(13, finding.line) - with self.subTest(i=3): - finding = findings[3] - self.assertEqual("AWS Access Key secret detected", finding.title) - self.assertEqual("Medium", finding.severity) - description = """**Result message:** AWS Access Key secret detected + self.assertEqual(description, finding.description) + self.assertEqual( + "dojo/unittests/scans/gitlab_secret_detection_report/gitlab_secret_detection_report_1_vuln.json", + finding.file_path, + ) + self.assertEqual(13, finding.line) + with self.subTest(i=3): + finding = findings[3] + self.assertEqual("AWS Access Key secret detected", finding.title) + self.assertEqual("Medium", finding.severity) + description = """**Result message:** AWS Access Key secret detected **Snippet:** ``` \"raw_source_code_extract\": \"AKIAIOSFODNN7EXAMPLE\",```""" - self.assertEqual(description, finding.description) - self.assertEqual( - "dojo/unittests/scans/gitlab_secret_detection_report/gitlab_secret_detection_report_3_vuln.json", - finding.file_path, - ) - self.assertEqual(44, finding.line) - with self.subTest(i=7): - finding = findings[7] - self.assertEqual("AWS Access Key secret detected", finding.title) - self.assertEqual("Medium", finding.severity) - description = """**Result message:** AWS Access Key secret detected + self.assertEqual(description, finding.description) + self.assertEqual( + "dojo/unittests/scans/gitlab_secret_detection_report/gitlab_secret_detection_report_3_vuln.json", + finding.file_path, + ) + self.assertEqual(44, finding.line) + with self.subTest(i=7): + finding = findings[7] + self.assertEqual("AWS Access Key secret detected", finding.title) + self.assertEqual("Medium", finding.severity) + description = """**Result message:** AWS Access Key secret detected **Snippet:** ``` self.assertEqual(\"AWS\\nAKIAIOSFODNN7EXAMPLE\", first_finding.description)```""" - self.assertEqual(description, finding.description) - self.assertEqual("dojo/unittests/tools/test_gitlab_secret_detection_report_parser.py", finding.file_path) - self.assertEqual(37, finding.line) + self.assertEqual(description, finding.description) + self.assertEqual("dojo/unittests/tools/test_gitlab_secret_detection_report_parser.py", finding.file_path) + self.assertEqual(37, finding.line) def test_flawfinder(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sarif/flawfinder.sarif")) - parser = SarifParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(53, len(findings)) - for finding in findings: - self.common_checks(finding) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual( - "random/setstate:This function is not sufficiently random for security-related functions such as key and nonce creation (CWE-327).", - finding.title, - ) - self.assertEqual("High", finding.severity) - description = """**Result message:** random/setstate:This function is not sufficiently random for security-related functions such as key and nonce creation (CWE-327). + with open(path.join(path.dirname(__file__), "../scans/sarif/flawfinder.sarif")) as testfile: + parser = SarifParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(53, len(findings)) + for finding in findings: + self.common_checks(finding) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual( + "random/setstate:This function is not sufficiently random for security-related functions such as key and nonce creation (CWE-327).", + finding.title, + ) + self.assertEqual("High", finding.severity) + description = """**Result message:** random/setstate:This function is not sufficiently random for security-related functions such as key and nonce creation (CWE-327). **Snippet:** ``` is.setstate(std::ios::failbit);``` **Rule name:** random/setstate **Rule short description:** This function is not sufficiently random for security-related functions such as key and nonce creation (CWE-327).""" - self.assertEqual(description, finding.description) - self.assertEqual("src/tree/param.cc", finding.file_path) - self.assertEqual(29, finding.line) - self.assertEqual(327, finding.cwe) - self.assertEqual("FF1048", finding.vuln_id_from_tool) - self.assertEqual( - "e6c1ad2b1d96ffc4035ed8df070600566ad240b8ded025dac30620f3fd4aa9fd", finding.unique_id_from_tool - ) - self.assertEqual("https://cwe.mitre.org/data/definitions/327.html", finding.references) - with self.subTest(i=20): - finding = findings[20] - self.assertEqual( - "buffer/memcpy:Does not check for buffer overflows when copying to destination (CWE-120).", - finding.title, - ) - self.assertEqual("Info", finding.severity) - description = """**Result message:** buffer/memcpy:Does not check for buffer overflows when copying to destination (CWE-120). + self.assertEqual(description, finding.description) + self.assertEqual("src/tree/param.cc", finding.file_path) + self.assertEqual(29, finding.line) + self.assertEqual(327, finding.cwe) + self.assertEqual("FF1048", finding.vuln_id_from_tool) + self.assertEqual( + "e6c1ad2b1d96ffc4035ed8df070600566ad240b8ded025dac30620f3fd4aa9fd", finding.unique_id_from_tool + ) + self.assertEqual("https://cwe.mitre.org/data/definitions/327.html", finding.references) + with self.subTest(i=20): + finding = findings[20] + self.assertEqual( + "buffer/memcpy:Does not check for buffer overflows when copying to destination (CWE-120).", + finding.title, + ) + self.assertEqual("Info", finding.severity) + description = """**Result message:** buffer/memcpy:Does not check for buffer overflows when copying to destination (CWE-120). **Snippet:** ``` std::memcpy(dptr, dmlc::BeginPtr(buffer_) + buffer_ptr_, size);``` **Rule name:** buffer/memcpy **Rule short description:** Does not check for buffer overflows when copying to destination (CWE-120).""" - self.assertEqual(description, finding.description) - self.assertEqual("src/common/io.cc", finding.file_path) - self.assertEqual(31, finding.line) - self.assertEqual(120, finding.cwe) - self.assertEqual("FF1004", finding.vuln_id_from_tool) - self.assertEqual( - "327fc54b75ab37bbbb31a1b71431aaefa8137ff755acc103685ad5adf88f5dda", finding.unique_id_from_tool - ) - self.assertEqual("https://cwe.mitre.org/data/definitions/120.html", finding.references) - with self.subTest(i=52): - finding = findings[52] - self.assertEqual( - "buffer/sscanf:The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20).", - finding.title, - ) - self.assertEqual("High", finding.severity) - description = """**Result message:** buffer/sscanf:The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20). + self.assertEqual(description, finding.description) + self.assertEqual("src/common/io.cc", finding.file_path) + self.assertEqual(31, finding.line) + self.assertEqual(120, finding.cwe) + self.assertEqual("FF1004", finding.vuln_id_from_tool) + self.assertEqual( + "327fc54b75ab37bbbb31a1b71431aaefa8137ff755acc103685ad5adf88f5dda", finding.unique_id_from_tool + ) + self.assertEqual("https://cwe.mitre.org/data/definitions/120.html", finding.references) + with self.subTest(i=52): + finding = findings[52] + self.assertEqual( + "buffer/sscanf:The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20).", + finding.title, + ) + self.assertEqual("High", finding.severity) + description = """**Result message:** buffer/sscanf:The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20). **Snippet:** ``` if (sscanf(argv[i], "%[^=]=%s", name, val) == 2) {``` **Rule name:** buffer/sscanf **Rule short description:** The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20).""" - self.assertEqual(description, finding.description) - self.assertEqual("src/cli_main.cc", finding.file_path) - self.assertEqual(482, finding.line) - self.assertEqual("FF1021", finding.vuln_id_from_tool) - self.assertEqual( - "ad8408027235170e870e7662751a01386beb2d2ed8beb75dd4ba8e4a70e91d65", finding.unique_id_from_tool - ) - self.assertEqual("https://cwe.mitre.org/data/definitions/120.html", finding.references) + self.assertEqual(description, finding.description) + self.assertEqual("src/cli_main.cc", finding.file_path) + self.assertEqual(482, finding.line) + self.assertEqual("FF1021", finding.vuln_id_from_tool) + self.assertEqual( + "ad8408027235170e870e7662751a01386beb2d2ed8beb75dd4ba8e4a70e91d65", finding.unique_id_from_tool + ) + self.assertEqual("https://cwe.mitre.org/data/definitions/120.html", finding.references) def test_flawfinder_interfacev2(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sarif/flawfinder.sarif")) - parser = SarifParser() - tests = parser.get_tests(parser.get_scan_types()[0], testfile) - self.assertEqual(1, len(tests)) - findings = tests[0].findings - self.assertEqual(53, len(findings)) - for finding in findings: - self.common_checks(finding) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual( - "random/setstate:This function is not sufficiently random for security-related functions such as key and nonce creation (CWE-327).", - finding.title, - ) - self.assertEqual("High", finding.severity) - description = """**Result message:** random/setstate:This function is not sufficiently random for security-related functions such as key and nonce creation (CWE-327). + with open(path.join(path.dirname(__file__), "../scans/sarif/flawfinder.sarif")) as testfile: + parser = SarifParser() + tests = parser.get_tests(parser.get_scan_types()[0], testfile) + self.assertEqual(1, len(tests)) + findings = tests[0].findings + self.assertEqual(53, len(findings)) + for finding in findings: + self.common_checks(finding) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual( + "random/setstate:This function is not sufficiently random for security-related functions such as key and nonce creation (CWE-327).", + finding.title, + ) + self.assertEqual("High", finding.severity) + description = """**Result message:** random/setstate:This function is not sufficiently random for security-related functions such as key and nonce creation (CWE-327). **Snippet:** ``` is.setstate(std::ios::failbit);``` **Rule name:** random/setstate **Rule short description:** This function is not sufficiently random for security-related functions such as key and nonce creation (CWE-327).""" - self.assertEqual(description, finding.description) - self.assertEqual("src/tree/param.cc", finding.file_path) - self.assertEqual(29, finding.line) - self.assertEqual(327, finding.cwe) - self.assertEqual("FF1048", finding.vuln_id_from_tool) - self.assertEqual("https://cwe.mitre.org/data/definitions/327.html", finding.references) - with self.subTest(i=20): - finding = findings[20] - self.assertEqual( - "buffer/memcpy:Does not check for buffer overflows when copying to destination (CWE-120).", - finding.title, - ) - self.assertEqual("Info", finding.severity) - description = """**Result message:** buffer/memcpy:Does not check for buffer overflows when copying to destination (CWE-120). + self.assertEqual(description, finding.description) + self.assertEqual("src/tree/param.cc", finding.file_path) + self.assertEqual(29, finding.line) + self.assertEqual(327, finding.cwe) + self.assertEqual("FF1048", finding.vuln_id_from_tool) + self.assertEqual("https://cwe.mitre.org/data/definitions/327.html", finding.references) + with self.subTest(i=20): + finding = findings[20] + self.assertEqual( + "buffer/memcpy:Does not check for buffer overflows when copying to destination (CWE-120).", + finding.title, + ) + self.assertEqual("Info", finding.severity) + description = """**Result message:** buffer/memcpy:Does not check for buffer overflows when copying to destination (CWE-120). **Snippet:** ``` std::memcpy(dptr, dmlc::BeginPtr(buffer_) + buffer_ptr_, size);``` **Rule name:** buffer/memcpy **Rule short description:** Does not check for buffer overflows when copying to destination (CWE-120).""" - self.assertEqual(description, finding.description) - self.assertEqual("src/common/io.cc", finding.file_path) - self.assertEqual(31, finding.line) - self.assertEqual(120, finding.cwe) - self.assertEqual("FF1004", finding.vuln_id_from_tool) - self.assertEqual("https://cwe.mitre.org/data/definitions/120.html", finding.references) - with self.subTest(i=52): - finding = findings[52] - self.assertEqual( - "buffer/sscanf:The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20).", - finding.title, - ) - self.assertEqual("High", finding.severity) - description = """**Result message:** buffer/sscanf:The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20). + self.assertEqual(description, finding.description) + self.assertEqual("src/common/io.cc", finding.file_path) + self.assertEqual(31, finding.line) + self.assertEqual(120, finding.cwe) + self.assertEqual("FF1004", finding.vuln_id_from_tool) + self.assertEqual("https://cwe.mitre.org/data/definitions/120.html", finding.references) + with self.subTest(i=52): + finding = findings[52] + self.assertEqual( + "buffer/sscanf:The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20).", + finding.title, + ) + self.assertEqual("High", finding.severity) + description = """**Result message:** buffer/sscanf:The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20). **Snippet:** ``` if (sscanf(argv[i], "%[^=]=%s", name, val) == 2) {``` **Rule name:** buffer/sscanf **Rule short description:** The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20).""" - self.assertEqual(description, finding.description) - self.assertEqual("src/cli_main.cc", finding.file_path) - self.assertEqual(482, finding.line) - self.assertEqual("FF1021", finding.vuln_id_from_tool) - self.assertEqual("https://cwe.mitre.org/data/definitions/120.html", finding.references) + self.assertEqual(description, finding.description) + self.assertEqual("src/cli_main.cc", finding.file_path) + self.assertEqual(482, finding.line) + self.assertEqual("FF1021", finding.vuln_id_from_tool) + self.assertEqual("https://cwe.mitre.org/data/definitions/120.html", finding.references) def test_appendix_k1_double_interfacev2(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sarif/appendix_k1_double.sarif")) - parser = SarifParser() - tests = parser.get_tests(parser.get_scan_types()[0], testfile) - self.assertEqual(2, len(tests)) - with self.subTest(test=0): - test = tests[0] - self.assertEqual("CodeScanner", test.type) - findings = test.findings - self.assertEqual(0, len(findings)) - with self.subTest(test=1): - test = tests[1] - self.assertEqual("OtherScanner", test.type) - findings = test.findings - self.assertEqual(0, len(findings)) + with open(path.join(path.dirname(__file__), "../scans/sarif/appendix_k1_double.sarif")) as testfile: + parser = SarifParser() + tests = parser.get_tests(parser.get_scan_types()[0], testfile) + self.assertEqual(2, len(tests)) + with self.subTest(test=0): + test = tests[0] + self.assertEqual("CodeScanner", test.type) + findings = test.findings + self.assertEqual(0, len(findings)) + with self.subTest(test=1): + test = tests[1] + self.assertEqual("OtherScanner", test.type) + findings = test.findings + self.assertEqual(0, len(findings)) def test_codeql_snippet_report(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sarif/codeQL-output.sarif")) - parser = SarifParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(72, len(findings)) - item = findings[7] - self.assertEqual("good/mod_user.py", item.file_path) - self.assertEqual(33, item.line) - self.assertEqual("High", item.severity) - description = """**Result message:** Keyword argument 'request' is not a supported parameter name of [function create](1). + with open(path.join(path.dirname(__file__), "../scans/sarif/codeQL-output.sarif")) as testfile: + parser = SarifParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(72, len(findings)) + item = findings[7] + self.assertEqual("good/mod_user.py", item.file_path) + self.assertEqual(33, item.line) + self.assertEqual("High", item.severity) + description = """**Result message:** Keyword argument 'request' is not a supported parameter name of [function create](1). **Snippet:** ``` response = make_response(redirect('/')) @@ -529,23 +529,23 @@ def test_codeql_snippet_report(self): **Rule name:** py/call/wrong-named-argument **Rule short description:** Wrong name for an argument in a call **Rule full description:** Using a named argument whose name does not correspond to a parameter of the called function or method, will result in a TypeError at runtime.""" - self.assertEqual(description, item.description) - for finding in findings: - self.common_checks(finding) + self.assertEqual(description, item.description) + for finding in findings: + self.common_checks(finding) def test_severity_cvss_from_grype(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sarif/cxf-3.4.6.sarif")) - parser = SarifParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(22, len(findings)) - # finding 0 - item = findings[0] - self.assertEqual("Low", item.severity) - self.assertEqual(2.1, item.cvssv3_score) - # finding 6 - item = findings[6] - self.assertEqual("High", item.severity) - self.assertEqual(7.8, item.cvssv3_score) + with open(path.join(path.dirname(__file__), "../scans/sarif/cxf-3.4.6.sarif")) as testfile: + parser = SarifParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(22, len(findings)) + # finding 0 + item = findings[0] + self.assertEqual("Low", item.severity) + self.assertEqual(2.1, item.cvssv3_score) + # finding 6 + item = findings[6] + self.assertEqual("High", item.severity) + self.assertEqual(7.8, item.cvssv3_score) def test_get_fingerprints_hashes(self): # example from 3.27.16 of the spec @@ -563,8 +563,8 @@ def test_get_fingerprints_hashes(self): ) def test_tags_from_result_properties(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sarif/taint-python-report.sarif")) - parser = SarifParser() - findings = parser.get_findings(testfile, Test()) - item = findings[0] - self.assertEqual(["Scan"], item.tags) + with open(path.join(path.dirname(__file__), "../scans/sarif/taint-python-report.sarif")) as testfile: + parser = SarifParser() + findings = parser.get_findings(testfile, Test()) + item = findings[0] + self.assertEqual(["Scan"], item.tags) diff --git a/unittests/tools/test_scantist_parser.py b/unittests/tools/test_scantist_parser.py index 2be741c3ac..6656e09dd2 100644 --- a/unittests/tools/test_scantist_parser.py +++ b/unittests/tools/test_scantist_parser.py @@ -6,34 +6,34 @@ class TestScantistParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/scantist/scantist-no-vuln.json") - parser = ScantistParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/scantist/scantist-no-vuln.json") as testfile: + parser = ScantistParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_finding(self): - testfile = open("unittests/scans/scantist/scantist-one-vuln.json") - parser = ScantistParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) + with open("unittests/scans/scantist/scantist-one-vuln.json") as testfile: + parser = ScantistParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) - findings = findings[0] - self.assertEqual(findings.title, findings.unsaved_vulnerability_ids[0] + "|" + findings.component_name) - self.assertEqual( - findings.description, - "Integer overflow in the crypt_raw method in the key-stretching implementation in jBCrypt before 0.4 " - "makes it easier for remote attackers to determine cleartext values of password hashes via a brute-force " - "attack against hashes associated with the maximum exponent.", - ) - self.assertEqual( - findings.severity, "Medium" - ) # Negligible is translated to Informational + findings = findings[0] + self.assertEqual(findings.title, findings.unsaved_vulnerability_ids[0] + "|" + findings.component_name) + self.assertEqual( + findings.description, + "Integer overflow in the crypt_raw method in the key-stretching implementation in jBCrypt before 0.4 " + "makes it easier for remote attackers to determine cleartext values of password hashes via a brute-force " + "attack against hashes associated with the maximum exponent.", + ) + self.assertEqual( + findings.severity, "Medium" + ) # Negligible is translated to Informational def test_parse_file_with_multiple_vuln_has_multiple_findings(self): - testfile = open("unittests/scans/scantist/scantist-many-vuln.json") - parser = ScantistParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(17, len(findings)) - finding = findings[0] - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2018-12432", finding.unsaved_vulnerability_ids[0]) + with open("unittests/scans/scantist/scantist-many-vuln.json") as testfile: + parser = ScantistParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(17, len(findings)) + finding = findings[0] + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2018-12432", finding.unsaved_vulnerability_ids[0]) diff --git a/unittests/tools/test_scout_suite_parser.py b/unittests/tools/test_scout_suite_parser.py index c4e71387bc..9ad71dfc2a 100644 --- a/unittests/tools/test_scout_suite_parser.py +++ b/unittests/tools/test_scout_suite_parser.py @@ -7,82 +7,82 @@ class TestScoutSuiteParser(DojoTestCase): def test_scout_suite_parser_with_no_vuln_has_no_findings(self): - test_file = open("unittests/scans/scout_suite/no_vuln.js") - parser = ScoutSuiteParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/scout_suite/no_vuln.js") as test_file: + parser = ScoutSuiteParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(0, len(findings)) def test_scout_suite_parser_with_two_findings(self): - test_file = open("unittests/scans/scout_suite/two_findings.js") - parser = ScoutSuiteParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(4, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Bucket with Logging Disabled", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertEqual(1032, finding.cwe) - self.assertEqual('gcp:cloudstorage-bucket-no-logging', finding.vuln_id_from_tool) - with self.subTest(i=2): - finding = findings[2] - self.assertEqual("Bucket with Versioning Disabled", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertEqual(1032, finding.cwe) - self.assertEqual(datetime.date(2021, 1, 8), finding.date) - self.assertEqual('gcp:cloudstorage-bucket-no-versioning', finding.vuln_id_from_tool) + with open("unittests/scans/scout_suite/two_findings.js") as test_file: + parser = ScoutSuiteParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(4, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Bucket with Logging Disabled", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertEqual(1032, finding.cwe) + self.assertEqual('gcp:cloudstorage-bucket-no-logging', finding.vuln_id_from_tool) + with self.subTest(i=2): + finding = findings[2] + self.assertEqual("Bucket with Versioning Disabled", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertEqual(1032, finding.cwe) + self.assertEqual(datetime.date(2021, 1, 8), finding.date) + self.assertEqual('gcp:cloudstorage-bucket-no-versioning', finding.vuln_id_from_tool) def test_get_findings(self): - test_file = open("unittests/scans/scout_suite/new2.js") - parser = ScoutSuiteParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(356, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("CloudTrail Service Not Configured", finding.title) - self.assertEqual("Critical", finding.severity) - self.assertEqual(1032, finding.cwe) - self.assertEqual('aws:cloudtrail-not-configured', finding.vuln_id_from_tool) - with self.subTest(i=15): - finding = findings[15] - self.assertEqual("CloudTrail Service Not Configured", finding.title) - self.assertEqual("Critical", finding.severity) - self.assertEqual(1032, finding.cwe) - self.assertEqual('aws:cloudtrail-not-configured', finding.vuln_id_from_tool) - with self.subTest(i=29): - finding = findings[29] - self.assertEqual("AWS Config Not Enabled", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertEqual(1032, finding.cwe) - self.assertEqual('aws:config-recorder-not-configured', finding.vuln_id_from_tool) + with open("unittests/scans/scout_suite/new2.js") as test_file: + parser = ScoutSuiteParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(356, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("CloudTrail Service Not Configured", finding.title) + self.assertEqual("Critical", finding.severity) + self.assertEqual(1032, finding.cwe) + self.assertEqual('aws:cloudtrail-not-configured', finding.vuln_id_from_tool) + with self.subTest(i=15): + finding = findings[15] + self.assertEqual("CloudTrail Service Not Configured", finding.title) + self.assertEqual("Critical", finding.severity) + self.assertEqual(1032, finding.cwe) + self.assertEqual('aws:cloudtrail-not-configured', finding.vuln_id_from_tool) + with self.subTest(i=29): + finding = findings[29] + self.assertEqual("AWS Config Not Enabled", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertEqual(1032, finding.cwe) + self.assertEqual('aws:config-recorder-not-configured', finding.vuln_id_from_tool) def test_get_tests(self): - test_file = open("unittests/scans/scout_suite/new2.js") - parser = ScoutSuiteParser() - scan_type = parser.get_scan_types()[0] - tests = parser.get_tests(scan_type, test_file) - self.assertEqual(1, len(tests)) - test = tests[0] - self.assertEqual("Scout Suite", test.name) - self.assertIn("Amazon Web Services", test.description) # check that the Cloud provider is in the description - self.assertIn("430150006394", test.description) # check that the account is in the description (very usefull) - findings = test.findings - self.assertEqual(356, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("CloudTrail Service Not Configured", finding.title) - self.assertEqual("Critical", finding.severity) - self.assertEqual(1032, finding.cwe) - self.assertEqual(datetime.date(2021, 10, 1), finding.date) - self.assertEqual('aws:cloudtrail-not-configured', finding.vuln_id_from_tool) - with self.subTest(i=15): - finding = findings[15] - self.assertEqual("CloudTrail Service Not Configured", finding.title) - self.assertEqual("Critical", finding.severity) - self.assertEqual(1032, finding.cwe) - self.assertEqual('aws:cloudtrail-not-configured', finding.vuln_id_from_tool) - with self.subTest(i=29): - finding = findings[29] - self.assertEqual("AWS Config Not Enabled", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertEqual(1032, finding.cwe) - self.assertEqual('aws:config-recorder-not-configured', finding.vuln_id_from_tool) + with open("unittests/scans/scout_suite/new2.js") as test_file: + parser = ScoutSuiteParser() + scan_type = parser.get_scan_types()[0] + tests = parser.get_tests(scan_type, test_file) + self.assertEqual(1, len(tests)) + test = tests[0] + self.assertEqual("Scout Suite", test.name) + self.assertIn("Amazon Web Services", test.description) # check that the Cloud provider is in the description + self.assertIn("430150006394", test.description) # check that the account is in the description (very usefull) + findings = test.findings + self.assertEqual(356, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("CloudTrail Service Not Configured", finding.title) + self.assertEqual("Critical", finding.severity) + self.assertEqual(1032, finding.cwe) + self.assertEqual(datetime.date(2021, 10, 1), finding.date) + self.assertEqual('aws:cloudtrail-not-configured', finding.vuln_id_from_tool) + with self.subTest(i=15): + finding = findings[15] + self.assertEqual("CloudTrail Service Not Configured", finding.title) + self.assertEqual("Critical", finding.severity) + self.assertEqual(1032, finding.cwe) + self.assertEqual('aws:cloudtrail-not-configured', finding.vuln_id_from_tool) + with self.subTest(i=29): + finding = findings[29] + self.assertEqual("AWS Config Not Enabled", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertEqual(1032, finding.cwe) + self.assertEqual('aws:config-recorder-not-configured', finding.vuln_id_from_tool) diff --git a/unittests/tools/test_semgrep_parser.py b/unittests/tools/test_semgrep_parser.py index 23e7a80129..ed98b3a431 100644 --- a/unittests/tools/test_semgrep_parser.py +++ b/unittests/tools/test_semgrep_parser.py @@ -6,137 +6,128 @@ class TestSemgrepParser(DojoTestCase): def test_parse_empty(self): - testfile = open("unittests/scans/semgrep/empty.json") - parser = SemgrepParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(0, len(findings)) + with open("unittests/scans/semgrep/empty.json") as testfile: + parser = SemgrepParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_one_finding(self): - testfile = open("unittests/scans/semgrep/one_finding.json") - parser = SemgrepParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertEqual("src/main/java/org/owasp/benchmark/testcode/BenchmarkTest02194.java", finding.file_path) - self.assertEqual(64, finding.line) - self.assertEqual(696, finding.cwe) - self.assertEqual("javax crypto Cipher.getInstance(\"AES/GCM/NoPadding\");", finding.mitigation) - self.assertEqual("java.lang.security.audit.cbc-padding-oracle.cbc-padding-oracle", finding.vuln_id_from_tool) - self.assertIn("javax.crypto.Cipher c = javax.crypto.Cipher.getInstance(\"DES/CBC/PKCS5Padding\");", finding.description) - self.assertIn("Using CBC with PKCS5Padding is susceptible to padding orcale attacks", finding.description) + with open("unittests/scans/semgrep/one_finding.json") as testfile: + parser = SemgrepParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertEqual("src/main/java/org/owasp/benchmark/testcode/BenchmarkTest02194.java", finding.file_path) + self.assertEqual(64, finding.line) + self.assertEqual(696, finding.cwe) + self.assertEqual("javax crypto Cipher.getInstance(\"AES/GCM/NoPadding\");", finding.mitigation) + self.assertEqual("java.lang.security.audit.cbc-padding-oracle.cbc-padding-oracle", finding.vuln_id_from_tool) + self.assertIn("javax.crypto.Cipher c = javax.crypto.Cipher.getInstance(\"DES/CBC/PKCS5Padding\");", finding.description) + self.assertIn("Using CBC with PKCS5Padding is susceptible to padding orcale attacks", finding.description) def test_parse_many_finding(self): - testfile = open("unittests/scans/semgrep/many_findings.json") - parser = SemgrepParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(3, len(findings)) - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertEqual("src/main/java/org/owasp/benchmark/testcode/BenchmarkTest02194.java", finding.file_path) - self.assertEqual(64, finding.line) - self.assertEqual(696, finding.cwe) - self.assertEqual("javax crypto Cipher.getInstance(\"AES/GCM/NoPadding\");", finding.mitigation) - self.assertEqual("java.lang.security.audit.cbc-padding-oracle.cbc-padding-oracle", finding.vuln_id_from_tool) - finding = findings[2] - self.assertEqual("Info", finding.severity) - self.assertEqual("src/main/java/org/owasp/benchmark/testcode/BenchmarkTest01150.java", finding.file_path) - self.assertEqual(66, finding.line) - self.assertEqual(696, finding.cwe) - self.assertEqual("javax crypto Cipher.getInstance(\"AES/GCM/NoPadding\");", finding.mitigation) - self.assertEqual("java.lang.security.audit.cbc-padding-oracle.cbc-padding-oracle", finding.vuln_id_from_tool) + with open("unittests/scans/semgrep/many_findings.json") as testfile: + parser = SemgrepParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(3, len(findings)) + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertEqual("src/main/java/org/owasp/benchmark/testcode/BenchmarkTest02194.java", finding.file_path) + self.assertEqual(64, finding.line) + self.assertEqual(696, finding.cwe) + self.assertEqual("javax crypto Cipher.getInstance(\"AES/GCM/NoPadding\");", finding.mitigation) + self.assertEqual("java.lang.security.audit.cbc-padding-oracle.cbc-padding-oracle", finding.vuln_id_from_tool) + finding = findings[2] + self.assertEqual("Info", finding.severity) + self.assertEqual("src/main/java/org/owasp/benchmark/testcode/BenchmarkTest01150.java", finding.file_path) + self.assertEqual(66, finding.line) + self.assertEqual(696, finding.cwe) + self.assertEqual("javax crypto Cipher.getInstance(\"AES/GCM/NoPadding\");", finding.mitigation) + self.assertEqual("java.lang.security.audit.cbc-padding-oracle.cbc-padding-oracle", finding.vuln_id_from_tool) def test_parse_repeated_finding(self): - testfile = open("unittests/scans/semgrep/repeated_findings.json") - parser = SemgrepParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertEqual("src/main/java/org/owasp/benchmark/testcode/BenchmarkTest01150.java", finding.file_path) - self.assertEqual(66, finding.line) - self.assertEqual("java.lang.security.audit.cbc-padding-oracle.cbc-padding-oracle", finding.vuln_id_from_tool) - self.assertEqual(696, finding.cwe) - self.assertEqual("javax crypto Cipher.getInstance(\"AES/GCM/NoPadding\");", finding.mitigation) - self.assertEqual(2, finding.nb_occurences) + with open("unittests/scans/semgrep/repeated_findings.json") as testfile: + parser = SemgrepParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertEqual("src/main/java/org/owasp/benchmark/testcode/BenchmarkTest01150.java", finding.file_path) + self.assertEqual(66, finding.line) + self.assertEqual("java.lang.security.audit.cbc-padding-oracle.cbc-padding-oracle", finding.vuln_id_from_tool) + self.assertEqual(696, finding.cwe) + self.assertEqual("javax crypto Cipher.getInstance(\"AES/GCM/NoPadding\");", finding.mitigation) + self.assertEqual(2, finding.nb_occurences) def test_parse_many_vulns(self): - testfile = open("unittests/scans/semgrep/many_vulns.json") - parser = SemgrepParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(48, len(findings)) - finding = findings[0] - self.assertEqual("High", finding.severity) - self.assertEqual("tasks.py", finding.file_path) - self.assertEqual(186, finding.line) - self.assertIsNone(finding.mitigation) - self.assertEqual("python.lang.correctness.tempfile.flush.tempfile-without-flush", finding.vuln_id_from_tool) - finding = findings[2] - self.assertEqual("Medium", finding.severity) - self.assertEqual("utils.py", finding.file_path) - self.assertEqual(503, finding.line) - self.assertEqual("python.lang.maintainability.useless-ifelse.useless-if-conditional", finding.vuln_id_from_tool) - finding = findings[4] - self.assertEqual("Medium", finding.severity) - self.assertEqual("tools/sslyze/parser_xml.py", finding.file_path) - self.assertEqual(124, finding.line) - self.assertEqual(327, finding.cwe) - self.assertEqual("python.lang.security.insecure-hash-algorithms.insecure-hash-algorithm-md5", finding.vuln_id_from_tool) - finding = findings[37] - self.assertEqual("High", finding.severity) - self.assertEqual("management/commands/csv_findings_export.py", finding.file_path) - self.assertEqual(33, finding.line) - self.assertEqual(1236, finding.cwe) - self.assertEqual("python.lang.security.unquoted-csv-writer.unquoted-csv-writer", finding.vuln_id_from_tool) + with open("unittests/scans/semgrep/many_vulns.json") as testfile: + parser = SemgrepParser() + findings = parser.get_findings(testfile, Test()) + testfile.close() + self.assertEqual(48, len(findings)) + finding = findings[0] + self.assertEqual("High", finding.severity) + self.assertEqual("tasks.py", finding.file_path) + self.assertEqual(186, finding.line) + self.assertIsNone(finding.mitigation) + self.assertEqual("python.lang.correctness.tempfile.flush.tempfile-without-flush", finding.vuln_id_from_tool) + finding = findings[2] + self.assertEqual("Medium", finding.severity) + self.assertEqual("utils.py", finding.file_path) + self.assertEqual(503, finding.line) + self.assertEqual("python.lang.maintainability.useless-ifelse.useless-if-conditional", finding.vuln_id_from_tool) + finding = findings[4] + self.assertEqual("Medium", finding.severity) + self.assertEqual("tools/sslyze/parser_xml.py", finding.file_path) + self.assertEqual(124, finding.line) + self.assertEqual(327, finding.cwe) + self.assertEqual("python.lang.security.insecure-hash-algorithms.insecure-hash-algorithm-md5", finding.vuln_id_from_tool) + finding = findings[37] + self.assertEqual("High", finding.severity) + self.assertEqual("management/commands/csv_findings_export.py", finding.file_path) + self.assertEqual(33, finding.line) + self.assertEqual(1236, finding.cwe) + self.assertEqual("python.lang.security.unquoted-csv-writer.unquoted-csv-writer", finding.vuln_id_from_tool) def test_parse_cwe_list(self): - testfile = open("unittests/scans/semgrep/cwe_list.json") - parser = SemgrepParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("Info", finding.severity) - self.assertEqual("index.js", finding.file_path) - self.assertEqual(12, finding.line) - self.assertEqual(352, finding.cwe) - self.assertEqual("javascript.express.security.audit.express-check-csurf-middleware-usage.express-check-csurf-middleware-usage", finding.vuln_id_from_tool) - self.assertIn("const app = express();", finding.description) - self.assertIn("A CSRF middleware was not detected in your express application. Ensure you are either using one such as `csurf` or `csrf` (see rule references) and/or you are properly doing CSRF validation in your routes with a token or cookies.", finding.description) + with open("unittests/scans/semgrep/cwe_list.json") as testfile: + parser = SemgrepParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("Info", finding.severity) + self.assertEqual("index.js", finding.file_path) + self.assertEqual(12, finding.line) + self.assertEqual(352, finding.cwe) + self.assertEqual("javascript.express.security.audit.express-check-csurf-middleware-usage.express-check-csurf-middleware-usage", finding.vuln_id_from_tool) + self.assertIn("const app = express();", finding.description) + self.assertIn("A CSRF middleware was not detected in your express application. Ensure you are either using one such as `csurf` or `csrf` (see rule references) and/or you are properly doing CSRF validation in your routes with a token or cookies.", finding.description) def test_different_lines_same_fingerprint(self): - testfile = open("unittests/scans/semgrep/semgrep_version_1_30_0_line_26.json") - parser = SemgrepParser() - findings_first = parser.get_findings(testfile, Test()) - testfile.close() - testfile = open("unittests/scans/semgrep/semgrep_version_1_30_0_line_27.json") - parser = SemgrepParser() - findings_second = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(len(findings_first), len(findings_second)) - for first, second in zip(findings_first, findings_second): - self.assertEqual(first.unique_id_from_tool, second.unique_id_from_tool) + with open("unittests/scans/semgrep/semgrep_version_1_30_0_line_26.json") as testfile: + parser = SemgrepParser() + findings_first = parser.get_findings(testfile, Test()) + with open("unittests/scans/semgrep/semgrep_version_1_30_0_line_27.json") as testfile2: + parser = SemgrepParser() + findings_second = parser.get_findings(testfile2, Test()) + self.assertEqual(len(findings_first), len(findings_second)) + for first, second in zip(findings_first, findings_second): + self.assertEqual(first.unique_id_from_tool, second.unique_id_from_tool) def test_parse_issue_8435(self): - testfile = open("unittests/scans/semgrep/issue_8435.json") - parser = SemgrepParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1, len(findings)) + with open("unittests/scans/semgrep/issue_8435.json") as testfile: + parser = SemgrepParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) def test_parse_sca_deployments_vulns(self): - testfile = open("unittests/scans/semgrep/sca-deployments-vulns.json") - parser = SemgrepParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(18, len(findings)) - finding = findings[0] - self.assertEqual("High", finding.severity) - self.assertEqual("requirements3.txt", finding.file_path) - self.assertEqual('222', finding.line) - self.assertEqual(617, finding.cwe) + with open("unittests/scans/semgrep/sca-deployments-vulns.json") as testfile: + parser = SemgrepParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(18, len(findings)) + finding = findings[0] + self.assertEqual("High", finding.severity) + self.assertEqual("requirements3.txt", finding.file_path) + self.assertEqual('222', finding.line) + self.assertEqual(617, finding.cwe) diff --git a/unittests/tools/test_skf_parser.py b/unittests/tools/test_skf_parser.py index b0fd61d0bd..a9222893a8 100644 --- a/unittests/tools/test_skf_parser.py +++ b/unittests/tools/test_skf_parser.py @@ -6,11 +6,11 @@ class TestSkfParser(DojoTestCase): def test_single_has_no_finding(self): - testfile = open("unittests/scans/skf/export.csv") - parser = SKFParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(27, len(findings)) - # finding 0 - finding = findings[0] - self.assertEqual("Authentication Verification Requirements : Verify that user set passwords are at least 12 characters in length. (C6)", finding.title) - self.assertEqual("Info", finding.severity) + with open("unittests/scans/skf/export.csv") as testfile: + parser = SKFParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(27, len(findings)) + # finding 0 + finding = findings[0] + self.assertEqual("Authentication Verification Requirements : Verify that user set passwords are at least 12 characters in length. (C6)", finding.title) + self.assertEqual("Info", finding.severity) diff --git a/unittests/tools/test_sonarqube_parser.py b/unittests/tools/test_sonarqube_parser.py index 946407e144..29111368cd 100644 --- a/unittests/tools/test_sonarqube_parser.py +++ b/unittests/tools/test_sonarqube_parser.py @@ -27,6 +27,7 @@ def test_file_name_aggregated_parse_file_with_no_vulnerabilities_has_no_findings parser = SonarQubeParser() findings = parser.get_findings(my_file_handle, test) self.assertEqual(0, len(findings)) + my_file_handle.close() # SonarQube Scan detailed - no finding def test_detailed_parse_file_with_no_vulnerabilities_has_no_findings(self): @@ -37,6 +38,7 @@ def test_detailed_parse_file_with_no_vulnerabilities_has_no_findings(self): parser.set_mode('detailed') findings = parser.get_findings(my_file_handle, test) self.assertEqual(0, len(findings)) + my_file_handle.close() # SonarQube Scan - report with one vuln def test_file_name_aggregated_parse_file_with_single_vulnerability_has_single_finding( @@ -88,6 +90,7 @@ def test_file_name_aggregated_parse_file_with_single_vulnerability_has_single_fi self.assertIsNone(item.unique_id_from_tool) self.assertEqual(int, type(item.nb_occurences)) self.assertEqual(1, item.nb_occurences) + my_file_handle.close() def test_detailed_parse_file_with_single_vulnerability_has_single_finding(self): my_file_handle, _product, _engagement, test = self.init( @@ -133,6 +136,7 @@ def test_detailed_parse_file_with_single_vulnerability_has_single_finding(self): self.assertEqual("66", item.line) self.assertEqual(str, type(item.unique_id_from_tool)) self.assertEqual("AWK40IMu-pl6AHs22MnV", item.unique_id_from_tool) + my_file_handle.close() def test_detailed_parse_file_with_multiple_vulnerabilities_has_multiple_findings( self, @@ -145,6 +149,7 @@ def test_detailed_parse_file_with_multiple_vulnerabilities_has_multiple_findings findings = parser.get_findings(my_file_handle, test) # common verifications self.assertEqual(6, len(findings)) + my_file_handle.close() def test_file_name_aggregated_parse_file_with_multiple_vulnerabilities_has_multiple_findings( self, @@ -158,6 +163,7 @@ def test_file_name_aggregated_parse_file_with_multiple_vulnerabilities_has_multi # common verifications # (there is no aggregation to be done here) self.assertEqual(6, len(findings)) + my_file_handle.close() def test_detailed_parse_file_with_table_in_table(self): """Test parsing when the vulnerability details include a table, with tr and td that should be ignored when looking for list of rules""" @@ -237,6 +243,7 @@ def test_detailed_parse_file_with_table_in_table(self): self.assertEqual(True, item.static_finding) self.assertEqual(bool, type(item.dynamic_finding)) self.assertEqual(False, item.dynamic_finding) + my_file_handle.close() def test_detailed_parse_file_with_rule_undefined(self): """the vulnerability's rule is not in the list of rules""" @@ -282,6 +289,7 @@ def test_detailed_parse_file_with_rule_undefined(self): self.assertEqual(True, item.static_finding) self.assertEqual(bool, type(item.dynamic_finding)) self.assertEqual(False, item.dynamic_finding) + my_file_handle.close() # SonarQube Scan - report with aggregations to be made def test_file_name_aggregated_parse_file_with_vuln_on_same_filename(self): @@ -344,6 +352,7 @@ def test_file_name_aggregated_parse_file_with_vuln_on_same_filename(self): self.assertIsNone(aggregatedItem.line) self.assertIsNone(aggregatedItem.unique_id_from_tool) self.assertEqual(int, type(aggregatedItem.nb_occurences)) + my_file_handle.close() # SonarQube Scan detailed - report with aggregations to be made def test_detailed_parse_file_with_vuln_on_same_filename(self): @@ -355,6 +364,7 @@ def test_detailed_parse_file_with_vuln_on_same_filename(self): findings = parser.get_findings(my_file_handle, test) # specific verifications self.assertEqual(4, len(findings)) + my_file_handle.close() def test_detailed_parse_file_with_vuln_issue_3725(self): """SonarQube Scan detailed - report that crash @@ -366,6 +376,7 @@ def test_detailed_parse_file_with_vuln_issue_3725(self): findings = parser.get_findings(my_file_handle, test) # specific verifications self.assertEqual(322, len(findings)) + my_file_handle.close() def test_detailed_parse_file_table_has_whitespace(self): """ @@ -449,6 +460,7 @@ def test_detailed_parse_file_table_has_whitespace(self): self.assertEqual(True, item.static_finding) self.assertEqual(bool, type(item.dynamic_finding)) self.assertEqual(False, item.dynamic_finding) + my_file_handle.close() def test_detailed_parse_json_file_with_no_vulnerabilities_has_no_findings(self): my_file_handle, _product, _engagement, test = self.init( @@ -458,6 +470,7 @@ def test_detailed_parse_json_file_with_no_vulnerabilities_has_no_findings(self): parser.set_mode('detailed') findings = parser.get_findings(my_file_handle, test) self.assertEqual(0, len(findings)) + my_file_handle.close() def test_detailed_parse_json_file_with_single_vulnerability_has_single_finding(self): my_file_handle, _product, _engagement, test = self.init( @@ -536,6 +549,7 @@ def test_detailed_parse_json_file_with_single_vulnerability_has_single_finding(s self.assertEqual(8, 8) self.assertEqual(str, type(item.unique_id_from_tool)) self.assertEqual("AYvNd32RyD1npIoQXyT1", item.unique_id_from_tool) + my_file_handle.close() def test_detailed_parse_json_file_with_multiple_vulnerabilities_has_multiple_findings(self): my_file_handle, _product, _engagement, test = self.init( @@ -547,6 +561,7 @@ def test_detailed_parse_json_file_with_multiple_vulnerabilities_has_multiple_fin # common verifications # (there is no aggregation to be done here) self.assertEqual(6, len(findings)) + my_file_handle.close() def test_parse_json_file_from_api_with_multiple_findings_json(self): my_file_handle, _product, _engagement, test = self.init( @@ -578,6 +593,7 @@ def test_parse_json_file_from_api_with_multiple_findings_json(self): self.assertEqual("CVE-2023-52428", item.unsaved_vulnerability_ids[0]) self.assertEqual("nimbus-jose-jwt-9.24.4.jar", item.component_name) self.assertIsNone(item.component_version) + my_file_handle.close() def test_parse_json_file_from_api_with_multiple_findings_hotspots_json(self): my_file_handle, _product, _engagement, test = self.init( @@ -596,6 +612,7 @@ def test_parse_json_file_from_api_with_multiple_findings_hotspots_json(self): item = findings[2] self.assertEqual("Web:9876_werrwerwerwer", item.title) self.assertEqual("Low", item.severity) + my_file_handle.close() def test_parse_json_file_from_api_with_empty_json(self): my_file_handle, _product, _engagement, test = self.init( @@ -604,6 +621,7 @@ def test_parse_json_file_from_api_with_empty_json(self): parser = SonarQubeParser() findings = parser.get_findings(my_file_handle, test) self.assertEqual(0, len(findings)) + my_file_handle.close() def test_parse_json_file_from_api_with_emppty_zip(self): my_file_handle, _product, _engagement, test = self.init( @@ -612,6 +630,7 @@ def test_parse_json_file_from_api_with_emppty_zip(self): parser = SonarQubeParser() findings = parser.get_findings(my_file_handle, test) self.assertEqual(0, len(findings)) + my_file_handle.close() def test_parse_json_file_from_api_with_multiple_findings_zip(self): my_file_handle, _product, _engagement, test = self.init( @@ -630,3 +649,4 @@ def test_parse_json_file_from_api_with_multiple_findings_zip(self): item = findings[5] self.assertEqual("typescript:S112533_fjoiewfjo1235gweifjoihugu-", item.title) self.assertEqual("Medium", item.severity) + my_file_handle.close() diff --git a/unittests/tools/test_ssh_audit_parser.py b/unittests/tools/test_ssh_audit_parser.py index a7bbf22256..a211fa5423 100644 --- a/unittests/tools/test_ssh_audit_parser.py +++ b/unittests/tools/test_ssh_audit_parser.py @@ -6,39 +6,39 @@ class TestSSHAuditParser(DojoTestCase): def test_parse_file_with_many_vuln_has_many_findings(self): - testfile = open("unittests/scans/ssh_audit/many_vulns.json") - parser = SSHAuditParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(20, len(findings)) - self.assertEqual(findings[0].title, "SSH-2.0-OpenSSH_7.9p1 Debian-10+deb10u2_CVE-2021-41617") - self.assertEqual(findings[1].title, "SSH-2.0-OpenSSH_7.9p1 Debian-10+deb10u2_CVE-2020-15778") - self.assertEqual(findings[0].severity, "High") - self.assertEqual(findings[13].severity, "Medium") + with open("unittests/scans/ssh_audit/many_vulns.json") as testfile: + parser = SSHAuditParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(20, len(findings)) + self.assertEqual(findings[0].title, "SSH-2.0-OpenSSH_7.9p1 Debian-10+deb10u2_CVE-2021-41617") + self.assertEqual(findings[1].title, "SSH-2.0-OpenSSH_7.9p1 Debian-10+deb10u2_CVE-2020-15778") + self.assertEqual(findings[0].severity, "High") + self.assertEqual(findings[13].severity, "Medium") def test_parse_file_with_many_vuln_has_many_findings2(self): - testfile = open("unittests/scans/ssh_audit/many_vulns2.json") - parser = SSHAuditParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(12, len(findings)) - self.assertEqual(findings[0].title, "SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.4_ecdh-sha2-nistp256") - self.assertEqual(findings[1].title, "SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.4_ecdh-sha2-nistp384") - self.assertEqual(findings[0].severity, "High") - self.assertEqual(findings[9].severity, "Medium") + with open("unittests/scans/ssh_audit/many_vulns2.json") as testfile: + parser = SSHAuditParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(12, len(findings)) + self.assertEqual(findings[0].title, "SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.4_ecdh-sha2-nistp256") + self.assertEqual(findings[1].title, "SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.4_ecdh-sha2-nistp384") + self.assertEqual(findings[0].severity, "High") + self.assertEqual(findings[9].severity, "Medium") def test_parse_file_with_many_vuln_bug_fix(self): - testfile = open("unittests/scans/ssh_audit/bug_fix.json") - parser = SSHAuditParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(13, len(findings)) - self.assertEqual(findings[0].title, "SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.5_ecdh-sha2-nistp256") - self.assertEqual(findings[1].title, "SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.5_ecdh-sha2-nistp384") - self.assertEqual(findings[0].severity, "High") + with open("unittests/scans/ssh_audit/bug_fix.json") as testfile: + parser = SSHAuditParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(13, len(findings)) + self.assertEqual(findings[0].title, "SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.5_ecdh-sha2-nistp256") + self.assertEqual(findings[1].title, "SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.5_ecdh-sha2-nistp384") + self.assertEqual(findings[0].severity, "High") diff --git a/unittests/tools/test_sslscan_parser.py b/unittests/tools/test_sslscan_parser.py index b9d518fe7f..4c42518f66 100644 --- a/unittests/tools/test_sslscan_parser.py +++ b/unittests/tools/test_sslscan_parser.py @@ -6,25 +6,25 @@ class TestSslscanParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/sslscan/sslscan_no_vuln.xml") - parser = SslscanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/sslscan/sslscan_no_vuln.xml") as testfile: + parser = SslscanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_findings(self): - testfile = open("unittests/scans/sslscan/sslscan_one_vuln.xml") - parser = SslscanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() + with open("unittests/scans/sslscan/sslscan_one_vuln.xml") as testfile: + parser = SslscanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() def test_parse_file_with_multiple_vuln_has_multiple_finding(self): - testfile = open("unittests/scans/sslscan/sslscan_many_vuln.xml") - parser = SslscanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(2, len(findings)) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() + with open("unittests/scans/sslscan/sslscan_many_vuln.xml") as testfile: + parser = SslscanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(2, len(findings)) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() diff --git a/unittests/tools/test_sslyze_parser.py b/unittests/tools/test_sslyze_parser.py index 1b968d376c..7d8f3dcad2 100644 --- a/unittests/tools/test_sslyze_parser.py +++ b/unittests/tools/test_sslyze_parser.py @@ -7,74 +7,74 @@ class TestSslyzeJSONParser(DojoTestCase): def test_parse_json_file_with_one_target_has_zero_vuln_old(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sslyze/one_target_zero_vuln_old.json")) - parser = SslyzeParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open(path.join(path.dirname(__file__), "../scans/sslyze/one_target_zero_vuln_old.json")) as testfile: + parser = SslyzeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_json_file_issue_9848(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sslyze/issue_9848.json")) - parser = SslyzeParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(3, len(findings)) + with open(path.join(path.dirname(__file__), "../scans/sslyze/issue_9848.json")) as testfile: + parser = SslyzeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(3, len(findings)) def test_parse_json_file_with_one_target_has_one_vuln_old(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sslyze/one_target_one_vuln_old.json")) - parser = SslyzeParser() - findings = parser.get_findings(testfile, Test()) - - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual('Problems in certificate deployments (www.example.com:443)', finding.title) - description = '''www.example.com:443 has problems in certificate deployments: + with open(path.join(path.dirname(__file__), "../scans/sslyze/one_target_one_vuln_old.json")) as testfile: + parser = SslyzeParser() + findings = parser.get_findings(testfile, Test()) + + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual('Problems in certificate deployments (www.example.com:443)', finding.title) + description = '''www.example.com:443 has problems in certificate deployments: - certificate has expired for trust store Android, version 9.0.0_r9 - certificate has expired for trust store Apple, version iOS 13, iPadOS 13, macOS 10.15, watchOS 6, and tvOS 13 - certificate has expired for trust store Java, version jdk-13.0.2 - certificate has expired for trust store Mozilla, version 2019-11-28 - certificate has expired for trust store Windows, version 2020-05-04''' - self.assertEqual(description, finding.description) - self.assertEqual('Medium', finding.severity) + self.assertEqual(description, finding.description) + self.assertEqual('Medium', finding.severity) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual('www.example.com', endpoint.host) - self.assertEqual(443, endpoint.port) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual('www.example.com', endpoint.host) + self.assertEqual(443, endpoint.port) def test_parse_json_file_with_one_target_has_four_vuln_old(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sslyze/one_target_many_vuln_old.json")) - parser = SslyzeParser() - findings = parser.get_findings(testfile, Test()) + with open(path.join(path.dirname(__file__), "../scans/sslyze/one_target_many_vuln_old.json")) as testfile: + parser = SslyzeParser() + findings = parser.get_findings(testfile, Test()) - self.assertEqual(4, len(findings)) + self.assertEqual(4, len(findings)) - self.assertEqual(1, len(findings[0].unsaved_vulnerability_ids)) - self.assertEqual('CVE-2014-0160', findings[0].unsaved_vulnerability_ids[0]) + self.assertEqual(1, len(findings[0].unsaved_vulnerability_ids)) + self.assertEqual('CVE-2014-0160', findings[0].unsaved_vulnerability_ids[0]) - self.assertEqual(1, len(findings[1].unsaved_vulnerability_ids)) - self.assertEqual('CVE-2014-0224', findings[1].unsaved_vulnerability_ids[0]) + self.assertEqual(1, len(findings[1].unsaved_vulnerability_ids)) + self.assertEqual('CVE-2014-0224', findings[1].unsaved_vulnerability_ids[0]) def test_parse_json_file_with_two_target_has_many_vuln_old(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sslyze/two_targets_two_vuln_old.json")) - parser = SslyzeParser() - findings = parser.get_findings(testfile, Test()) + with open(path.join(path.dirname(__file__), "../scans/sslyze/two_targets_two_vuln_old.json")) as testfile: + parser = SslyzeParser() + findings = parser.get_findings(testfile, Test()) - self.assertEqual(2, len(findings)) + self.assertEqual(2, len(findings)) def test_parse_json_file_with_one_target_has_zero_vuln_new(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sslyze/one_target_zero_vuln_new.json")) - parser = SslyzeParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open(path.join(path.dirname(__file__), "../scans/sslyze/one_target_zero_vuln_new.json")) as testfile: + parser = SslyzeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_json_file_with_one_target_has_one_vuln_new(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sslyze/one_target_one_vuln_new.json")) - parser = SslyzeParser() - findings = parser.get_findings(testfile, Test()) - - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual('Unrecommended cipher suites for TLS 1.2 (example.com:443)', finding.title) - description = '''example.com:443 accepts unrecommended cipher suites for TLS 1.2: + with open(path.join(path.dirname(__file__), "../scans/sslyze/one_target_one_vuln_new.json")) as testfile: + parser = SslyzeParser() + findings = parser.get_findings(testfile, Test()) + + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual('Unrecommended cipher suites for TLS 1.2 (example.com:443)', finding.title) + description = '''example.com:443 accepts unrecommended cipher suites for TLS 1.2: - TLS_RSA_WITH_AES_256_GCM_SHA384 - TLS_RSA_WITH_AES_256_CCM_8 - TLS_RSA_WITH_AES_256_CCM @@ -91,34 +91,34 @@ def test_parse_json_file_with_one_target_has_one_vuln_new(self): - TLS_DHE_RSA_WITH_AES_256_CBC_SHA - TLS_DHE_RSA_WITH_AES_128_CCM_8 - TLS_DHE_RSA_WITH_AES_128_CBC_SHA''' - self.assertEqual(description, finding.description) - self.assertEqual('Medium', finding.severity) - self.assertEqual( - 'TLS recommendations of German BSI: https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TG02102/BSI-TR-02102-2.pdf?__blob=publicationFile&v=10', - finding.references - ) - - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual('example.com', endpoint.host) - self.assertEqual(443, endpoint.port) + self.assertEqual(description, finding.description) + self.assertEqual('Medium', finding.severity) + self.assertEqual( + 'TLS recommendations of German BSI: https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TG02102/BSI-TR-02102-2.pdf?__blob=publicationFile&v=10', + finding.references + ) + + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual('example.com', endpoint.host) + self.assertEqual(443, endpoint.port) def test_parse_json_file_with_one_target_has_three_vuln_new(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sslyze/one_target_many_vuln_new.json")) - parser = SslyzeParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(3, len(findings)) + with open(path.join(path.dirname(__file__), "../scans/sslyze/one_target_many_vuln_new.json")) as testfile: + parser = SslyzeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(3, len(findings)) def test_parse_json_file_with_two_target_has_many_vuln_new(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sslyze/two_targets_many_vuln_new.json")) - parser = SslyzeParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(5, len(findings)) - - # We look at 2 examplary findings, the others are similar and don't give more test coverage - finding = findings[0] - self.assertEqual('Unrecommended cipher suites for TLS 1.2 (example.com:443)', finding.title) - description = '''example.com:443 accepts unrecommended cipher suites for TLS 1.2: + with open(path.join(path.dirname(__file__), "../scans/sslyze/two_targets_many_vuln_new.json")) as testfile: + parser = SslyzeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(5, len(findings)) + + # We look at 2 examplary findings, the others are similar and don't give more test coverage + finding = findings[0] + self.assertEqual('Unrecommended cipher suites for TLS 1.2 (example.com:443)', finding.title) + description = '''example.com:443 accepts unrecommended cipher suites for TLS 1.2: - TLS_RSA_WITH_AES_256_GCM_SHA384 - TLS_RSA_WITH_AES_256_CBC_SHA256 - TLS_RSA_WITH_AES_256_CBC_SHA @@ -130,66 +130,66 @@ def test_parse_json_file_with_two_target_has_many_vuln_new(self): - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - TLS_DHE_RSA_WITH_AES_256_CBC_SHA - TLS_DHE_RSA_WITH_AES_128_CBC_SHA''' - self.assertEqual(description, finding.description) - self.assertEqual('Medium', finding.severity) - self.assertEqual( - 'TLS recommendations of German BSI: https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TG02102/BSI-TR-02102-2.pdf?__blob=publicationFile&v=10', - finding.references - ) - - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual('example.com', endpoint.host) - self.assertEqual(443, endpoint.port) - - finding = findings[1] - self.assertEqual('TLS 1.0 not recommended (example2.com:443)', finding.title) - self.assertEqual('example2.com:443 accepts TLS 1.0 connections', finding.description) - self.assertEqual('Medium', finding.severity) - self.assertEqual( - 'TLS recommendations of German BSI: https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TG02102/BSI-TR-02102-2.pdf?__blob=publicationFile&v=10', - finding.references - ) - - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual('example2.com', endpoint.host) - self.assertEqual(443, endpoint.port) + self.assertEqual(description, finding.description) + self.assertEqual('Medium', finding.severity) + self.assertEqual( + 'TLS recommendations of German BSI: https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TG02102/BSI-TR-02102-2.pdf?__blob=publicationFile&v=10', + finding.references + ) + + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual('example.com', endpoint.host) + self.assertEqual(443, endpoint.port) + + finding = findings[1] + self.assertEqual('TLS 1.0 not recommended (example2.com:443)', finding.title) + self.assertEqual('example2.com:443 accepts TLS 1.0 connections', finding.description) + self.assertEqual('Medium', finding.severity) + self.assertEqual( + 'TLS recommendations of German BSI: https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TG02102/BSI-TR-02102-2.pdf?__blob=publicationFile&v=10', + finding.references + ) + + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual('example2.com', endpoint.host) + self.assertEqual(443, endpoint.port) class TestSSLyzeXMLParser(DojoTestCase): def test_parse_file_with_one_target_has_three_vuln(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sslyze/report_one_target_three_vuln.xml")) - parser = SslyzeParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(3, len(findings)) + with open(path.join(path.dirname(__file__), "../scans/sslyze/report_one_target_three_vuln.xml")) as testfile: + parser = SslyzeParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(3, len(findings)) def test_parse_xml_file_with_one_target_has_one_vuln(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sslyze/report_one_target_one_vuln.xml")) - parser = SslyzeParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) + with open(path.join(path.dirname(__file__), "../scans/sslyze/report_one_target_one_vuln.xml")) as testfile: + parser = SslyzeParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) def test_parse_xml_file_with_one_target_has_three_vuln(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sslyze/report_one_target_three_vuln.xml")) - parser = SslyzeParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(3, len(findings)) + with open(path.join(path.dirname(__file__), "../scans/sslyze/report_one_target_three_vuln.xml")) as testfile: + parser = SslyzeParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(3, len(findings)) def test_parse_xml_file_with_two_target_has_many_vuln(self): - testfile = open(path.join(path.dirname(__file__), "../scans/sslyze/report_two_target_many_vuln.xml")) - parser = SslyzeParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(7, len(findings)) + with open(path.join(path.dirname(__file__), "../scans/sslyze/report_two_target_many_vuln.xml")) as testfile: + parser = SslyzeParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(7, len(findings)) diff --git a/unittests/tools/test_stackhawk_parser.py b/unittests/tools/test_stackhawk_parser.py index eec165c4e3..6a7b3af359 100644 --- a/unittests/tools/test_stackhawk_parser.py +++ b/unittests/tools/test_stackhawk_parser.py @@ -9,215 +9,208 @@ class TestStackHawkParser(DojoTestCase): __test_datetime = datetime.datetime(2022, 2, 16, 23, 7, 19, 575000, datetime.timezone.utc) def test_invalid_json_format(self): - testfile = open("unittests/scans/stackhawk/invalid.json") - parser = StackHawkParser() - with self.assertRaises(ValueError): - parser.get_findings(testfile, Test()) + with open("unittests/scans/stackhawk/invalid.json") as testfile: + parser = StackHawkParser() + with self.assertRaises(ValueError): + parser.get_findings(testfile, Test()) def test_parser_ensures_data_is_for_stackhawk_before_parsing(self): - testfile = open("unittests/scans/stackhawk/oddly_familiar_json_that_isnt_us.json") - parser = StackHawkParser() - with self.assertRaises(ValueError): - parser.get_findings(testfile, Test()) + with open("unittests/scans/stackhawk/oddly_familiar_json_that_isnt_us.json") as testfile: + parser = StackHawkParser() + with self.assertRaises(ValueError): + parser.get_findings(testfile, Test()) def test_stackhawk_parser_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/stackhawk/stackhawk_zero_vul.json") - parser = StackHawkParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(0, len(findings)) + with open("unittests/scans/stackhawk/stackhawk_zero_vul.json") as testfile: + parser = StackHawkParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_stackhawk_parser_with_one_high_vuln_has_one_findings(self): - testfile = open("unittests/scans/stackhawk/stackhawk_one_vul.json") - parser = StackHawkParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.__assertAllEndpointsAreClean(findings) - self.assertEqual(1, len(findings)) - - finding = findings[0] - - self.__assertFindingEquals( - finding, - "Anti CSRF Tokens Scanner", - self.__test_datetime, - "Secured Application", - "Development", - "High", - "https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27/finding/20012", - "20012", - "10", - False, - False - ) + with open("unittests/scans/stackhawk/stackhawk_one_vul.json") as testfile: + parser = StackHawkParser() + findings = parser.get_findings(testfile, Test()) + self.__assertAllEndpointsAreClean(findings) + self.assertEqual(1, len(findings)) + + finding = findings[0] + + self.__assertFindingEquals( + finding, + "Anti CSRF Tokens Scanner", + self.__test_datetime, + "Secured Application", + "Development", + "High", + "https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27/finding/20012", + "20012", + "10", + False, + False + ) def test_stackhawk_parser_with_many_vuln_has_many_findings_and_removes_duplicates(self): - testfile = open("unittests/scans/stackhawk/stackhawk_many_vul.json") - parser = StackHawkParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.__assertAllEndpointsAreClean(findings) - self.assertEqual(6, len(findings)) - - self.__assertFindingEquals( - findings[0], - "Cookie Slack Detector", - self.__test_datetime, - "Secured Application", - "Development", - "Low", - "https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27/finding/90027", - "90027", - "10", - False, - False - ) - - self.__assertFindingEquals( - findings[1], - "Proxy Disclosure", - self.__test_datetime, - "Secured Application", - "Development", - "Medium", - "https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27/finding/40025", - "40025", - "10", - False, - False - ) - - self.__assertFindingEquals( - findings[2], - "Anti CSRF Tokens Scanner", - self.__test_datetime, - "Secured Application", - "Development", - "High", - "https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27/finding/20012", - "20012", - "10", - False, - False - ) - - self.__assertFindingEquals( - findings[3], - "Cross Site Scripting Weakness (Reflected in JSON Response)", - self.__test_datetime, - "Secured Application", - "Development", - "High", - "https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27/finding/40012", - "40012", - "1", - False, - False - ) - - self.__assertFindingEquals( - findings[4], - "Content Security Policy (CSP) Header Not Set", - self.__test_datetime, - "Secured Application", - "Development", - "Medium", - "https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27/finding/10038", - "10038", - "12", - False, - False - ) - - self.__assertFindingEquals( - findings[5], - "Permissions Policy Header Not Set", - self.__test_datetime, - "Secured Application", - "Development", - "Low", - "https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27/finding/10063", - "10063", - "12", - False, - False - ) + with open("unittests/scans/stackhawk/stackhawk_many_vul.json") as testfile: + parser = StackHawkParser() + findings = parser.get_findings(testfile, Test()) + self.__assertAllEndpointsAreClean(findings) + self.assertEqual(6, len(findings)) + + self.__assertFindingEquals( + findings[0], + "Cookie Slack Detector", + self.__test_datetime, + "Secured Application", + "Development", + "Low", + "https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27/finding/90027", + "90027", + "10", + False, + False + ) + + self.__assertFindingEquals( + findings[1], + "Proxy Disclosure", + self.__test_datetime, + "Secured Application", + "Development", + "Medium", + "https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27/finding/40025", + "40025", + "10", + False, + False + ) + + self.__assertFindingEquals( + findings[2], + "Anti CSRF Tokens Scanner", + self.__test_datetime, + "Secured Application", + "Development", + "High", + "https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27/finding/20012", + "20012", + "10", + False, + False + ) + + self.__assertFindingEquals( + findings[3], + "Cross Site Scripting Weakness (Reflected in JSON Response)", + self.__test_datetime, + "Secured Application", + "Development", + "High", + "https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27/finding/40012", + "40012", + "1", + False, + False + ) + + self.__assertFindingEquals( + findings[4], + "Content Security Policy (CSP) Header Not Set", + self.__test_datetime, + "Secured Application", + "Development", + "Medium", + "https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27/finding/10038", + "10038", + "12", + False, + False + ) + + self.__assertFindingEquals( + findings[5], + "Permissions Policy Header Not Set", + self.__test_datetime, + "Secured Application", + "Development", + "Low", + "https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27/finding/10063", + "10063", + "12", + False, + False + ) def test_that_a_scan_import_updates_the_test_description(self): - testfile = open("unittests/scans/stackhawk/stackhawk_zero_vul.json") - parser = StackHawkParser() - test = Test() - parser.get_findings(testfile, test) - testfile.close() - self.assertEqual( - test.description, - 'View scan details here: ' - + '[https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27]' - + '(https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27)' - ) + with open("unittests/scans/stackhawk/stackhawk_zero_vul.json") as testfile: + parser = StackHawkParser() + test = Test() + parser.get_findings(testfile, test) + self.assertEqual( + test.description, + 'View scan details here: ' + + '[https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27]' + + '(https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27)' + ) def test_that_a_scan_with_all_false_positive_endpoints_on_a_finding_marks_as_false_positive(self): - testfile = open("unittests/scans/stackhawk/stackhawk_one_vuln_all_endpoints_false_positive.json") - parser = StackHawkParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.__assertAllEndpointsAreClean(findings) - self.assertEqual(1, len(findings)) - self.__assertFindingEquals( - findings[0], - "Cookie Slack Detector", - self.__test_datetime, - "Secured Application", - "Development", - "Low", - "https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27/finding/90027", - "90027", - "3", - True, - False - ) + with open("unittests/scans/stackhawk/stackhawk_one_vuln_all_endpoints_false_positive.json") as testfile: + parser = StackHawkParser() + findings = parser.get_findings(testfile, Test()) + self.__assertAllEndpointsAreClean(findings) + self.assertEqual(1, len(findings)) + self.__assertFindingEquals( + findings[0], + "Cookie Slack Detector", + self.__test_datetime, + "Secured Application", + "Development", + "Low", + "https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27/finding/90027", + "90027", + "3", + True, + False + ) def test_that_a_scan_with_all_risk_accepted_endpoints_on_a_finding_marks_as_risk_accepted(self): - testfile = open("unittests/scans/stackhawk/stackhawk_one_vuln_all_endpoints_risk_accepted.json") - parser = StackHawkParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.__assertAllEndpointsAreClean(findings) - self.assertEqual(1, len(findings)) - self.__assertFindingEquals( - findings[0], - "Cookie Slack Detector", - self.__test_datetime, - "Secured Application", - "Development", - "Low", - "https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27/finding/90027", - "90027", - "3", - False, - True - ) + with open("unittests/scans/stackhawk/stackhawk_one_vuln_all_endpoints_risk_accepted.json") as testfile: + parser = StackHawkParser() + findings = parser.get_findings(testfile, Test()) + self.__assertAllEndpointsAreClean(findings) + self.assertEqual(1, len(findings)) + self.__assertFindingEquals( + findings[0], + "Cookie Slack Detector", + self.__test_datetime, + "Secured Application", + "Development", + "Low", + "https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27/finding/90027", + "90027", + "3", + False, + True + ) def test_that_a_scan_with_endpoints_in_differing_statuses_does_not_mark_as_risk_accepted_or_false_positive(self): - testfile = open("unittests/scans/stackhawk/stackhawk_one_vuln_all_endpoints_have_different_status.json") - parser = StackHawkParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.__assertAllEndpointsAreClean(findings) - self.assertEqual(1, len(findings)) - self.__assertFindingEquals( - findings[0], - "Cookie Slack Detector", - self.__test_datetime, - "Secured Application", - "Development", - "Low", - "https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27/finding/90027", - "90027", - "3", - False, - False - ) + with open("unittests/scans/stackhawk/stackhawk_one_vuln_all_endpoints_have_different_status.json") as testfile: + parser = StackHawkParser() + findings = parser.get_findings(testfile, Test()) + self.__assertAllEndpointsAreClean(findings) + self.assertEqual(1, len(findings)) + self.__assertFindingEquals( + findings[0], + "Cookie Slack Detector", + self.__test_datetime, + "Secured Application", + "Development", + "Low", + "https://app.stackhawk.com/scans/e2ff5651-7eef-47e9-b743-0c2f7d861e27/finding/90027", + "90027", + "3", + False, + False + ) def __assertFindingEquals( self, diff --git a/unittests/tools/test_sysdig_reports_parser.py b/unittests/tools/test_sysdig_reports_parser.py index 20744618df..d0f9c9ae8e 100644 --- a/unittests/tools/test_sysdig_reports_parser.py +++ b/unittests/tools/test_sysdig_reports_parser.py @@ -6,67 +6,61 @@ class TestSysdigParser(TestCase): def test_sysdig_parser_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/sysdig_reports/sysdig_reports_zero_vul.csv") - parser = SysdigReportsParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(0, len(findings)) + with open("unittests/scans/sysdig_reports/sysdig_reports_zero_vul.csv") as testfile: + parser = SysdigReportsParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_sysdig_parser_with_one_criticle_vuln_has_one_findings(self): - testfile = open("unittests/scans/sysdig_reports/sysdig_reports_one_vul.csv") - parser = SysdigReportsParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - self.assertEqual("com.fasterxml.jackson.core:jackson-databind", findings[0].component_name) - self.assertEqual("2.9.7", findings[0].component_version) - self.assertEqual("CVE-2018-19360", findings[0].unsaved_vulnerability_ids[0]) + with open("unittests/scans/sysdig_reports/sysdig_reports_one_vul.csv") as testfile: + parser = SysdigReportsParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + self.assertEqual("com.fasterxml.jackson.core:jackson-databind", findings[0].component_name) + self.assertEqual("2.9.7", findings[0].component_version) + self.assertEqual("CVE-2018-19360", findings[0].unsaved_vulnerability_ids[0]) def test_sysdig_parser_with_many_vuln_has_many_findings(self): - testfile = open("unittests/scans/sysdig_reports/sysdig_reports_many_vul.csv") - parser = SysdigReportsParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(50, len(findings)) - - def test_sysdig_parser_missing_cve_field_id_from_csv_file(self): - with self.assertRaises(ValueError) as context: - testfile = open("unittests/scans/sysdig_reports/sysdig_reports_missing_cve_field.csv") + with open("unittests/scans/sysdig_reports/sysdig_reports_many_vul.csv") as testfile: parser = SysdigReportsParser() findings = parser.get_findings(testfile, Test()) - testfile.close() for finding in findings: for endpoint in finding.unsaved_endpoints: endpoint.clean() + self.assertEqual(50, len(findings)) + + def test_sysdig_parser_missing_cve_field_id_from_csv_file(self): + with self.assertRaises(ValueError) as context: + with open("unittests/scans/sysdig_reports/sysdig_reports_missing_cve_field.csv") as testfile: + parser = SysdigReportsParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() self.assertEqual( "Number of fields in row (22) does not match number of headers (21)", str(context.exception) ) def test_sysdig_parser_missing_cve_field_not_starting_with_cve(self): with self.assertRaises(ValueError) as context: - testfile = open("unittests/scans/sysdig_reports/sysdig_reports_not_starting_with_cve.csv") - parser = SysdigReportsParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() + with open("unittests/scans/sysdig_reports/sysdig_reports_not_starting_with_cve.csv") as testfile: + parser = SysdigReportsParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() self.assertEqual( "Number of fields in row (22) does not match number of headers (21)", str(context.exception) ) def test_sysdig_parser_json_with_many_findings(self): - testfile = open("unittests/scans/sysdig_reports/sysdig.json") - parser = SysdigReportsParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(207, len(findings)) + with open("unittests/scans/sysdig_reports/sysdig.json") as testfile: + parser = SysdigReportsParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(207, len(findings)) diff --git a/unittests/tools/test_talisman_parser.py b/unittests/tools/test_talisman_parser.py index 1fb15a37da..89221d212b 100644 --- a/unittests/tools/test_talisman_parser.py +++ b/unittests/tools/test_talisman_parser.py @@ -6,39 +6,36 @@ class TestTalismanParser(DojoTestCase): def test_parse_empty(self): - testfile = open("unittests/scans/talisman/no_finding.json") - parser = TalismanParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(0, len(findings)) + with open("unittests/scans/talisman/no_finding.json") as testfile: + parser = TalismanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_one_finding(self): - testfile = open("unittests/scans/talisman/one_finding.json") - parser = TalismanParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("password.html", finding.file_path) - self.assertEqual("Secret pattern found in password.html file", finding.title) - self.assertIsNotNone(finding.description) + with open("unittests/scans/talisman/one_finding.json") as testfile: + parser = TalismanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("password.html", finding.file_path) + self.assertEqual("Secret pattern found in password.html file", finding.title) + self.assertIsNotNone(finding.description) def test_parse_many_finding(self): - testfile = open("unittests/scans/talisman/many_findings.json") - parser = TalismanParser() - findings = parser.get_findings(testfile, Test()) - testfile.close() - self.assertEqual(3, len(findings)) - finding = findings[0] - self.assertEqual( - "talisman_report/talisman_reports/data/report.json", finding.file_path - ) - self.assertEqual( - "Secret pattern found in talisman_report/talisman_reports/data/report.json file", - finding.title, - ) - self.assertIsNotNone(finding.description) - finding = findings[1] - self.assertEqual("README.md", finding.file_path) - self.assertEqual("Secret pattern found in README.md file", finding.title) - self.assertIsNotNone(finding.description) + with open("unittests/scans/talisman/many_findings.json") as testfile: + parser = TalismanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(3, len(findings)) + finding = findings[0] + self.assertEqual( + "talisman_report/talisman_reports/data/report.json", finding.file_path + ) + self.assertEqual( + "Secret pattern found in talisman_report/talisman_reports/data/report.json file", + finding.title, + ) + self.assertIsNotNone(finding.description) + finding = findings[1] + self.assertEqual("README.md", finding.file_path) + self.assertEqual("Secret pattern found in README.md file", finding.title) + self.assertIsNotNone(finding.description) diff --git a/unittests/tools/test_tenable_parser.py b/unittests/tools/test_tenable_parser.py index 7ad5485851..4d55d4bb78 100644 --- a/unittests/tools/test_tenable_parser.py +++ b/unittests/tools/test_tenable_parser.py @@ -12,289 +12,289 @@ def create_test(self): return test def test_parse_some_findings_nessus_legacy(self): - testfile = open(path.join(path.dirname(__file__), "../scans/tenable/nessus/nessus_many_vuln.xml")) - parser = TenableParser() - findings = parser.get_findings(testfile, self.create_test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(6, len(findings)) - finding = findings[5] - self.assertEqual("Info", finding.severity) - self.assertIsNone(finding.cwe) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual("https", endpoint.protocol) - endpoint = finding.unsaved_endpoints[1] - self.assertEqual("tcp", endpoint.protocol) + with open(path.join(path.dirname(__file__), "../scans/tenable/nessus/nessus_many_vuln.xml")) as testfile: + parser = TenableParser() + findings = parser.get_findings(testfile, self.create_test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(6, len(findings)) + finding = findings[5] + self.assertEqual("Info", finding.severity) + self.assertIsNone(finding.cwe) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual("https", endpoint.protocol) + endpoint = finding.unsaved_endpoints[1] + self.assertEqual("tcp", endpoint.protocol) def test_parse_some_findings_csv_nessus_legacy(self): """Test one report provided by a user""" - testfile = open(path.join(path.dirname(__file__), "../scans/tenable/nessus/nessus_many_vuln.csv")) - parser = TenableParser() - findings = parser.get_findings(testfile, self.create_test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(4, len(findings)) - for i in [0, 1, 2, 3]: - finding = findings[i] - self.assertIn(finding.severity, Finding.SEVERITIES) - self.assertEqual("Medium", finding.severity) - self.assertEqual(0, finding.cwe) - # check some data - finding = findings[0] - self.assertEqual(1, len(finding.unsaved_endpoints)) - self.assertEqual("10.1.1.1", finding.unsaved_endpoints[0].host) - self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N/E:P/RL:O/RC:C", finding.cvssv3) - # TODO work on component attributes for Nessus CSV parser - self.assertIsNotNone(finding.component_name) - self.assertEqual("md5", finding.component_name) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2004-2761", finding.unsaved_vulnerability_ids[0]) - # this vuln have 'CVE-2013-2566,CVE-2015-2808' as CVE - finding = findings[3] - self.assertEqual(2, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2013-2566", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("CVE-2015-2808", finding.unsaved_vulnerability_ids[1]) + with open(path.join(path.dirname(__file__), "../scans/tenable/nessus/nessus_many_vuln.csv")) as testfile: + parser = TenableParser() + findings = parser.get_findings(testfile, self.create_test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(4, len(findings)) + for i in [0, 1, 2, 3]: + finding = findings[i] + self.assertIn(finding.severity, Finding.SEVERITIES) + self.assertEqual("Medium", finding.severity) + self.assertEqual(0, finding.cwe) + # check some data + finding = findings[0] + self.assertEqual(1, len(finding.unsaved_endpoints)) + self.assertEqual("10.1.1.1", finding.unsaved_endpoints[0].host) + self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N/E:P/RL:O/RC:C", finding.cvssv3) + # TODO work on component attributes for Nessus CSV parser + self.assertIsNotNone(finding.component_name) + self.assertEqual("md5", finding.component_name) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2004-2761", finding.unsaved_vulnerability_ids[0]) + # this vuln have 'CVE-2013-2566,CVE-2015-2808' as CVE + finding = findings[3] + self.assertEqual(2, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2013-2566", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("CVE-2015-2808", finding.unsaved_vulnerability_ids[1]) def test_parse_some_findings_csv2_nessus_legacy(self): """Test that use default columns of Nessus Pro 8.13.1 (#257)""" - testfile = open(path.join(path.dirname(__file__), "../scans/tenable/nessus/nessus_many_vuln2-default.csv")) - parser = TenableParser() - findings = parser.get_findings(testfile, self.create_test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(29, len(findings)) - finding = findings[0] - self.assertIn(finding.severity, Finding.SEVERITIES) - self.assertEqual("Info", finding.severity) - self.assertEqual(0, len(finding.unsaved_vulnerability_ids)) - self.assertEqual(0, finding.cwe) - self.assertEqual("HTTP Server Type and Version", finding.title) - finding = findings[25] - self.assertIn(finding.severity, Finding.SEVERITIES) - self.assertEqual("SSL Certificate Signed Using Weak Hashing Algorithm (Known CA)", finding.title) - self.assertEqual("Info", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2004-2761", finding.unsaved_vulnerability_ids[0]) + with open(path.join(path.dirname(__file__), "../scans/tenable/nessus/nessus_many_vuln2-default.csv")) as testfile: + parser = TenableParser() + findings = parser.get_findings(testfile, self.create_test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(29, len(findings)) + finding = findings[0] + self.assertIn(finding.severity, Finding.SEVERITIES) + self.assertEqual("Info", finding.severity) + self.assertEqual(0, len(finding.unsaved_vulnerability_ids)) + self.assertEqual(0, finding.cwe) + self.assertEqual("HTTP Server Type and Version", finding.title) + finding = findings[25] + self.assertIn(finding.severity, Finding.SEVERITIES) + self.assertEqual("SSL Certificate Signed Using Weak Hashing Algorithm (Known CA)", finding.title) + self.assertEqual("Info", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2004-2761", finding.unsaved_vulnerability_ids[0]) def test_parse_some_findings_csv2_all_nessus_legacy(self): """Test that use a report with all columns of Nessus Pro 8.13.1 (#257)""" - testfile = open(path.join(path.dirname(__file__), "../scans/tenable/nessus/nessus_many_vuln2-all.csv")) - parser = TenableParser() - findings = parser.get_findings(testfile, self.create_test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(29, len(findings)) - finding = findings[0] - self.assertIn(finding.severity, Finding.SEVERITIES) - self.assertEqual("Info", finding.severity) - self.assertEqual(0, len(finding.unsaved_vulnerability_ids)) - self.assertEqual(0, finding.cwe) - self.assertEqual("HTTP Server Type and Version", finding.title) - finding = findings[25] - self.assertIn(finding.severity, Finding.SEVERITIES) - self.assertEqual("SSL Certificate Signed Using Weak Hashing Algorithm (Known CA)", finding.title) - self.assertEqual("Info", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2004-2761", finding.unsaved_vulnerability_ids[0]) + with open(path.join(path.dirname(__file__), "../scans/tenable/nessus/nessus_many_vuln2-all.csv")) as testfile: + parser = TenableParser() + findings = parser.get_findings(testfile, self.create_test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(29, len(findings)) + finding = findings[0] + self.assertIn(finding.severity, Finding.SEVERITIES) + self.assertEqual("Info", finding.severity) + self.assertEqual(0, len(finding.unsaved_vulnerability_ids)) + self.assertEqual(0, finding.cwe) + self.assertEqual("HTTP Server Type and Version", finding.title) + finding = findings[25] + self.assertIn(finding.severity, Finding.SEVERITIES) + self.assertEqual("SSL Certificate Signed Using Weak Hashing Algorithm (Known CA)", finding.title) + self.assertEqual("Info", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2004-2761", finding.unsaved_vulnerability_ids[0]) def test_parse_some_findings_csv_bytes_nessus_legacy(self): """This tests is designed to test the parser with different read modes""" - testfile = open(path.join(path.dirname(__file__), "../scans/tenable/nessus/nessus_many_vuln2-all.csv")) - parser = TenableParser() - findings = parser.get_findings(testfile, self.create_test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - testfile = open(path.join(path.dirname(__file__), "../scans/tenable/nessus/nessus_many_vuln2-all.csv")) - parser = TenableParser() - findings = parser.get_findings(testfile, self.create_test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - testfile = open(path.join(path.dirname(__file__), "../scans/tenable/nessus/nessus_many_vuln2-all.csv"), "rb") - parser = TenableParser() - findings = parser.get_findings(testfile, self.create_test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() + with open(path.join(path.dirname(__file__), "../scans/tenable/nessus/nessus_many_vuln2-all.csv")) as testfile: + parser = TenableParser() + findings = parser.get_findings(testfile, self.create_test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + with open(path.join(path.dirname(__file__), "../scans/tenable/nessus/nessus_many_vuln2-all.csv")) as testfile: + parser = TenableParser() + findings = parser.get_findings(testfile, self.create_test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + with open(path.join(path.dirname(__file__), "../scans/tenable/nessus/nessus_many_vuln2-all.csv"), "rb") as testfile: + parser = TenableParser() + findings = parser.get_findings(testfile, self.create_test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() def test_parse_some_findings_samples_nessus_legacy(self): """Test that come from samples repo""" - testfile = open(path.join(path.dirname(__file__), "../scans/tenable/nessus/nessus_v_unknown.xml")) - parser = TenableParser() - findings = parser.get_findings(testfile, self.create_test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(32, len(findings)) + with open(path.join(path.dirname(__file__), "../scans/tenable/nessus/nessus_v_unknown.xml")) as testfile: + parser = TenableParser() + findings = parser.get_findings(testfile, self.create_test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(32, len(findings)) - finding = findings[0] - self.assertIn(finding.severity, Finding.SEVERITIES) - self.assertEqual("Info", finding.severity) - self.assertEqual(0, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("Nessus Scan Information", finding.title) + finding = findings[0] + self.assertIn(finding.severity, Finding.SEVERITIES) + self.assertEqual("Info", finding.severity) + self.assertEqual(0, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("Nessus Scan Information", finding.title) - finding = findings[25] - self.assertIn(finding.severity, Finding.SEVERITIES) - self.assertEqual("Nessus SYN scanner", finding.title) - self.assertEqual("Info", finding.severity) - self.assertEqual(0, len(finding.unsaved_vulnerability_ids)) - endpoint = finding.unsaved_endpoints[26] - self.assertEqual("http", endpoint.protocol) - endpoint = finding.unsaved_endpoints[37] - self.assertEqual("tcp", endpoint.protocol) + finding = findings[25] + self.assertIn(finding.severity, Finding.SEVERITIES) + self.assertEqual("Nessus SYN scanner", finding.title) + self.assertEqual("Info", finding.severity) + self.assertEqual(0, len(finding.unsaved_vulnerability_ids)) + endpoint = finding.unsaved_endpoints[26] + self.assertEqual("http", endpoint.protocol) + endpoint = finding.unsaved_endpoints[37] + self.assertEqual("tcp", endpoint.protocol) - finding = findings[9] - self.assertEqual(7, len(finding.unsaved_vulnerability_ids)) - for vulnerability_id in finding.unsaved_vulnerability_ids: - self.assertEqual('CVE-2005-1794', vulnerability_id) + finding = findings[9] + self.assertEqual(7, len(finding.unsaved_vulnerability_ids)) + for vulnerability_id in finding.unsaved_vulnerability_ids: + self.assertEqual('CVE-2005-1794', vulnerability_id) def test_parse_some_findings_with_cvssv3_nessus_legacy(self): """test with cvssv3""" - testfile = open(path.join(path.dirname(__file__), "../scans/tenable/nessus/nessus_with_cvssv3.nessus")) - parser = TenableParser() - findings = parser.get_findings(testfile, self.create_test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(48, len(findings)) - finding = findings[3] - self.assertEqual("Medium", finding.severity) - self.assertIsNone(finding.cwe) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual("http", endpoint.protocol) - self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", finding.cvssv3) + with open(path.join(path.dirname(__file__), "../scans/tenable/nessus/nessus_with_cvssv3.nessus")) as testfile: + parser = TenableParser() + findings = parser.get_findings(testfile, self.create_test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(48, len(findings)) + finding = findings[3] + self.assertEqual("Medium", finding.severity) + self.assertIsNone(finding.cwe) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual("http", endpoint.protocol) + self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", finding.cvssv3) def test_parse_many_findings_xml_nessus_was_legacy(self): - testfile = open("unittests/scans/tenable/nessus_was/nessus_was_many_vuln.xml") - parser = TenableParser() - findings = parser.get_findings(testfile, self.create_test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(5, len(findings)) - for i in [0, 1, 2, 3, 4]: - finding = findings[i] - self.assertEqual('http', finding.unsaved_endpoints[0].protocol) - self.assertIsNone(finding.cwe) - finding = findings[0] - self.assertEqual('High', finding.severity) - self.assertEqual('Cross-Site Scripting (XSS)', finding.title) + with open("unittests/scans/tenable/nessus_was/nessus_was_many_vuln.xml") as testfile: + parser = TenableParser() + findings = parser.get_findings(testfile, self.create_test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(5, len(findings)) + for i in [0, 1, 2, 3, 4]: + finding = findings[i] + self.assertEqual('http', finding.unsaved_endpoints[0].protocol) + self.assertIsNone(finding.cwe) + finding = findings[0] + self.assertEqual('High', finding.severity) + self.assertEqual('Cross-Site Scripting (XSS)', finding.title) def test_parse_one_findings_xml_nessus_was_legacy(self): - testfile = open("unittests/scans/tenable/nessus_was/nessus_was_one_vuln.xml") - parser = TenableParser() - findings = parser.get_findings(testfile, self.create_test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual('http', finding.unsaved_endpoints[0].protocol) - self.assertIsNone(finding.cwe) - self.assertEqual('High', finding.severity) - self.assertEqual('Cross-Site Scripting (XSS)', finding.title) + with open("unittests/scans/tenable/nessus_was/nessus_was_one_vuln.xml") as testfile: + parser = TenableParser() + findings = parser.get_findings(testfile, self.create_test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual('http', finding.unsaved_endpoints[0].protocol) + self.assertIsNone(finding.cwe) + self.assertEqual('High', finding.severity) + self.assertEqual('Cross-Site Scripting (XSS)', finding.title) def test_parse_no_findings_xml_nessus_was_legacy(self): - testfile = open("unittests/scans/tenable/nessus_was/nessus_was_no_vuln.xml") - parser = TenableParser() - findings = parser.get_findings(testfile, self.create_test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(0, len(findings)) + with open("unittests/scans/tenable/nessus_was/nessus_was_no_vuln.xml") as testfile: + parser = TenableParser() + findings = parser.get_findings(testfile, self.create_test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(0, len(findings)) def test_parse_many_findings_csv_nessus_was_legacy(self): - testfile = open("unittests/scans/tenable/nessus_was/nessus_was_many_vuln.csv") - parser = TenableParser() - findings = parser.get_findings(testfile, self.create_test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(5, len(findings)) - for i in [0, 1, 2, 3, 4]: - finding = findings[i] + with open("unittests/scans/tenable/nessus_was/nessus_was_many_vuln.csv") as testfile: + parser = TenableParser() + findings = parser.get_findings(testfile, self.create_test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(5, len(findings)) + for i in [0, 1, 2, 3, 4]: + finding = findings[i] + self.assertIn(finding.severity, Finding.SEVERITIES) + self.assertEqual('google.com', finding.unsaved_endpoints[0].host) + self.assertEqual(0, len(finding.unsaved_vulnerability_ids)) + finding = findings[0] + self.assertEqual('7.1', finding.cvssv3_score) + self.assertEqual('High', finding.severity) + self.assertEqual('http', finding.unsaved_endpoints[0].protocol) + + def test_parse_one_findings_csv_nessus_was_legacy(self): + with open("unittests/scans/tenable/nessus_was/nessus_was_one_vuln.csv") as testfile: + parser = TenableParser() + findings = parser.get_findings(testfile, self.create_test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + finding = findings[0] self.assertIn(finding.severity, Finding.SEVERITIES) self.assertEqual('google.com', finding.unsaved_endpoints[0].host) self.assertEqual(0, len(finding.unsaved_vulnerability_ids)) - finding = findings[0] - self.assertEqual('7.1', finding.cvssv3_score) - self.assertEqual('High', finding.severity) - self.assertEqual('http', finding.unsaved_endpoints[0].protocol) - - def test_parse_one_findings_csv_nessus_was_legacy(self): - testfile = open("unittests/scans/tenable/nessus_was/nessus_was_one_vuln.csv") - parser = TenableParser() - findings = parser.get_findings(testfile, self.create_test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertIn(finding.severity, Finding.SEVERITIES) - self.assertEqual('google.com', finding.unsaved_endpoints[0].host) - self.assertEqual(0, len(finding.unsaved_vulnerability_ids)) - self.assertEqual('7.1', finding.cvssv3_score) - self.assertEqual('High', finding.severity) - self.assertEqual('http', finding.unsaved_endpoints[0].protocol) + self.assertEqual('7.1', finding.cvssv3_score) + self.assertEqual('High', finding.severity) + self.assertEqual('http', finding.unsaved_endpoints[0].protocol) def test_parse_no_findings_csv_nessus_was_legacy(self): - testfile = open("unittests/scans/tenable/nessus_was/nessus_was_no_vuln.csv") - parser = TenableParser() - findings = parser.get_findings(testfile, self.create_test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/tenable/nessus_was/nessus_was_no_vuln.csv") as testfile: + parser = TenableParser() + findings = parser.get_findings(testfile, self.create_test()) + self.assertEqual(0, len(findings)) def test_parse_many_tenable_vulns(self): - testfile = open("unittests/scans/tenable/tenable_many_vuln.csv") - parser = TenableParser() - findings = parser.get_findings(testfile, self.create_test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(9, len(findings)) - finding = findings[0] - self.assertIn(finding.severity, Finding.SEVERITIES) - self.assertEqual('High', finding.severity) - self.assertEqual('ip-127-0-0-1.us-west-2.compute.internal', finding.unsaved_endpoints[0].host) - self.assertEqual('Amazon Linux 2 : kernel (ALAS-2023-2050)', finding.title) - self.assertEqual('tcp', finding.unsaved_endpoints[0].protocol) - self.assertEqual(None, finding.unsaved_endpoints[0].port) - self.assertIn('https://alas.aws.amazon.com/AL2/ALAS-2023-2050.html', finding.references) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - for vulnerability_id in finding.unsaved_vulnerability_ids: - self.assertEqual('CVE-2023-32233', vulnerability_id) + with open("unittests/scans/tenable/tenable_many_vuln.csv") as testfile: + parser = TenableParser() + findings = parser.get_findings(testfile, self.create_test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(9, len(findings)) + finding = findings[0] + self.assertIn(finding.severity, Finding.SEVERITIES) + self.assertEqual('High', finding.severity) + self.assertEqual('ip-127-0-0-1.us-west-2.compute.internal', finding.unsaved_endpoints[0].host) + self.assertEqual('Amazon Linux 2 : kernel (ALAS-2023-2050)', finding.title) + self.assertEqual('tcp', finding.unsaved_endpoints[0].protocol) + self.assertEqual(None, finding.unsaved_endpoints[0].port) + self.assertIn('https://alas.aws.amazon.com/AL2/ALAS-2023-2050.html', finding.references) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + for vulnerability_id in finding.unsaved_vulnerability_ids: + self.assertEqual('CVE-2023-32233', vulnerability_id) def test_parse_issue_6992(self): - testfile = open("unittests/scans/tenable/nessus/issue_6992.nessus") - parser = TenableParser() - findings = parser.get_findings(testfile, self.create_test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - self.assertEqual("High", findings[0].severity) + with open("unittests/scans/tenable/nessus/issue_6992.nessus") as testfile: + parser = TenableParser() + findings = parser.get_findings(testfile, self.create_test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + self.assertEqual("High", findings[0].severity) def test_parse_nessus_new(self): - testfile = open("unittests/scans/tenable/nessus/nessus_new.csv") - parser = TenableParser() - findings = parser.get_findings(testfile, self.create_test()) - self.assertEqual(99, len(findings)) - finding = findings[0] - self.assertEqual("Blah1", finding.unsaved_endpoints[0].host) - self.assertEqual("Blah1", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual("3.1", finding.cvssv3_score) + with open("unittests/scans/tenable/nessus/nessus_new.csv") as testfile: + parser = TenableParser() + findings = parser.get_findings(testfile, self.create_test()) + self.assertEqual(99, len(findings)) + finding = findings[0] + self.assertEqual("Blah1", finding.unsaved_endpoints[0].host) + self.assertEqual("Blah1", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual("3.1", finding.cvssv3_score) def test_parse_issue_9612(self): - testfile = open("unittests/scans/tenable/issue_9612.csv") - parser = TenableParser() - findings = parser.get_findings(testfile, self.create_test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(2, len(findings)) - self.assertEqual("Critical", findings[0].severity) + with open("unittests/scans/tenable/issue_9612.csv") as testfile: + parser = TenableParser() + findings = parser.get_findings(testfile, self.create_test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(2, len(findings)) + self.assertEqual("Critical", findings[0].severity) diff --git a/unittests/tools/test_terrascan_parser.py b/unittests/tools/test_terrascan_parser.py index 61ac1be489..ee6605da6d 100644 --- a/unittests/tools/test_terrascan_parser.py +++ b/unittests/tools/test_terrascan_parser.py @@ -6,112 +6,112 @@ class TestTerrascanParser(DojoTestCase): def test_parse_no_findings(self): - testfile = open("unittests/scans/terrascan/no_findings.json") - parser = TerrascanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/terrascan/no_findings.json") as testfile: + parser = TerrascanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_many_findings(self): - testfile = open("unittests/scans/terrascan/many_findings.json") - parser = TerrascanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(9, len(findings)) + with open("unittests/scans/terrascan/many_findings.json") as testfile: + parser = TerrascanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(9, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Infrastructure Security: gkeControlPlaneNotPublic", finding.title) - self.assertEqual("High", finding.severity) - self.assertIsNotNone(finding.description) - self.assertEqual("cluster.tf", finding.file_path) - self.assertEqual(52, finding.line) - self.assertEqual("google_container_cluster/k8s_cluster", finding.component_name) - self.assertEqual("accurics.gcp.NS.109", finding.vuln_id_from_tool) - self.assertEqual(1, finding.nb_occurences) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Infrastructure Security: gkeControlPlaneNotPublic", finding.title) + self.assertEqual("High", finding.severity) + self.assertIsNotNone(finding.description) + self.assertEqual("cluster.tf", finding.file_path) + self.assertEqual(52, finding.line) + self.assertEqual("google_container_cluster/k8s_cluster", finding.component_name) + self.assertEqual("accurics.gcp.NS.109", finding.vuln_id_from_tool) + self.assertEqual(1, finding.nb_occurences) - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("Security Best Practices: autoNodeRepairEnabled", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertIsNotNone(finding.description) - self.assertEqual("cluster.tf", finding.file_path) - self.assertEqual(14, finding.line) - self.assertEqual("google_container_node_pool/k8s_cluster_node_pool", finding.component_name) - self.assertEqual("accurics.gcp.OPS.144", finding.vuln_id_from_tool) - self.assertEqual(1, finding.nb_occurences) + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("Security Best Practices: autoNodeRepairEnabled", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertIsNotNone(finding.description) + self.assertEqual("cluster.tf", finding.file_path) + self.assertEqual(14, finding.line) + self.assertEqual("google_container_node_pool/k8s_cluster_node_pool", finding.component_name) + self.assertEqual("accurics.gcp.OPS.144", finding.vuln_id_from_tool) + self.assertEqual(1, finding.nb_occurences) - with self.subTest(i=2): - finding = findings[2] - self.assertEqual("Infrastructure Security: checkRequireSSLEnabled", finding.title) - self.assertEqual("High", finding.severity) - self.assertIsNotNone(finding.description) - self.assertEqual("db.tf", finding.file_path) - self.assertEqual(5, finding.line) - self.assertEqual("google_sql_database_instance/master", finding.component_name) - self.assertEqual("accurics.gcp.EKM.141", finding.vuln_id_from_tool) - self.assertEqual(1, finding.nb_occurences) + with self.subTest(i=2): + finding = findings[2] + self.assertEqual("Infrastructure Security: checkRequireSSLEnabled", finding.title) + self.assertEqual("High", finding.severity) + self.assertIsNotNone(finding.description) + self.assertEqual("db.tf", finding.file_path) + self.assertEqual(5, finding.line) + self.assertEqual("google_sql_database_instance/master", finding.component_name) + self.assertEqual("accurics.gcp.EKM.141", finding.vuln_id_from_tool) + self.assertEqual(1, finding.nb_occurences) - with self.subTest(i=3): - finding = findings[3] - self.assertEqual("Logging and Monitoring: stackDriverLoggingEnabled", finding.title) - self.assertEqual("High", finding.severity) - self.assertIsNotNone(finding.description) - self.assertEqual("cluster.tf", finding.file_path) - self.assertEqual(52, finding.line) - self.assertEqual("google_container_cluster/k8s_cluster", finding.component_name) - self.assertEqual("accurics.gcp.LOG.100", finding.vuln_id_from_tool) - self.assertEqual(1, finding.nb_occurences) + with self.subTest(i=3): + finding = findings[3] + self.assertEqual("Logging and Monitoring: stackDriverLoggingEnabled", finding.title) + self.assertEqual("High", finding.severity) + self.assertIsNotNone(finding.description) + self.assertEqual("cluster.tf", finding.file_path) + self.assertEqual(52, finding.line) + self.assertEqual("google_container_cluster/k8s_cluster", finding.component_name) + self.assertEqual("accurics.gcp.LOG.100", finding.vuln_id_from_tool) + self.assertEqual(1, finding.nb_occurences) - with self.subTest(i=4): - finding = findings[4] - self.assertEqual("Logging and Monitoring: stackDriverMonitoringEnabled", finding.title) - self.assertEqual("High", finding.severity) - self.assertIsNotNone(finding.description) - self.assertEqual("cluster.tf", finding.file_path) - self.assertEqual(52, finding.line) - self.assertEqual("google_container_cluster/k8s_cluster", finding.component_name) - self.assertEqual("accurics.gcp.MON.143", finding.vuln_id_from_tool) - self.assertEqual(1, finding.nb_occurences) + with self.subTest(i=4): + finding = findings[4] + self.assertEqual("Logging and Monitoring: stackDriverMonitoringEnabled", finding.title) + self.assertEqual("High", finding.severity) + self.assertIsNotNone(finding.description) + self.assertEqual("cluster.tf", finding.file_path) + self.assertEqual(52, finding.line) + self.assertEqual("google_container_cluster/k8s_cluster", finding.component_name) + self.assertEqual("accurics.gcp.MON.143", finding.vuln_id_from_tool) + self.assertEqual(1, finding.nb_occurences) - with self.subTest(i=5): - finding = findings[5] - self.assertEqual("Security Best Practices: checkRotation365Days", finding.title) - self.assertEqual("High", finding.severity) - self.assertIsNotNone(finding.description) - self.assertEqual("vault.tf", finding.file_path) - self.assertEqual(18, finding.line) - self.assertEqual("google_kms_crypto_key/crypto_key", finding.component_name) - self.assertEqual("accurics.gcp.EKM.007", finding.vuln_id_from_tool) - self.assertEqual(1, finding.nb_occurences) + with self.subTest(i=5): + finding = findings[5] + self.assertEqual("Security Best Practices: checkRotation365Days", finding.title) + self.assertEqual("High", finding.severity) + self.assertIsNotNone(finding.description) + self.assertEqual("vault.tf", finding.file_path) + self.assertEqual(18, finding.line) + self.assertEqual("google_kms_crypto_key/crypto_key", finding.component_name) + self.assertEqual("accurics.gcp.EKM.007", finding.vuln_id_from_tool) + self.assertEqual(1, finding.nb_occurences) - with self.subTest(i=6): - finding = findings[6] - self.assertEqual("Infrastructure Security: networkPolicyEnabled", finding.title) - self.assertEqual("High", finding.severity) - self.assertIsNotNone(finding.description) - self.assertEqual("cluster.tf", finding.file_path) - self.assertEqual(52, finding.line) - self.assertEqual("google_container_cluster/k8s_cluster", finding.component_name) - self.assertEqual("accurics.gcp.NS.103", finding.vuln_id_from_tool) - self.assertEqual(1, finding.nb_occurences) + with self.subTest(i=6): + finding = findings[6] + self.assertEqual("Infrastructure Security: networkPolicyEnabled", finding.title) + self.assertEqual("High", finding.severity) + self.assertIsNotNone(finding.description) + self.assertEqual("cluster.tf", finding.file_path) + self.assertEqual(52, finding.line) + self.assertEqual("google_container_cluster/k8s_cluster", finding.component_name) + self.assertEqual("accurics.gcp.NS.103", finding.vuln_id_from_tool) + self.assertEqual(1, finding.nb_occurences) - with self.subTest(i=7): - finding = findings[7] - self.assertEqual("Security Best Practices: checkRotation90Days", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertIsNotNone(finding.description) - self.assertEqual("vault.tf", finding.file_path) - self.assertEqual(18, finding.line) - self.assertEqual("google_kms_crypto_key/crypto_key", finding.component_name) - self.assertEqual("accurics.gcp.EKM.139", finding.vuln_id_from_tool) - self.assertEqual(1, finding.nb_occurences) + with self.subTest(i=7): + finding = findings[7] + self.assertEqual("Security Best Practices: checkRotation90Days", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertIsNotNone(finding.description) + self.assertEqual("vault.tf", finding.file_path) + self.assertEqual(18, finding.line) + self.assertEqual("google_kms_crypto_key/crypto_key", finding.component_name) + self.assertEqual("accurics.gcp.EKM.139", finding.vuln_id_from_tool) + self.assertEqual(1, finding.nb_occurences) - with self.subTest(i=8): - finding = findings[8] - self.assertEqual("Security Best Practices: autoNodeUpgradeEnabled", finding.title) - self.assertEqual("High", finding.severity) - self.assertIsNotNone(finding.description) - self.assertEqual("cluster.tf", finding.file_path) - self.assertEqual(14, finding.line) - self.assertEqual("google_container_node_pool/k8s_cluster_node_pool", finding.component_name) - self.assertEqual("accurics.gcp.OPS.101", finding.vuln_id_from_tool) - self.assertEqual(1, finding.nb_occurences) + with self.subTest(i=8): + finding = findings[8] + self.assertEqual("Security Best Practices: autoNodeUpgradeEnabled", finding.title) + self.assertEqual("High", finding.severity) + self.assertIsNotNone(finding.description) + self.assertEqual("cluster.tf", finding.file_path) + self.assertEqual(14, finding.line) + self.assertEqual("google_container_node_pool/k8s_cluster_node_pool", finding.component_name) + self.assertEqual("accurics.gcp.OPS.101", finding.vuln_id_from_tool) + self.assertEqual(1, finding.nb_occurences) diff --git a/unittests/tools/test_testssl_parser.py b/unittests/tools/test_testssl_parser.py index 05a7e55ef9..9c302cf3f1 100644 --- a/unittests/tools/test_testssl_parser.py +++ b/unittests/tools/test_testssl_parser.py @@ -6,106 +6,106 @@ class TestTestsslParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_finding(self): - testfile = open("unittests/scans/testssl/defectdojo_no_vuln.csv") - parser = TestsslParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/testssl/defectdojo_no_vuln.csv") as testfile: + parser = TestsslParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_one_vuln_has_one_finding(self): - testfile = open("unittests/scans/testssl/defectdojo_one_vuln.csv") - parser = TestsslParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) + with open("unittests/scans/testssl/defectdojo_one_vuln.csv") as testfile: + parser = TestsslParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) def test_parse_file_with_many_vuln_has_many_findings(self): - testfile = open("unittests/scans/testssl/defectdojo_many_vuln.csv") - parser = TestsslParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(100, len(findings)) - # finding 8 - # "cipherlist_AVERAGE","www.defectdojo.org/185.199.110.153","443","LOW","offered","","CWE-310" - finding = findings[8] - self.assertEqual("Low", finding.severity) - self.assertEqual(310, finding.cwe) - # "LUCKY13","www.defectdojo.org/185.199.110.153","443","LOW","potentially vulnerable, uses TLS CBC ciphers","CVE-2013-0169","CWE-310" - finding = findings[50] - self.assertEqual("Low", finding.severity) - self.assertEqual(310, finding.cwe) - self.assertEqual(4, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2013-0169", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("CVE-2013-0169", finding.unsaved_vulnerability_ids[1]) - self.assertEqual("CVE-2013-0169", finding.unsaved_vulnerability_ids[2]) - self.assertEqual("CVE-2013-0169", finding.unsaved_vulnerability_ids[3]) - self.assertEqual(310, finding.cwe) + with open("unittests/scans/testssl/defectdojo_many_vuln.csv") as testfile: + parser = TestsslParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(100, len(findings)) + # finding 8 + # "cipherlist_AVERAGE","www.defectdojo.org/185.199.110.153","443","LOW","offered","","CWE-310" + finding = findings[8] + self.assertEqual("Low", finding.severity) + self.assertEqual(310, finding.cwe) + # "LUCKY13","www.defectdojo.org/185.199.110.153","443","LOW","potentially vulnerable, uses TLS CBC ciphers","CVE-2013-0169","CWE-310" + finding = findings[50] + self.assertEqual("Low", finding.severity) + self.assertEqual(310, finding.cwe) + self.assertEqual(4, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2013-0169", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("CVE-2013-0169", finding.unsaved_vulnerability_ids[1]) + self.assertEqual("CVE-2013-0169", finding.unsaved_vulnerability_ids[2]) + self.assertEqual("CVE-2013-0169", finding.unsaved_vulnerability_ids[3]) + self.assertEqual(310, finding.cwe) def test_parse_file_with_many_cves(self): - testfile = open("unittests/scans/testssl/many_cves.csv") - parser = TestsslParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(2, len(findings)) - finding = findings[0] - self.assertEqual("DROWN", finding.title) - self.assertEqual("High", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2016-0800", finding.unsaved_vulnerability_ids[0]) - self.assertEqual(310, finding.cwe) - finding = findings[1] - self.assertEqual("DROWN", finding.title) - self.assertEqual("High", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2016-0703", finding.unsaved_vulnerability_ids[0]) - self.assertEqual(310, finding.cwe) + with open("unittests/scans/testssl/many_cves.csv") as testfile: + parser = TestsslParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(2, len(findings)) + finding = findings[0] + self.assertEqual("DROWN", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2016-0800", finding.unsaved_vulnerability_ids[0]) + self.assertEqual(310, finding.cwe) + finding = findings[1] + self.assertEqual("DROWN", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2016-0703", finding.unsaved_vulnerability_ids[0]) + self.assertEqual(310, finding.cwe) def test_parse_file_with_31_version(self): - testfile = open("unittests/scans/testssl/demo.csv") - parser = TestsslParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(12, len(findings)) + with open("unittests/scans/testssl/demo.csv") as testfile: + parser = TestsslParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(12, len(findings)) def test_parse_file_with_31_version2(self): - testfile = open("unittests/scans/testssl/demo2.csv") - parser = TestsslParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(3, len(findings)) + with open("unittests/scans/testssl/demo2.csv") as testfile: + parser = TestsslParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(3, len(findings)) def test_parse_file_with_one_vuln_has_overall_medium(self): - testfile = open("unittests/scans/testssl/overall_medium.csv") - parser = TestsslParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(2, len(findings)) + with open("unittests/scans/testssl/overall_medium.csv") as testfile: + parser = TestsslParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(2, len(findings)) def test_parse_file_with_one_vuln_has_overall_critical(self): - testfile = open("unittests/scans/testssl/overall_critical.csv") - parser = TestsslParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(145, len(findings)) + with open("unittests/scans/testssl/overall_critical.csv") as testfile: + parser = TestsslParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(145, len(findings)) def test_parse_file_with_one_vuln_has_failed_target(self): - testfile = open("unittests/scans/testssl/failed_target.csv") - parser = TestsslParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) + with open("unittests/scans/testssl/failed_target.csv") as testfile: + parser = TestsslParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) diff --git a/unittests/tools/test_tfsec_parser.py b/unittests/tools/test_tfsec_parser.py index 417a2691d2..50d7992433 100644 --- a/unittests/tools/test_tfsec_parser.py +++ b/unittests/tools/test_tfsec_parser.py @@ -6,103 +6,103 @@ class TestTFSecParser(DojoTestCase): def test_parse_no_findings(self): - testfile = open("unittests/scans/tfsec/no_findings.json") - parser = TFSecParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/tfsec/no_findings.json") as testfile: + parser = TFSecParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_one_finding_legacy(self): - testfile = open("unittests/scans/tfsec/one_finding_legacy.json") - parser = TFSecParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) + with open("unittests/scans/tfsec/one_finding_legacy.json") as testfile: + parser = TFSecParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Potentially sensitive data stored in block attribute.", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertIsNotNone(finding.description) - self.assertTrue(finding.active) - self.assertEqual("Don't include sensitive data in blocks", finding.mitigation) - self.assertEqual("Block attribute could be leaking secrets", finding.impact) - self.assertEqual("tfsec-test/identity.tf", finding.file_path) - self.assertEqual(226, finding.line) - self.assertEqual("GEN003", finding.vuln_id_from_tool) - self.assertEqual(1, finding.nb_occurences) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Potentially sensitive data stored in block attribute.", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertIsNotNone(finding.description) + self.assertTrue(finding.active) + self.assertEqual("Don't include sensitive data in blocks", finding.mitigation) + self.assertEqual("Block attribute could be leaking secrets", finding.impact) + self.assertEqual("tfsec-test/identity.tf", finding.file_path) + self.assertEqual(226, finding.line) + self.assertEqual("GEN003", finding.vuln_id_from_tool) + self.assertEqual(1, finding.nb_occurences) def test_parse_many_findings_legacy(self): - testfile = open("unittests/scans/tfsec/many_findings_legacy.json") - parser = TFSecParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(3, len(findings)) + with open("unittests/scans/tfsec/many_findings_legacy.json") as testfile: + parser = TFSecParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(3, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Pod security policy enforcement not defined.", finding.title) - self.assertEqual("High", finding.severity) - self.assertIsNotNone(finding.description) - self.assertTrue(finding.active) - self.assertEqual("Use security policies for pods to restrict permissions to those needed to be effective", finding.mitigation) - self.assertEqual("Pods could be operating with more permissions than required to be effective", finding.impact) - self.assertEqual("tfsec-test/cluster.tf", finding.file_path) - self.assertEqual(52, finding.line) - self.assertEqual("GCP009", finding.vuln_id_from_tool) - self.assertEqual(1, finding.nb_occurences) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Pod security policy enforcement not defined.", finding.title) + self.assertEqual("High", finding.severity) + self.assertIsNotNone(finding.description) + self.assertTrue(finding.active) + self.assertEqual("Use security policies for pods to restrict permissions to those needed to be effective", finding.mitigation) + self.assertEqual("Pods could be operating with more permissions than required to be effective", finding.impact) + self.assertEqual("tfsec-test/cluster.tf", finding.file_path) + self.assertEqual(52, finding.line) + self.assertEqual("GCP009", finding.vuln_id_from_tool) + self.assertEqual(1, finding.nb_occurences) - with self.subTest(i=1): - finding = findings[1] - self.assertEqual("Shielded GKE nodes not enabled.", finding.title) - self.assertEqual("High", finding.severity) - self.assertIsNotNone(finding.description) - self.assertTrue(finding.active) - self.assertEqual("Enable node shielding", finding.mitigation) - self.assertEqual("Node identity and integrity can't be verified without shielded GKE nodes", finding.impact) - self.assertEqual("tfsec-test/cluster.tf", finding.file_path) - self.assertEqual(52, finding.line) - self.assertEqual("GCP010", finding.vuln_id_from_tool) - self.assertEqual(1, finding.nb_occurences) + with self.subTest(i=1): + finding = findings[1] + self.assertEqual("Shielded GKE nodes not enabled.", finding.title) + self.assertEqual("High", finding.severity) + self.assertIsNotNone(finding.description) + self.assertTrue(finding.active) + self.assertEqual("Enable node shielding", finding.mitigation) + self.assertEqual("Node identity and integrity can't be verified without shielded GKE nodes", finding.impact) + self.assertEqual("tfsec-test/cluster.tf", finding.file_path) + self.assertEqual(52, finding.line) + self.assertEqual("GCP010", finding.vuln_id_from_tool) + self.assertEqual(1, finding.nb_occurences) - with self.subTest(i=2): - finding = findings[2] - self.assertEqual("Potentially sensitive data stored in block attribute.", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertIsNotNone(finding.description) - self.assertTrue(finding.active) - self.assertEqual("Don't include sensitive data in blocks", finding.mitigation) - self.assertEqual("Block attribute could be leaking secrets", finding.impact) - self.assertEqual("tfsec-test/identity.tf", finding.file_path) - self.assertEqual(226, finding.line) - self.assertEqual("GEN003", finding.vuln_id_from_tool) - self.assertEqual(1, finding.nb_occurences) + with self.subTest(i=2): + finding = findings[2] + self.assertEqual("Potentially sensitive data stored in block attribute.", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertIsNotNone(finding.description) + self.assertTrue(finding.active) + self.assertEqual("Don't include sensitive data in blocks", finding.mitigation) + self.assertEqual("Block attribute could be leaking secrets", finding.impact) + self.assertEqual("tfsec-test/identity.tf", finding.file_path) + self.assertEqual(226, finding.line) + self.assertEqual("GEN003", finding.vuln_id_from_tool) + self.assertEqual(1, finding.nb_occurences) def test_parse_many_findings_current(self): - testfile = open("unittests/scans/tfsec/many_findings_current.json") - parser = TFSecParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(13, len(findings)) + with open("unittests/scans/tfsec/many_findings_current.json") as testfile: + parser = TFSecParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(13, len(findings)) - finding = findings[0] - self.assertEqual("An ingress Network ACL rule allows ALL ports.", finding.title) - self.assertEqual("Critical", finding.severity) - self.assertIsNotNone(finding.description) - self.assertTrue(finding.active) - self.assertEqual("Set specific allowed ports", finding.mitigation) - self.assertEqual("All ports exposed for egressing data", finding.impact) - self.assertEqual("/tmp/aws-eks/modules/vpc-subnets/resources.tf", finding.file_path) - self.assertEqual(155, finding.line) - self.assertEqual("aws-vpc-no-excessive-port-access", finding.vuln_id_from_tool) - self.assertEqual(1, finding.nb_occurences) - self.assertIsNotNone(finding.references) + finding = findings[0] + self.assertEqual("An ingress Network ACL rule allows ALL ports.", finding.title) + self.assertEqual("Critical", finding.severity) + self.assertIsNotNone(finding.description) + self.assertTrue(finding.active) + self.assertEqual("Set specific allowed ports", finding.mitigation) + self.assertEqual("All ports exposed for egressing data", finding.impact) + self.assertEqual("/tmp/aws-eks/modules/vpc-subnets/resources.tf", finding.file_path) + self.assertEqual(155, finding.line) + self.assertEqual("aws-vpc-no-excessive-port-access", finding.vuln_id_from_tool) + self.assertEqual(1, finding.nb_occurences) + self.assertIsNotNone(finding.references) - severities = {} - for finding in findings: - if severities.get(finding.severity, None): - numSeverity = severities.get(finding.severity) - numSeverity += 1 - severities[finding.severity] = numSeverity - else: - severities[finding.severity] = 1 - self.assertEqual(8, severities.get("Critical")) - self.assertEqual(3, severities.get("High")) - self.assertEqual(1, severities.get("Medium")) - self.assertEqual(1, severities.get("Low")) + severities = {} + for finding in findings: + if severities.get(finding.severity, None): + numSeverity = severities.get(finding.severity) + numSeverity += 1 + severities[finding.severity] = numSeverity + else: + severities[finding.severity] = 1 + self.assertEqual(8, severities.get("Critical")) + self.assertEqual(3, severities.get("High")) + self.assertEqual(1, severities.get("Medium")) + self.assertEqual(1, severities.get("Low")) diff --git a/unittests/tools/test_trivy_operator_parser.py b/unittests/tools/test_trivy_operator_parser.py index 6d21975b16..4307385dab 100644 --- a/unittests/tools/test_trivy_operator_parser.py +++ b/unittests/tools/test_trivy_operator_parser.py @@ -12,148 +12,148 @@ def sample_path(file_name): class TestTrivyOperatorParser(DojoTestCase): def test_configauditreport_no_vuln(self): - test_file = open(sample_path("configauditreport_no_vuln.json")) - parser = TrivyOperatorParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 0) + with open(sample_path("configauditreport_no_vuln.json")) as test_file: + parser = TrivyOperatorParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 0) def test_configauditreport_single_vulns(self): - test_file = open(sample_path("configauditreport_single_vuln.json")) - parser = TrivyOperatorParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 1) - finding = findings[0] - self.assertEqual("Low", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("KSV014", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("KSV014 - Root file system is not read-only", finding.title) + with open(sample_path("configauditreport_single_vuln.json")) as test_file: + parser = TrivyOperatorParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 1) + finding = findings[0] + self.assertEqual("Low", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("KSV014", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("KSV014 - Root file system is not read-only", finding.title) def test_configauditreport_many_vulns(self): - test_file = open(sample_path("configauditreport_many.json")) - parser = TrivyOperatorParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 13) - finding = findings[0] - self.assertEqual("Low", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("KSV014", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("KSV014 - Root file system is not read-only", finding.title) - finding = findings[1] - self.assertEqual("Low", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("KSV016", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("KSV016 - Memory requests not specified", finding.title) + with open(sample_path("configauditreport_many.json")) as test_file: + parser = TrivyOperatorParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 13) + finding = findings[0] + self.assertEqual("Low", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("KSV014", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("KSV014 - Root file system is not read-only", finding.title) + finding = findings[1] + self.assertEqual("Low", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("KSV016", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("KSV016 - Memory requests not specified", finding.title) def test_vulnerabilityreport_no_vuln(self): - test_file = open(sample_path("vulnerabilityreport_no_vuln.json")) - parser = TrivyOperatorParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 0) + with open(sample_path("vulnerabilityreport_no_vuln.json")) as test_file: + parser = TrivyOperatorParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 0) def test_vulnerabilityreport_single_vulns(self): - test_file = open(sample_path("vulnerabilityreport_single_vuln.json")) - parser = TrivyOperatorParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 1) - finding = findings[0] - self.assertEqual("Critical", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2023-23914", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("CVE-2023-23914 curl 7.87.0-r1", finding.title) - self.assertEqual("7.87.0-r2", finding.mitigation) - self.assertEqual(4.2, finding.cvssv3_score) + with open(sample_path("vulnerabilityreport_single_vuln.json")) as test_file: + parser = TrivyOperatorParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 1) + finding = findings[0] + self.assertEqual("Critical", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2023-23914", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("CVE-2023-23914 curl 7.87.0-r1", finding.title) + self.assertEqual("7.87.0-r2", finding.mitigation) + self.assertEqual(4.2, finding.cvssv3_score) def test_vulnerabilityreport_many(self): - test_file = open(sample_path("vulnerabilityreport_many.json")) - parser = TrivyOperatorParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 41) - finding = findings[0] - self.assertEqual("Critical", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2023-23914", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("CVE-2023-23914 curl 7.87.0-r1", finding.title) - self.assertEqual("7.87.0-r2", finding.mitigation) - self.assertEqual(4.2, finding.cvssv3_score) - finding = findings[1] - self.assertEqual("High", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2023-23916", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("CVE-2023-23916 curl 7.87.0-r1", finding.title) - self.assertEqual("7.87.0-r2", finding.mitigation) - self.assertEqual(6.5, finding.cvssv3_score) + with open(sample_path("vulnerabilityreport_many.json")) as test_file: + parser = TrivyOperatorParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 41) + finding = findings[0] + self.assertEqual("Critical", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2023-23914", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("CVE-2023-23914 curl 7.87.0-r1", finding.title) + self.assertEqual("7.87.0-r2", finding.mitigation) + self.assertEqual(4.2, finding.cvssv3_score) + finding = findings[1] + self.assertEqual("High", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2023-23916", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("CVE-2023-23916 curl 7.87.0-r1", finding.title) + self.assertEqual("7.87.0-r2", finding.mitigation) + self.assertEqual(6.5, finding.cvssv3_score) def test_exposedsecretreport_no_vuln(self): - test_file = open(sample_path("exposedsecretreport_no_vuln.json")) - parser = TrivyOperatorParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 0) + with open(sample_path("exposedsecretreport_no_vuln.json")) as test_file: + parser = TrivyOperatorParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 0) def test_exposedsecretreport_single_vulns(self): - test_file = open(sample_path("exposedsecretreport_single_vuln.json")) - parser = TrivyOperatorParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 1) - finding = findings[0] - self.assertEqual("Critical", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("aws-secret-access-key", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("aws-secret-access-key", finding.references) - self.assertEqual("root/aws_secret.txt", finding.file_path) - self.assertEqual("Secret detected in root/aws_secret.txt - AWS Secret Access Key", finding.title) + with open(sample_path("exposedsecretreport_single_vuln.json")) as test_file: + parser = TrivyOperatorParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 1) + finding = findings[0] + self.assertEqual("Critical", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("aws-secret-access-key", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("aws-secret-access-key", finding.references) + self.assertEqual("root/aws_secret.txt", finding.file_path) + self.assertEqual("Secret detected in root/aws_secret.txt - AWS Secret Access Key", finding.title) def test_exposedsecretreport_many(self): - test_file = open(sample_path("exposedsecretreport_many.json")) - parser = TrivyOperatorParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 2) - finding = findings[0] - self.assertEqual("Critical", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("aws-secret-access-key", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("aws-secret-access-key", finding.references) - self.assertEqual("root/aws_secret.txt", finding.file_path) - self.assertEqual("Secret detected in root/aws_secret.txt - AWS Secret Access Key", finding.title) - finding = findings[1] - self.assertEqual("Critical", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("github-pat", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("github-pat", finding.references) - self.assertEqual("root/github_secret.txt", finding.file_path) - self.assertEqual("Secret detected in root/github_secret.txt - GitHub Personal Access Token", finding.title) + with open(sample_path("exposedsecretreport_many.json")) as test_file: + parser = TrivyOperatorParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 2) + finding = findings[0] + self.assertEqual("Critical", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("aws-secret-access-key", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("aws-secret-access-key", finding.references) + self.assertEqual("root/aws_secret.txt", finding.file_path) + self.assertEqual("Secret detected in root/aws_secret.txt - AWS Secret Access Key", finding.title) + finding = findings[1] + self.assertEqual("Critical", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("github-pat", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("github-pat", finding.references) + self.assertEqual("root/github_secret.txt", finding.file_path) + self.assertEqual("Secret detected in root/github_secret.txt - GitHub Personal Access Token", finding.title) def test_vulnerabilityreport_extended(self): - test_file = open(sample_path("vulnerabilityreport_extended.json")) - parser = TrivyOperatorParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 5) - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2024-0553", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("CVE-2024-0553 libgnutls30 3.6.13-2ubuntu1.9", finding.title) - self.assertEqual("3.6.13-2ubuntu1.10", finding.mitigation) - self.assertEqual(5.9, finding.cvssv3_score) - self.assertEqual("ubuntu:20.04 (ubuntu 20.04)", finding.file_path) - self.assertEqual("os-pkgs, ubuntu", str(finding.tags)) + with open(sample_path("vulnerabilityreport_extended.json")) as test_file: + parser = TrivyOperatorParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 5) + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2024-0553", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("CVE-2024-0553 libgnutls30 3.6.13-2ubuntu1.9", finding.title) + self.assertEqual("3.6.13-2ubuntu1.10", finding.mitigation) + self.assertEqual(5.9, finding.cvssv3_score) + self.assertEqual("ubuntu:20.04 (ubuntu 20.04)", finding.file_path) + self.assertEqual("os-pkgs, ubuntu", str(finding.tags)) def test_cis_benchmark(self): - test_file = open(sample_path("cis_benchmark.json")) - parser = TrivyOperatorParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 795) - finding = findings[0] - self.assertEqual("5.1.2 AVD-KSV-0041 /clusterrole-admin", finding.title) - self.assertEqual("High", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("AVD-KSV-0041", finding.unsaved_vulnerability_ids[0]) - finding = findings[40] - self.assertEqual("5.2.2 AVD-KSV-0017 kube-system/daemonset-csi-azuredisk-node", finding.title) - self.assertEqual("High", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("AVD-KSV-0017", finding.unsaved_vulnerability_ids[0]) - finding = findings[150] - self.assertEqual("5.2.7 AVD-KSV-0012 opentelemetry-demo/replicaset-opentelemetry-demo-frauddetectionservice-6c6c4b7994", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("AVD-KSV-0012", finding.unsaved_vulnerability_ids[0]) + with open(sample_path("cis_benchmark.json")) as test_file: + parser = TrivyOperatorParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 795) + finding = findings[0] + self.assertEqual("5.1.2 AVD-KSV-0041 /clusterrole-admin", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("AVD-KSV-0041", finding.unsaved_vulnerability_ids[0]) + finding = findings[40] + self.assertEqual("5.2.2 AVD-KSV-0017 kube-system/daemonset-csi-azuredisk-node", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("AVD-KSV-0017", finding.unsaved_vulnerability_ids[0]) + finding = findings[150] + self.assertEqual("5.2.7 AVD-KSV-0012 opentelemetry-demo/replicaset-opentelemetry-demo-frauddetectionservice-6c6c4b7994", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("AVD-KSV-0012", finding.unsaved_vulnerability_ids[0]) diff --git a/unittests/tools/test_trivy_parser.py b/unittests/tools/test_trivy_parser.py index 33390be18e..914b72cddb 100644 --- a/unittests/tools/test_trivy_parser.py +++ b/unittests/tools/test_trivy_parser.py @@ -13,144 +13,144 @@ def sample_path(file_name): class TestTrivyParser(DojoTestCase): def test_legacy_no_vuln(self): - test_file = open(sample_path("legacy_no_vuln.json")) - parser = TrivyParser() - trivy_findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(trivy_findings), 0) + with open(sample_path("legacy_no_vuln.json")) as test_file: + parser = TrivyParser() + trivy_findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(trivy_findings), 0) def test_legacy_many_vulns(self): - test_file = open(sample_path("legacy_many_vulns.json")) - parser = TrivyParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 93) - finding = findings[0] - self.assertEqual("Low", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2011-3374", finding.unsaved_vulnerability_ids[0]) - self.assertEqual(347, finding.cwe) - self.assertEqual("apt", finding.component_name) - self.assertEqual("1.8.2.2", finding.component_version) + with open(sample_path("legacy_many_vulns.json")) as test_file: + parser = TrivyParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 93) + finding = findings[0] + self.assertEqual("Low", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2011-3374", finding.unsaved_vulnerability_ids[0]) + self.assertEqual(347, finding.cwe) + self.assertEqual("apt", finding.component_name) + self.assertEqual("1.8.2.2", finding.component_version) def test_scheme_2_no_vuln(self): - test_file = open(sample_path("scheme_2_no_vuln.json")) - parser = TrivyParser() - trivy_findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(trivy_findings), 0) + with open(sample_path("scheme_2_no_vuln.json")) as test_file: + parser = TrivyParser() + trivy_findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(trivy_findings), 0) def test_scheme_2_many_vulns(self): - test_file = open(sample_path("scheme_2_many_vulns.json")) - parser = TrivyParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 5) - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertEqual('CVE-2020-15999 freetype 2.9.1-r2', finding.title) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2020-15999", finding.unsaved_vulnerability_ids[0]) - self.assertEqual(787, finding.cwe) - self.assertEqual("freetype", finding.component_name) - self.assertEqual("app/libs/freetype-2.9.1-r2", finding.file_path) - self.assertEqual("2.9.1-r2", finding.component_version) - self.assertIsNotNone(finding.description) - self.assertIsNotNone(finding.references) - self.assertEqual('2.9.1-r3', finding.mitigation) - self.assertEqual('CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H', finding.cvssv3) - self.assertTrue(finding.static_finding) - self.assertFalse(finding.dynamic_finding) - finding = findings[1] - self.assertEqual("High", finding.severity) - self.assertEqual('CVE-2020-28196 krb5-libs 1.15.5-r0', finding.title) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2020-28196", finding.unsaved_vulnerability_ids[0]) - self.assertEqual(674, finding.cwe) - self.assertEqual("krb5-libs", finding.component_name) - self.assertEqual("app/libs/krb5-libs-1.15.5-r0", finding.file_path) - self.assertEqual("1.15.5-r0", finding.component_version) - self.assertIsNotNone(finding.description) - self.assertIsNotNone(finding.references) - self.assertEqual('1.15.5-r1', finding.mitigation) - self.assertIsNone(finding.cvssv3) - self.assertTrue(finding.static_finding) - self.assertFalse(finding.dynamic_finding) + with open(sample_path("scheme_2_many_vulns.json")) as test_file: + parser = TrivyParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 5) + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertEqual('CVE-2020-15999 freetype 2.9.1-r2', finding.title) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2020-15999", finding.unsaved_vulnerability_ids[0]) + self.assertEqual(787, finding.cwe) + self.assertEqual("freetype", finding.component_name) + self.assertEqual("app/libs/freetype-2.9.1-r2", finding.file_path) + self.assertEqual("2.9.1-r2", finding.component_version) + self.assertIsNotNone(finding.description) + self.assertIsNotNone(finding.references) + self.assertEqual('2.9.1-r3', finding.mitigation) + self.assertEqual('CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H', finding.cvssv3) + self.assertTrue(finding.static_finding) + self.assertFalse(finding.dynamic_finding) + finding = findings[1] + self.assertEqual("High", finding.severity) + self.assertEqual('CVE-2020-28196 krb5-libs 1.15.5-r0', finding.title) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2020-28196", finding.unsaved_vulnerability_ids[0]) + self.assertEqual(674, finding.cwe) + self.assertEqual("krb5-libs", finding.component_name) + self.assertEqual("app/libs/krb5-libs-1.15.5-r0", finding.file_path) + self.assertEqual("1.15.5-r0", finding.component_version) + self.assertIsNotNone(finding.description) + self.assertIsNotNone(finding.references) + self.assertEqual('1.15.5-r1', finding.mitigation) + self.assertIsNone(finding.cvssv3) + self.assertTrue(finding.static_finding) + self.assertFalse(finding.dynamic_finding) def test_misconfigurations_and_secrets(self): - test_file = open(sample_path("misconfigurations_and_secrets.json")) - parser = TrivyParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 5) - finding = findings[2] - self.assertEqual('DS002 - Image user should not be \'root\'', finding.title) - self.assertEqual('High', finding.severity) - description = '''**Target:** Dockerfile + with open(sample_path("misconfigurations_and_secrets.json")) as test_file: + parser = TrivyParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 5) + finding = findings[2] + self.assertEqual('DS002 - Image user should not be \'root\'', finding.title) + self.assertEqual('High', finding.severity) + description = '''**Target:** Dockerfile **Type:** Dockerfile Security Check Running containers with 'root' user can lead to a container escape situation. It is a best practice to run containers as non-root users, which can be done by adding a 'USER' statement to the Dockerfile. Specify at least 1 USER command in Dockerfile with non-root user as argument ''' - self.assertEqual(description, finding.description) - self.assertEqual('Add \'USER \' line to the Dockerfile', finding.mitigation) - references = '''https://avd.aquasec.com/misconfig/ds002 + self.assertEqual(description, finding.description) + self.assertEqual('Add \'USER \' line to the Dockerfile', finding.mitigation) + references = '''https://avd.aquasec.com/misconfig/ds002 https://docs.docker.com/develop/develop-images/dockerfile_best-practices/''' - self.assertEqual(references, finding.references) - self.assertEqual(['config', 'dockerfile'], finding.tags) - finding = findings[3] - self.assertEqual('Secret detected in Dockerfile - GitHub Personal Access Token', finding.title) - self.assertEqual('Critical', finding.severity) - description = '''GitHub Personal Access Token + self.assertEqual(references, finding.references) + self.assertEqual(['config', 'dockerfile'], finding.tags) + finding = findings[3] + self.assertEqual('Secret detected in Dockerfile - GitHub Personal Access Token', finding.title) + self.assertEqual('Critical', finding.severity) + description = '''GitHub Personal Access Token **Category:** GitHub **Match:** ENV GITHUB_PAT=***** ''' - self.assertEqual(description, finding.description) - self.assertEqual('Dockerfile', finding.file_path) - self.assertEqual(24, finding.line) - self.assertEqual(['secret'], finding.tags) + self.assertEqual(description, finding.description) + self.assertEqual('Dockerfile', finding.file_path) + self.assertEqual(24, finding.line) + self.assertEqual(['secret'], finding.tags) def test_kubernetes(self): - test_file = open(sample_path("kubernetes.json")) - parser = TrivyParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 20) - finding = findings[0] - self.assertEqual('CVE-2020-27350 apt 1.8.2.1', finding.title) - self.assertEqual('Medium', finding.severity) - description = '''apt: integer overflows and underflows while parsing .deb packages + with open(sample_path("kubernetes.json")) as test_file: + parser = TrivyParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 20) + finding = findings[0] + self.assertEqual('CVE-2020-27350 apt 1.8.2.1', finding.title) + self.assertEqual('Medium', finding.severity) + description = '''apt: integer overflows and underflows while parsing .deb packages **Target:** gcr.io/google_samples/gb-redis-follower:v2 (debian 10.4) **Type:** debian **Fixed version:** 1.8.2.2 APT had several integer overflows and underflows while parsing .deb packages, aka GHSL-2020-168 GHSL-2020-169, in files apt-pkg/contrib/extracttar.cc, apt-pkg/deb/debfile.cc, and apt-pkg/contrib/arfile.cc. This issue affects: apt 1.2.32ubuntu0 versions prior to 1.2.32ubuntu0.2; 1.6.12ubuntu0 versions prior to 1.6.12ubuntu0.2; 2.0.2ubuntu0 versions prior to 2.0.2ubuntu0.2; 2.1.10ubuntu0 versions prior to 2.1.10ubuntu0.1; ''' - self.assertEqual(description, finding.description) - self.assertEqual('1.8.2.2', finding.mitigation) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2020-27350", finding.unsaved_vulnerability_ids[0]) - self.assertEqual(['debian', 'os-pkgs'], finding.tags) - self.assertEqual('apt', finding.component_name) - self.assertEqual('1.8.2.1', finding.component_version) - self.assertEqual('default / Deployment / redis-follower', finding.service) - self.assertEqual(finding.file_path, "gcr.io/google_samples/gb-redis-follower:v2 (debian 10.4)") - finding = findings[5] - self.assertEqual('CVE-2020-27350 apt 1.8.2.1', finding.title) - self.assertEqual('Medium', finding.severity) - description = '''apt: integer overflows and underflows while parsing .deb packages + self.assertEqual(description, finding.description) + self.assertEqual('1.8.2.2', finding.mitigation) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2020-27350", finding.unsaved_vulnerability_ids[0]) + self.assertEqual(['debian', 'os-pkgs'], finding.tags) + self.assertEqual('apt', finding.component_name) + self.assertEqual('1.8.2.1', finding.component_version) + self.assertEqual('default / Deployment / redis-follower', finding.service) + self.assertEqual(finding.file_path, "gcr.io/google_samples/gb-redis-follower:v2 (debian 10.4)") + finding = findings[5] + self.assertEqual('CVE-2020-27350 apt 1.8.2.1', finding.title) + self.assertEqual('Medium', finding.severity) + description = '''apt: integer overflows and underflows while parsing .deb packages **Target:** docker.io/redis:6.0.5 (debian 10.4) **Type:** debian **Fixed version:** 1.8.2.2 APT had several integer overflows and underflows while parsing .deb packages, aka GHSL-2020-168 GHSL-2020-169, in files apt-pkg/contrib/extracttar.cc, apt-pkg/deb/debfile.cc, and apt-pkg/contrib/arfile.cc. This issue affects: apt 1.2.32ubuntu0 versions prior to 1.2.32ubuntu0.2; 1.6.12ubuntu0 versions prior to 1.6.12ubuntu0.2; 2.0.2ubuntu0 versions prior to 2.0.2ubuntu0.2; 2.1.10ubuntu0 versions prior to 2.1.10ubuntu0.1; ''' - self.assertEqual(description, finding.description) - self.assertEqual('1.8.2.2', finding.mitigation) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2020-27350", finding.unsaved_vulnerability_ids[0]) - self.assertEqual(['debian', 'os-pkgs'], finding.tags) - self.assertEqual('apt', finding.component_name) - self.assertEqual('1.8.2.1', finding.component_version) - self.assertEqual('default / Deployment / redis-leader', finding.service) - finding = findings[10] - self.assertEqual('KSV001 - Process can elevate its own privileges', finding.title) - self.assertEqual('Medium', finding.severity) - description = '''**Target:** Deployment/redis-follower + self.assertEqual(description, finding.description) + self.assertEqual('1.8.2.2', finding.mitigation) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2020-27350", finding.unsaved_vulnerability_ids[0]) + self.assertEqual(['debian', 'os-pkgs'], finding.tags) + self.assertEqual('apt', finding.component_name) + self.assertEqual('1.8.2.1', finding.component_version) + self.assertEqual('default / Deployment / redis-leader', finding.service) + finding = findings[10] + self.assertEqual('KSV001 - Process can elevate its own privileges', finding.title) + self.assertEqual('Medium', finding.severity) + description = '''**Target:** Deployment/redis-follower **Type:** Kubernetes Security Check A program inside the container can elevate its own privileges and run as root, which might give the program control over the container and node. @@ -166,62 +166,62 @@ def test_kubernetes(self): 139 requests: 140 cpu: 100m 141''' - re_description = re.sub(r"\s+", " ", description) - re_finding_description = re.sub(r"\s+", " ", finding.description) - self.assertEqual(re_description.strip(), re_finding_description.strip()) - self.assertEqual('Set \'set containers[].securityContext.allowPrivilegeEscalation\' to \'false\'.', finding.mitigation) - self.assertIsNone(finding.unsaved_vulnerability_ids) - self.assertEqual(['config', 'kubernetes'], finding.tags) - self.assertIsNone(finding.component_name) - self.assertIsNone(finding.component_version) - self.assertEqual('default / Deployment / redis-follower', finding.service) + re_description = re.sub(r"\s+", " ", description) + re_finding_description = re.sub(r"\s+", " ", finding.description) + self.assertEqual(re_description.strip(), re_finding_description.strip()) + self.assertEqual('Set \'set containers[].securityContext.allowPrivilegeEscalation\' to \'false\'.', finding.mitigation) + self.assertIsNone(finding.unsaved_vulnerability_ids) + self.assertEqual(['config', 'kubernetes'], finding.tags) + self.assertIsNone(finding.component_name) + self.assertIsNone(finding.component_version) + self.assertEqual('default / Deployment / redis-follower', finding.service) def test_license_scheme(self): - test_file = open(sample_path("license_scheme.json")) - parser = TrivyParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 19) - finding = findings[0] - self.assertEqual("High", finding.severity) - self.assertEqual("", finding.file_path) - self.assertEqual(1, finding.scanner_confidence) - self.assertEqual("", finding.url) - description = '''GPL-2.0 + with open(sample_path("license_scheme.json")) as test_file: + parser = TrivyParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 19) + finding = findings[0] + self.assertEqual("High", finding.severity) + self.assertEqual("", finding.file_path) + self.assertEqual(1, finding.scanner_confidence) + self.assertEqual("", finding.url) + description = '''GPL-2.0 **Category:** restricted **Package:** alpine-baselayout ''' - self.assertEqual(description, finding.description) + self.assertEqual(description, finding.description) def test_issue_9092(self): - test_file = open(sample_path("issue_9092.json")) - parser = TrivyParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 1) - finding = findings[0] - self.assertEqual("Critical", finding.severity) - self.assertEqual(finding.file_path, "requirements.txt") + with open(sample_path("issue_9092.json")) as test_file: + parser = TrivyParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 1) + finding = findings[0] + self.assertEqual("Critical", finding.severity) + self.assertEqual(finding.file_path, "requirements.txt") def test_issue_9170(self): - test_file = open(sample_path("issue_9170.json")) - parser = TrivyParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 37) - finding = findings[0] - self.assertEqual("Low", finding.severity) - self.assertEqual("KSV116 - Runs with a root primary or supplementary GID", finding.title) + with open(sample_path("issue_9170.json")) as test_file: + parser = TrivyParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 37) + finding = findings[0] + self.assertEqual("Low", finding.severity) + self.assertEqual("KSV116 - Runs with a root primary or supplementary GID", finding.title) def test_issue_9263(self): - test_file = open(sample_path("issue_9263.json")) - parser = TrivyParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 1) - finding = findings[0] - self.assertEqual("High", finding.severity) + with open(sample_path("issue_9263.json")) as test_file: + parser = TrivyParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 1) + finding = findings[0] + self.assertEqual("High", finding.severity) def test_issue_9333(self): - test_file = open(sample_path("issue_9333.json")) - parser = TrivyParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 13) - finding = findings[0] - self.assertEqual("Low", finding.severity) + with open(sample_path("issue_9333.json")) as test_file: + parser = TrivyParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 13) + finding = findings[0] + self.assertEqual("Low", finding.severity) diff --git a/unittests/tools/test_trufflehog3_parser.py b/unittests/tools/test_trufflehog3_parser.py index 0f1b2c2048..f1b84feea9 100644 --- a/unittests/tools/test_trufflehog3_parser.py +++ b/unittests/tools/test_trufflehog3_parser.py @@ -12,96 +12,96 @@ def sample_path(file_name): class TestTruffleHog3Parser(DojoTestCase): def test_zero_vulns(self): - test_file = open(sample_path("zero_vulns.json")) - parser = TruffleHog3Parser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 0) + with open(sample_path("zero_vulns.json")) as test_file: + parser = TruffleHog3Parser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 0) def test_many_vulns_legacy(self): - test_file = open(sample_path("many_vulns_legacy.json")) - parser = TruffleHog3Parser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 7) - # { - # "date": "2018-05-28 03:24:03", - # "path": "fixtures/users.json", - # "branch": "origin/master", - # "commit": "Update users.json", - # "commitHash": "3e2d1f58bf2ee974fb1195373d8526876fd6348b", - # "reason": "High entropy", - # "stringsFound": [ - # "+ \"password\": \"md5$c77N8n6nJPb1$3b35343aac5e46740f6e673521aa53dc\",", - # "- \"password\": \"md5$oAKvI66ce0Xq$a5c1836db3d6dedff5deca630a358d8b\"," - # ] - # } - finding = findings[0] - self.assertEqual("High", finding.severity) - self.assertEqual(798, finding.cwe) - self.assertEqual('fixtures/users.json', finding.file_path) - # FIXME for now the date in Finding is type datetime.date we need to switch to datetime - # self.assertEqual(datetime.datetime, type(finding.date)) - # self.assertEqual(datetime.datetime(2018, 2, 25, 11, 35, 52), finding.date) - self.assertEqual(datetime.date, type(finding.date)) - self.assertEqual(7, finding.nb_occurences) + with open(sample_path("many_vulns_legacy.json")) as test_file: + parser = TruffleHog3Parser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 7) + # { + # "date": "2018-05-28 03:24:03", + # "path": "fixtures/users.json", + # "branch": "origin/master", + # "commit": "Update users.json", + # "commitHash": "3e2d1f58bf2ee974fb1195373d8526876fd6348b", + # "reason": "High entropy", + # "stringsFound": [ + # "+ \"password\": \"md5$c77N8n6nJPb1$3b35343aac5e46740f6e673521aa53dc\",", + # "- \"password\": \"md5$oAKvI66ce0Xq$a5c1836db3d6dedff5deca630a358d8b\"," + # ] + # } + finding = findings[0] + self.assertEqual("High", finding.severity) + self.assertEqual(798, finding.cwe) + self.assertEqual('fixtures/users.json', finding.file_path) + # FIXME for now the date in Finding is type datetime.date we need to switch to datetime + # self.assertEqual(datetime.datetime, type(finding.date)) + # self.assertEqual(datetime.datetime(2018, 2, 25, 11, 35, 52), finding.date) + self.assertEqual(datetime.date, type(finding.date)) + self.assertEqual(7, finding.nb_occurences) def test_many_vulns2_legacy(self): - test_file = open(sample_path("many_vulns2_legacy.json")) - parser = TruffleHog3Parser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 27) - finding = findings[0] - self.assertEqual("High", finding.severity) - self.assertEqual(798, finding.cwe) - self.assertEqual('test_all.py', finding.file_path) - self.assertEqual(8, finding.nb_occurences) + with open(sample_path("many_vulns2_legacy.json")) as test_file: + parser = TruffleHog3Parser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 27) + finding = findings[0] + self.assertEqual("High", finding.severity) + self.assertEqual(798, finding.cwe) + self.assertEqual('test_all.py', finding.file_path) + self.assertEqual(8, finding.nb_occurences) def test_many_vulns_current(self): - test_file = open(sample_path("many_vulns_current.json")) - parser = TruffleHog3Parser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 3) + with open(sample_path("many_vulns_current.json")) as test_file: + parser = TruffleHog3Parser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 3) - finding = findings[0] - self.assertEqual('High Entropy found in docker/Dockerfile', finding.title) - self.assertEqual(798, finding.cwe) - description = '''**Secret:** 964a1afa20dd4a3723002560124dd96f2a9e853f7ef5b86f5c2354af336fca37 + finding = findings[0] + self.assertEqual('High Entropy found in docker/Dockerfile', finding.title) + self.assertEqual(798, finding.cwe) + description = '''**Secret:** 964a1afa20dd4a3723002560124dd96f2a9e853f7ef5b86f5c2354af336fca37 **Context:** 3: +FROM python:3.9.7-alpine@sha256:964a1afa20dd4a3723002560124dd96f2a9e853f7ef5b86f5c2354af336fca37 **Branch:** python-ab08dd9 **Commit message:** Bump python from 3.9.7-alpine to 3.10.0-alpine **Commit hash:** 9c3f4d641d14eba2740febccd902cde300218a8d **Commit date:** 2021-10-08T20:14:27+02:00''' - self.assertEqual(description, finding.description) - self.assertEqual("High", finding.severity) - self.assertEqual('docker/Dockerfile', finding.file_path) - self.assertEqual(3, finding.line) - self.assertEqual(1, finding.nb_occurences) + self.assertEqual(description, finding.description) + self.assertEqual("High", finding.severity) + self.assertEqual('docker/Dockerfile', finding.file_path) + self.assertEqual(3, finding.line) + self.assertEqual(1, finding.nb_occurences) - finding = findings[1] - self.assertEqual('High Entropy found in docker/Dockerfile', finding.title) - self.assertEqual(798, finding.cwe) - self.maxDiff = None - self.assertIn('\n\n***\n\n', finding.description) - self.assertEqual("Medium", finding.severity) - self.assertEqual('docker/Dockerfile', finding.file_path) - self.assertEqual(2, finding.line) - self.assertEqual(2, finding.nb_occurences) + finding = findings[1] + self.assertEqual('High Entropy found in docker/Dockerfile', finding.title) + self.assertEqual(798, finding.cwe) + self.maxDiff = None + self.assertIn('\n\n***\n\n', finding.description) + self.assertEqual("Medium", finding.severity) + self.assertEqual('docker/Dockerfile', finding.file_path) + self.assertEqual(2, finding.line) + self.assertEqual(2, finding.nb_occurences) - finding = findings[2] - self.assertEqual('High Entropy found in env-file.txt', finding.title) - self.assertEqual(798, finding.cwe) - description = '''**Secret:** 44c45225cf94e58d0c86f0a31051eb7c52c8f78f + finding = findings[2] + self.assertEqual('High Entropy found in env-file.txt', finding.title) + self.assertEqual(798, finding.cwe) + description = '''**Secret:** 44c45225cf94e58d0c86f0a31051eb7c52c8f78f **Context:** 10: DD_API_KEY=44c45225cf94e58d0c86f0a31051eb7c52c8f78f 11: second line of context''' - self.assertEqual(description, finding.description) - self.assertEqual("Low", finding.severity) - self.assertEqual('env-file.txt', finding.file_path) - self.assertEqual(10, finding.line) - self.assertEqual(1, finding.nb_occurences) + self.assertEqual(description, finding.description) + self.assertEqual("Low", finding.severity) + self.assertEqual('env-file.txt', finding.file_path) + self.assertEqual(10, finding.line) + self.assertEqual(1, finding.nb_occurences) def test_issue_6999(self): - test_file = open(sample_path("issue_6999.json")) - parser = TruffleHog3Parser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 1) + with open(sample_path("issue_6999.json")) as test_file: + parser = TruffleHog3Parser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 1) diff --git a/unittests/tools/test_trufflehog_parser.py b/unittests/tools/test_trufflehog_parser.py index 4790d16006..f9c4de2f3e 100644 --- a/unittests/tools/test_trufflehog_parser.py +++ b/unittests/tools/test_trufflehog_parser.py @@ -12,31 +12,31 @@ def sample_path(file_name): class TestTruffleHogParser(DojoTestCase): def test_many_vulns_v2(self): - test_file = open(sample_path("v2_many_vulns.json")) - parser = TruffleHogParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 18) - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertEqual(798, finding.cwe) - self.assertEqual('test_all.py', finding.file_path) + with open(sample_path("v2_many_vulns.json")) as test_file: + parser = TruffleHogParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 18) + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertEqual(798, finding.cwe) + self.assertEqual('test_all.py', finding.file_path) def test_many_vulns_git_v3(self): - test_file = open(sample_path("v3_git.json")) - parser = TruffleHogParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 3) - finding = findings[0] - self.assertEqual("Critical", finding.severity) - self.assertEqual(798, finding.cwe) - self.assertEqual('keys', finding.file_path) + with open(sample_path("v3_git.json")) as test_file: + parser = TruffleHogParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 3) + finding = findings[0] + self.assertEqual("Critical", finding.severity) + self.assertEqual(798, finding.cwe) + self.assertEqual('keys', finding.file_path) def test_many_vulns_github_v3(self): - test_file = open(sample_path("v3_github.json")) - parser = TruffleHogParser() - findings = parser.get_findings(test_file, Test()) - self.assertEqual(len(findings), 3) - finding = findings[0] - self.assertEqual("Critical", finding.severity) - self.assertEqual(798, finding.cwe) - self.assertEqual('keys', finding.file_path) + with open(sample_path("v3_github.json")) as test_file: + parser = TruffleHogParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 3) + finding = findings[0] + self.assertEqual("Critical", finding.severity) + self.assertEqual(798, finding.cwe) + self.assertEqual('keys', finding.file_path) diff --git a/unittests/tools/test_trustwave_fusion_api_parser.py b/unittests/tools/test_trustwave_fusion_api_parser.py index 7a289919ec..ebdd02156f 100644 --- a/unittests/tools/test_trustwave_fusion_api_parser.py +++ b/unittests/tools/test_trustwave_fusion_api_parser.py @@ -5,73 +5,73 @@ class TestTrustwaveFusionAPIParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/trustwave_fusion_api/trustwave_fusion_api_zero_vul.json" - ) - parser = TrustwaveFusionAPIParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + ) as testfile: + parser = TrustwaveFusionAPIParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_vuln_with_valid_cve(self): - testfile = open("unittests/scans/trustwave_fusion_api/test_cve.json") - parser = TrustwaveFusionAPIParser() - findings = parser.get_findings(testfile, Test()) + with open("unittests/scans/trustwave_fusion_api/test_cve.json") as testfile: + parser = TrustwaveFusionAPIParser() + findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() - # first example - finding = findings[0] - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2017-7529", finding.unsaved_vulnerability_ids[0]) - self.assertEqual( - "Vulnerability/Missing Patch", finding.description - ) + # first example + finding = findings[0] + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2017-7529", finding.unsaved_vulnerability_ids[0]) + self.assertEqual( + "Vulnerability/Missing Patch", finding.description + ) - # second example - finding = findings[1] - self.assertEqual(2, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2013-2566", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("CVE-2015-2808", finding.unsaved_vulnerability_ids[1]) - self.assertEqual( - "Cryptography/Weak Cryptography", - finding.description, - ) - self.assertEqual(str(finding.unsaved_endpoints[0]), "https://google.com") + # second example + finding = findings[1] + self.assertEqual(2, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2013-2566", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("CVE-2015-2808", finding.unsaved_vulnerability_ids[1]) + self.assertEqual( + "Cryptography/Weak Cryptography", + finding.description, + ) + self.assertEqual(str(finding.unsaved_endpoints[0]), "https://google.com") def test_parse_file_with_multiple_vuln_has_multiple_findings(self): - testfile = open( + with open( get_unit_tests_path() + "/scans/trustwave_fusion_api/trustwave_fusion_api_many_vul.json" - ) - parser = TrustwaveFusionAPIParser() - findings = parser.get_findings(testfile, Test()) + ) as testfile: + parser = TrustwaveFusionAPIParser() + findings = parser.get_findings(testfile, Test()) - self.assertEqual(3, len(findings)) # checking dupes + self.assertEqual(3, len(findings)) # checking dupes - # endpoint validation - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() + # endpoint validation + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() - finding = findings[0] - self.assertEqual("0123456:id", finding.unique_id_from_tool) - self.assertEqual("Website Detected", finding.title) - self.assertEqual( - "Information/Service Discovery", finding.description - ) - self.assertIsNone(finding.unsaved_vulnerability_ids) - date = finding.date.strftime("%Y-%m-%dT%H:%M:%S.%f%z") - self.assertEqual("2021-06-15T07:48:08.727000+0000", date) - self.assertEqual("Info", finding.severity) - self.assertIsNone(finding.unsaved_vulnerability_ids) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual(str(endpoint), "https://google.com") - self.assertEqual(endpoint.host, "google.com") - self.assertIsNone(endpoint.path) - self.assertEqual(endpoint.port, 443) + finding = findings[0] + self.assertEqual("0123456:id", finding.unique_id_from_tool) + self.assertEqual("Website Detected", finding.title) + self.assertEqual( + "Information/Service Discovery", finding.description + ) + self.assertIsNone(finding.unsaved_vulnerability_ids) + date = finding.date.strftime("%Y-%m-%dT%H:%M:%S.%f%z") + self.assertEqual("2021-06-15T07:48:08.727000+0000", date) + self.assertEqual("Info", finding.severity) + self.assertIsNone(finding.unsaved_vulnerability_ids) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual(str(endpoint), "https://google.com") + self.assertEqual(endpoint.host, "google.com") + self.assertIsNone(endpoint.path) + self.assertEqual(endpoint.port, 443) - # testing component_name and component_version - finding = findings[2] - self.assertEqual("nginx:nginx", finding.component_name) - self.assertEqual("1.20.0", finding.component_version) + # testing component_name and component_version + finding = findings[2] + self.assertEqual("nginx:nginx", finding.component_name) + self.assertEqual("1.20.0", finding.component_version) diff --git a/unittests/tools/test_trustwave_parser.py b/unittests/tools/test_trustwave_parser.py index 37022142d4..5ab1627088 100644 --- a/unittests/tools/test_trustwave_parser.py +++ b/unittests/tools/test_trustwave_parser.py @@ -15,43 +15,43 @@ def test_no_vuln(self): test = Test() test.engagement = Engagement() test.engagement.product = Product() - test_file = open(sample_path("many_vulns.csv")) - parser = TrustwaveParser() - findings = parser.get_findings(test_file, test) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(len(findings), 4) - # finding 0 - finding = findings[0] - self.assertEqual("High", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-3011-123", finding.unsaved_vulnerability_ids[0]) - # finding 1 - finding = findings[1] - self.assertEqual("Tom and Jerry vulnerable to Mouse Traps", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-3011-321", finding.unsaved_vulnerability_ids[0]) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual("192.168.0.58", endpoint.host) - self.assertEqual("tcp", endpoint.protocol) - self.assertEqual(80, endpoint.port) - # finding 2 - finding = findings[2] - self.assertEqual("Medium", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-3011-313", finding.unsaved_vulnerability_ids[0]) - # finding 3 - finding = findings[3] - self.assertEqual("Critical", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-3011-32", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("Tom and Jerry versions 4 and 5 is vulnerable to Denial of Service (DoS) remote attack via the ever so long running series the simpsons", finding.description) - self.assertEqual("This vulnerability was addressed in Tom and Jerry Reboot 12.0 Affected users should upgrade to the latest stable version of Tom and Jerry.", finding.mitigation) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual("www.example43.com", endpoint.host) - self.assertEqual("tcp", endpoint.protocol) - self.assertEqual(443, endpoint.port) + with open(sample_path("many_vulns.csv")) as test_file: + parser = TrustwaveParser() + findings = parser.get_findings(test_file, test) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(len(findings), 4) + # finding 0 + finding = findings[0] + self.assertEqual("High", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-3011-123", finding.unsaved_vulnerability_ids[0]) + # finding 1 + finding = findings[1] + self.assertEqual("Tom and Jerry vulnerable to Mouse Traps", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-3011-321", finding.unsaved_vulnerability_ids[0]) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual("192.168.0.58", endpoint.host) + self.assertEqual("tcp", endpoint.protocol) + self.assertEqual(80, endpoint.port) + # finding 2 + finding = findings[2] + self.assertEqual("Medium", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-3011-313", finding.unsaved_vulnerability_ids[0]) + # finding 3 + finding = findings[3] + self.assertEqual("Critical", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-3011-32", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("Tom and Jerry versions 4 and 5 is vulnerable to Denial of Service (DoS) remote attack via the ever so long running series the simpsons", finding.description) + self.assertEqual("This vulnerability was addressed in Tom and Jerry Reboot 12.0 Affected users should upgrade to the latest stable version of Tom and Jerry.", finding.mitigation) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual("www.example43.com", endpoint.host) + self.assertEqual("tcp", endpoint.protocol) + self.assertEqual(443, endpoint.port) diff --git a/unittests/tools/test_veracode_parser.py b/unittests/tools/test_veracode_parser.py index 55799e9cf8..005cf3dbce 100644 --- a/unittests/tools/test_veracode_parser.py +++ b/unittests/tools/test_veracode_parser.py @@ -23,10 +23,10 @@ def test_parse_file_with_one_finding(self): self.parse_file_with_one_finding() def parse_file_with_one_finding(self): - testfile = open("unittests/scans/veracode/one_finding.xml") - parser = VeracodeParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) + with open("unittests/scans/veracode/one_finding.xml") as testfile: + parser = VeracodeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) @override_settings(USE_FIRST_SEEN=True) def test_parse_file_many_findings_different_hash_code_different_unique_id_first_seen(self): @@ -36,28 +36,28 @@ def test_parse_file_many_findings_different_hash_code_different_unique_id(self): self.parse_file_many_findings_different_hash_code_different_unique_id() def parse_file_many_findings_different_hash_code_different_unique_id(self): - testfile = open("unittests/scans/veracode/many_findings_different_hash_code_different_unique_id.xml") - parser = VeracodeParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(4, len(findings)) - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertEqual(123, finding.cwe) - self.assertEqual("catname", finding.title) - self.assertFalse(finding.is_mitigated) - self.assertEqual("sourcefilepathMyApp2.java", finding.file_path) - self.assertEqual(2, finding.line) - self.assertEqual("app-12345_issue-1", finding.unique_id_from_tool) - finding = findings[1] - self.assertEqual("Medium", finding.severity) - self.assertTrue(finding.dynamic_finding) - finding = findings[2] - self.assertEqual("High", finding.severity) - self.assertIsNone(finding.cwe) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-1234-1234", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("Vulnerable component: library:1234", finding.title) - self.assertFalse(finding.is_mitigated) + with open("unittests/scans/veracode/many_findings_different_hash_code_different_unique_id.xml") as testfile: + parser = VeracodeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(4, len(findings)) + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertEqual(123, finding.cwe) + self.assertEqual("catname", finding.title) + self.assertFalse(finding.is_mitigated) + self.assertEqual("sourcefilepathMyApp2.java", finding.file_path) + self.assertEqual(2, finding.line) + self.assertEqual("app-12345_issue-1", finding.unique_id_from_tool) + finding = findings[1] + self.assertEqual("Medium", finding.severity) + self.assertTrue(finding.dynamic_finding) + finding = findings[2] + self.assertEqual("High", finding.severity) + self.assertIsNone(finding.cwe) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-1234-1234", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("Vulnerable component: library:1234", finding.title) + self.assertFalse(finding.is_mitigated) @override_settings(USE_FIRST_SEEN=True) def test_parse_file_with_multiple_finding_first_seen(self): @@ -67,40 +67,40 @@ def test_parse_file_with_multiple_finding(self): self.parse_file_with_multiple_finding() def parse_file_with_multiple_finding(self): - testfile = open("unittests/scans/veracode/many_findings.xml") - parser = VeracodeParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(4, len(findings)) - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertEqual(123, finding.cwe) - self.assertEqual("catname", finding.title) - self.assertTrue(finding.static_finding) - self.assertFalse(finding.is_mitigated) - self.assertEqual("sourcefilepathMyApp.java", finding.file_path) - self.assertEqual(2, finding.line) - self.assertEqual("app-1234_issue-1", finding.unique_id_from_tool) - self.assertIn('sast', finding.unsaved_tags) - finding = findings[1] - self.assertEqual("Medium", finding.severity) - self.assertEqual(456, finding.cwe) - self.assertTrue(finding.dynamic_finding) - self.assertIn('dast', finding.unsaved_tags) - finding = findings[2] - self.assertEqual("High", finding.severity) - self.assertIsNone(finding.cwe) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-1234-1234", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("Vulnerable component: library:1234", finding.title) - self.assertFalse(finding.is_mitigated) - self.assertIn('sca', finding.unsaved_tags) - finding = findings[3] - self.assertEqual("High", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-5678-5678", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("Vulnerable component: library1:1234", finding.title) - self.assertFalse(finding.is_mitigated) - self.assertIn('sca', finding.unsaved_tags) + with open("unittests/scans/veracode/many_findings.xml") as testfile: + parser = VeracodeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(4, len(findings)) + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertEqual(123, finding.cwe) + self.assertEqual("catname", finding.title) + self.assertTrue(finding.static_finding) + self.assertFalse(finding.is_mitigated) + self.assertEqual("sourcefilepathMyApp.java", finding.file_path) + self.assertEqual(2, finding.line) + self.assertEqual("app-1234_issue-1", finding.unique_id_from_tool) + self.assertIn('sast', finding.unsaved_tags) + finding = findings[1] + self.assertEqual("Medium", finding.severity) + self.assertEqual(456, finding.cwe) + self.assertTrue(finding.dynamic_finding) + self.assertIn('dast', finding.unsaved_tags) + finding = findings[2] + self.assertEqual("High", finding.severity) + self.assertIsNone(finding.cwe) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-1234-1234", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("Vulnerable component: library:1234", finding.title) + self.assertFalse(finding.is_mitigated) + self.assertIn('sca', finding.unsaved_tags) + finding = findings[3] + self.assertEqual("High", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-5678-5678", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("Vulnerable component: library1:1234", finding.title) + self.assertFalse(finding.is_mitigated) + self.assertIn('sca', finding.unsaved_tags) @override_settings(USE_FIRST_SEEN=True) def test_parse_file_with_multiple_finding2_first_seen(self): @@ -112,31 +112,31 @@ def test_parse_file_with_multiple_finding2(self): self.assertEqual(datetime.datetime.today().date(), finding.date) def parse_file_with_multiple_finding2(self): - testfile = open("unittests/scans/veracode/veracode_scan.xml") - parser = VeracodeParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(7, len(findings)) - finding = findings[0] - self.assertEqual("Information Exposure Through Sent Data", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(201, finding.cwe) - finding = findings[1] - self.assertEqual("Low", finding.severity) - self.assertEqual(201, finding.cwe) - self.assertEqual("/devTools/utility.jsp", finding.file_path) - self.assertEqual(361, finding.line) - self.assertIsNone(finding.component_name) - self.assertIsNone(finding.component_version) - # finding 6 - finding = findings[6] - self.assertEqual("Medium", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2012-6153", finding.unsaved_vulnerability_ids[0]) - self.assertEqual(20, finding.cwe) - self.assertEqual("commons-httpclient", finding.component_name) - self.assertEqual("3.1", finding.component_version) - self.assertEqual(4.3, finding.cvssv3_score) - return findings[0] + with open("unittests/scans/veracode/veracode_scan.xml") as testfile: + parser = VeracodeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(7, len(findings)) + finding = findings[0] + self.assertEqual("Information Exposure Through Sent Data", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(201, finding.cwe) + finding = findings[1] + self.assertEqual("Low", finding.severity) + self.assertEqual(201, finding.cwe) + self.assertEqual("/devTools/utility.jsp", finding.file_path) + self.assertEqual(361, finding.line) + self.assertIsNone(finding.component_name) + self.assertIsNone(finding.component_version) + # finding 6 + finding = findings[6] + self.assertEqual("Medium", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2012-6153", finding.unsaved_vulnerability_ids[0]) + self.assertEqual(20, finding.cwe) + self.assertEqual("commons-httpclient", finding.component_name) + self.assertEqual("3.1", finding.component_version) + self.assertEqual(4.3, finding.cvssv3_score) + return findings[0] @override_settings(USE_FIRST_SEEN=True) def test_parse_file_with_mitigated_finding_first_seen(self): @@ -146,16 +146,16 @@ def test_parse_file_with_mitigated_finding(self): self.parse_file_with_mitigated_finding() def parse_file_with_mitigated_finding(self): - testfile = open("unittests/scans/veracode/mitigated_finding.xml") - parser = VeracodeParser() - findings = parser.get_findings(testfile, self.test) - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertTrue(finding.is_mitigated) - self.assertEqual(datetime.datetime(2020, 6, 1, 10, 2, 1), finding.mitigated) - self.assertEqual("app-1234_issue-1", finding.unique_id_from_tool) - self.assertEqual(0, finding.sla_age) + with open("unittests/scans/veracode/mitigated_finding.xml") as testfile: + parser = VeracodeParser() + findings = parser.get_findings(testfile, self.test) + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertTrue(finding.is_mitigated) + self.assertEqual(datetime.datetime(2020, 6, 1, 10, 2, 1), finding.mitigated) + self.assertEqual("app-1234_issue-1", finding.unique_id_from_tool) + self.assertEqual(0, finding.sla_age) @override_settings(USE_FIRST_SEEN=True) def test_parse_file_with_mitigated_fixed_finding_first_seen(self): @@ -165,14 +165,14 @@ def test_parse_file_with_mitigated_fixed_finding(self): self.parse_file_with_mitigated_fixed_finding() def parse_file_with_mitigated_fixed_finding(self): - testfile = open("unittests/scans/veracode/mitigated_fixed_finding.xml") - parser = VeracodeParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertTrue(finding.is_mitigated) - self.assertEqual("app-1234_issue-1", finding.unique_id_from_tool) + with open("unittests/scans/veracode/mitigated_fixed_finding.xml") as testfile: + parser = VeracodeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertTrue(finding.is_mitigated) + self.assertEqual("app-1234_issue-1", finding.unique_id_from_tool) @override_settings(USE_FIRST_SEEN=True) def test_parse_file_with_mitigated_sca_finding_first_seen(self): @@ -182,14 +182,14 @@ def test_parse_file_with_mitigated_sca_finding(self): self.parse_file_with_mitigated_sca_finding() def parse_file_with_mitigated_sca_finding(self): - testfile = open("unittests/scans/veracode/veracode_scan_sca_mitigated.xml") - parser = VeracodeParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("Critical", finding.severity) - self.assertTrue(finding.is_mitigated) - self.assertEqual(datetime.datetime(2022, 9, 12, 14, 29, 18), finding.mitigated) + with open("unittests/scans/veracode/veracode_scan_sca_mitigated.xml") as testfile: + parser = VeracodeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("Critical", finding.severity) + self.assertTrue(finding.is_mitigated) + self.assertEqual(datetime.datetime(2022, 9, 12, 14, 29, 18), finding.mitigated) @override_settings(USE_FIRST_SEEN=True) def test_parse_file_with_dynamic_finding_first_seen(self): @@ -201,24 +201,25 @@ def test_parse_file_with_dynamic_finding(self): self.assertEqual(datetime.datetime.today().date(), finding.date) def parse_file_with_dynamic_finding(self): - testfile = open("unittests/scans/veracode/dynamic_finding.xml") - parser = VeracodeParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertEqual(456, finding.cwe) - self.assertTrue(finding.dynamic_finding) - self.assertEqual("catname", finding.title) - self.assertEqual("Description", finding.description) - self.assertFalse(finding.is_mitigated) - self.assertIn('dast', finding.unsaved_tags) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual('https', endpoint.protocol) - self.assertEqual('www.example.com', endpoint.host) - self.assertEqual('index.html', endpoint.path) - return finding + with open("unittests/scans/veracode/dynamic_finding.xml") as testfile: + parser = VeracodeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertEqual(456, finding.cwe) + self.assertTrue(finding.dynamic_finding) + self.assertEqual("catname", finding.title) + self.assertEqual("Description", finding.description) + self.assertFalse(finding.is_mitigated) + self.assertIn('dast', finding.unsaved_tags) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual('https', endpoint.protocol) + self.assertEqual('www.example.com', endpoint.host) + self.assertEqual('index.html', endpoint.path) + + return finding @override_settings(USE_FIRST_SEEN=True) def test_parse_file_with_changed_severity_first_seen(self): @@ -228,19 +229,19 @@ def test_parse_file_with_changed_severity(self): self.parse_file_with_changed_severity() def parse_file_with_changed_severity(self): - testfile = open("unittests/scans/veracode/veracode_scan_changed_severity.xml") - parser = VeracodeParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(7, len(findings)) - # finding 6 - finding = findings[6] - self.assertEqual("Low", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2012-6153", finding.unsaved_vulnerability_ids[0]) - self.assertEqual(20, finding.cwe) - self.assertEqual("commons-httpclient", finding.component_name) - self.assertEqual("3.1", finding.component_version) - self.assertEqual(4.3, finding.cvssv3_score) + with open("unittests/scans/veracode/veracode_scan_changed_severity.xml") as testfile: + parser = VeracodeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(7, len(findings)) + # finding 6 + finding = findings[6] + self.assertEqual("Low", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2012-6153", finding.unsaved_vulnerability_ids[0]) + self.assertEqual(20, finding.cwe) + self.assertEqual("commons-httpclient", finding.component_name) + self.assertEqual("3.1", finding.component_version) + self.assertEqual(4.3, finding.cvssv3_score) @override_settings(USE_FIRST_SEEN=True) def test_maven_component_name_first_seen(self): @@ -250,74 +251,74 @@ def test_maven_component_name(self): self.maven_component_name() def maven_component_name(self): - testfile = open("unittests/scans/veracode/veracode_maven.xml") - parser = VeracodeParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - - finding = findings[0] - self.assertEqual("Critical", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2022-41852", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("commons-jxpath", finding.component_name) - self.assertEqual("1.3", finding.component_version) - self.assertEqual(9.8, finding.cvssv3_score) + with open("unittests/scans/veracode/veracode_maven.xml") as testfile: + parser = VeracodeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + + finding = findings[0] + self.assertEqual("Critical", finding.severity) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2022-41852", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("commons-jxpath", finding.component_name) + self.assertEqual("1.3", finding.component_version) + self.assertEqual(9.8, finding.cvssv3_score) def json_static_findings_test(self, file_name): - testfile = open(file_name) - parser = VeracodeParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(3, len(findings)) - finding = findings[0] - self.assertEqual(finding.title, "Cross-Site Scripting (XSS)") - self.assertEqual(finding.severity, "Medium") - self.assertEqual(finding.cwe, 80) - self.assertEqual(finding.description, ( - '### Meta Information\n' - '**Exploitability Predication**: Likely\n' - '**Attack Vector**: page.html\n' - '**Module**: CoolProduct.jsa\n' - '### Details\n' - 'This call to page.html() contains a cross-site scripting ' - '(XSS) flaw. The application populates the HTTP response with ' - 'untrusted input, allowing an attacker to embed malicious ' - 'content, such as Javascript code, which will be executed in ' - "the context of the victim's browser. XSS vulnerabilities are " - 'commonly exploited to steal or manipulate cookies, modify ' - 'presentation of content, and compromise confidential ' - 'information, with new attack vectors being discovered on a ' - 'regular basis.' - )) - self.assertEqual(finding.mitigation, ( - 'Use contextual escaping on all untrusted data before using it ' - 'to construct any portion of an HTTP response. The escaping ' - 'method should be chosen based on the specific use case of the ' - 'untrusted data, otherwise it may not protect fully against the ' - 'attack. For example, if the data is being written to the body ' - 'of an HTML page, use HTML entity escaping; if the data is ' - 'being written to an attribute, use attribute escaping; etc. ' - 'Both the OWASP Java Encoder library and the Microsoft AntiXSS ' - 'library provide contextual escaping methods. For more details ' - 'on contextual escaping, see ' - 'https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.md. ' - 'In addition, as a best practice, always validate untrusted ' - 'input to ensure that it conforms to the expected format, using ' - 'centralized data validation routines when possible.' - )) - self.assertEqual(finding.references, ( - '- [CWE](https://cwe.mitre.org/data/definitions/79.html)\n' - '- [OWASP](https://owasp.org/www-community/attacks/xss/)\n' - '- [Supported Cleansers](https://docs.veracode.com/r/review_cleansers)\n' - )) - self.assertEqual(finding.line, 50) - self.assertEqual(finding.sast_source_line, 50) - self.assertEqual(finding.sast_sink_line, 50) - self.assertEqual(finding.file_path, "/WEB-INF/views/contact.jsp") - self.assertEqual(finding.sast_source_file_path, "/WEB-INF/views/contact.jsp") - self.assertEqual(finding.sast_sink_file_path, "/WEB-INF/views/contact.jsp") - self.assertEqual(finding.sast_source_object, "lambda_3") - self.assertEqual(finding.sast_sink_object, "lambda_3") - self.assertEqual(finding.unsaved_tags, ["policy-violation"]) + with open(file_name) as testfile: + parser = VeracodeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(3, len(findings)) + finding = findings[0] + self.assertEqual(finding.title, "Cross-Site Scripting (XSS)") + self.assertEqual(finding.severity, "Medium") + self.assertEqual(finding.cwe, 80) + self.assertEqual(finding.description, ( + '### Meta Information\n' + '**Exploitability Predication**: Likely\n' + '**Attack Vector**: page.html\n' + '**Module**: CoolProduct.jsa\n' + '### Details\n' + 'This call to page.html() contains a cross-site scripting ' + '(XSS) flaw. The application populates the HTTP response with ' + 'untrusted input, allowing an attacker to embed malicious ' + 'content, such as Javascript code, which will be executed in ' + "the context of the victim's browser. XSS vulnerabilities are " + 'commonly exploited to steal or manipulate cookies, modify ' + 'presentation of content, and compromise confidential ' + 'information, with new attack vectors being discovered on a ' + 'regular basis.' + )) + self.assertEqual(finding.mitigation, ( + 'Use contextual escaping on all untrusted data before using it ' + 'to construct any portion of an HTTP response. The escaping ' + 'method should be chosen based on the specific use case of the ' + 'untrusted data, otherwise it may not protect fully against the ' + 'attack. For example, if the data is being written to the body ' + 'of an HTML page, use HTML entity escaping; if the data is ' + 'being written to an attribute, use attribute escaping; etc. ' + 'Both the OWASP Java Encoder library and the Microsoft AntiXSS ' + 'library provide contextual escaping methods. For more details ' + 'on contextual escaping, see ' + 'https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.md. ' + 'In addition, as a best practice, always validate untrusted ' + 'input to ensure that it conforms to the expected format, using ' + 'centralized data validation routines when possible.' + )) + self.assertEqual(finding.references, ( + '- [CWE](https://cwe.mitre.org/data/definitions/79.html)\n' + '- [OWASP](https://owasp.org/www-community/attacks/xss/)\n' + '- [Supported Cleansers](https://docs.veracode.com/r/review_cleansers)\n' + )) + self.assertEqual(finding.line, 50) + self.assertEqual(finding.sast_source_line, 50) + self.assertEqual(finding.sast_sink_line, 50) + self.assertEqual(finding.file_path, "/WEB-INF/views/contact.jsp") + self.assertEqual(finding.sast_source_file_path, "/WEB-INF/views/contact.jsp") + self.assertEqual(finding.sast_sink_file_path, "/WEB-INF/views/contact.jsp") + self.assertEqual(finding.sast_source_object, "lambda_3") + self.assertEqual(finding.sast_sink_object, "lambda_3") + self.assertEqual(finding.unsaved_tags, ["policy-violation"]) @override_settings(USE_FIRST_SEEN=True) def test_json_static_findings_list_format_first_seen(self): @@ -340,56 +341,56 @@ def json_static_embedded_format(self): self.json_static_findings_test("unittests/scans/veracode/static_embedded_format.json") def json_dynamic_findings_test(self, file_name): - testfile = open(file_name) - parser = VeracodeParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(3, len(findings)) - finding = findings[0] - self.assertEqual(finding.title, "Code Injection") - self.assertEqual(finding.severity, "High") - self.assertEqual(finding.cwe, 74) - self.assertEqual(finding.description, ( - '### Meta Information\n' - '**Plugin**: Code Injection\n' - '**Attack Vector**: Improper Neutralization of Special ' - 'Elements in Output Used by a Downstream Component ' - "('Injection')\n" - '**Vulnerable Parameter**: api\n' - '### Details\n' - 'Injections happen when untrusted data is inserted into an ' - 'interpreted syntax and subsequently evaluated on the server ' - 'side. This syntax may be a SQL query, a parsed JSON or XML ' - 'document, an executed script or other syntax that may be in ' - 'use within the application. Although the target syntax has ' - 'not been identified, the application behavior demonstrates ' - 'that the input HTTP parameter may be inserted without proper ' - 'escaping. It was observed by sending valid and invalid ' - 'payloads that should throw or should not throw errors. By ' - 'inserting a proper and improper comments such as ``, `*/_/*`, ' - '`/*_*/` into the `api` parameter, the scanner was able to ' - 'spot a difference in the responses, which is a good indicator ' - 'of a potential vulnerability. Confidence: medium. Response ' - 'codes: `404`, `404`, `404`. Similarities: `` vs `*/_/*`: 0.0; ' - '`*/_/*` vs `/*_*/`: 0.0; `` vs `/*_*/`: 1.0.' - )) - self.assertEqual(finding.mitigation, ( - 'It is recommended to identify how the current parameter is ' - 'used in the application source code, and make sure it is ' - 'escaped before inserting into any syntax or query. You can add ' - 'valid values to an allowlist and invalid values to a ' - 'blocklist.' - )) - self.assertEqual(finding.references, ( - '- [CWE](http://cwe.mitre.org/cgi-bin/jumpmenu.cgi?id=74)\n' - )) - self.assertEqual(finding.unsaved_tags, ["policy-violation"]) - self.assertEqual(finding.unsaved_endpoints[0], Endpoint( - protocol="https", - host="application.insecure-company-alliance.com", - port=443, - path="api/*_*//new_user_sign_up", - query="param=wild-things" - )) + with open(file_name) as testfile: + parser = VeracodeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(3, len(findings)) + finding = findings[0] + self.assertEqual(finding.title, "Code Injection") + self.assertEqual(finding.severity, "High") + self.assertEqual(finding.cwe, 74) + self.assertEqual(finding.description, ( + '### Meta Information\n' + '**Plugin**: Code Injection\n' + '**Attack Vector**: Improper Neutralization of Special ' + 'Elements in Output Used by a Downstream Component ' + "('Injection')\n" + '**Vulnerable Parameter**: api\n' + '### Details\n' + 'Injections happen when untrusted data is inserted into an ' + 'interpreted syntax and subsequently evaluated on the server ' + 'side. This syntax may be a SQL query, a parsed JSON or XML ' + 'document, an executed script or other syntax that may be in ' + 'use within the application. Although the target syntax has ' + 'not been identified, the application behavior demonstrates ' + 'that the input HTTP parameter may be inserted without proper ' + 'escaping. It was observed by sending valid and invalid ' + 'payloads that should throw or should not throw errors. By ' + 'inserting a proper and improper comments such as ``, `*/_/*`, ' + '`/*_*/` into the `api` parameter, the scanner was able to ' + 'spot a difference in the responses, which is a good indicator ' + 'of a potential vulnerability. Confidence: medium. Response ' + 'codes: `404`, `404`, `404`. Similarities: `` vs `*/_/*`: 0.0; ' + '`*/_/*` vs `/*_*/`: 0.0; `` vs `/*_*/`: 1.0.' + )) + self.assertEqual(finding.mitigation, ( + 'It is recommended to identify how the current parameter is ' + 'used in the application source code, and make sure it is ' + 'escaped before inserting into any syntax or query. You can add ' + 'valid values to an allowlist and invalid values to a ' + 'blocklist.' + )) + self.assertEqual(finding.references, ( + '- [CWE](http://cwe.mitre.org/cgi-bin/jumpmenu.cgi?id=74)\n' + )) + self.assertEqual(finding.unsaved_tags, ["policy-violation"]) + self.assertEqual(finding.unsaved_endpoints[0], Endpoint( + protocol="https", + host="application.insecure-company-alliance.com", + port=443, + path="api/*_*//new_user_sign_up", + query="param=wild-things" + )) @override_settings(USE_FIRST_SEEN=True) def test_json_dynamic_findings_list_format_first_seen(self): @@ -412,73 +413,73 @@ def json_dynamic_embedded_format(self): self.json_dynamic_findings_test("unittests/scans/veracode/dynamic_embedded_format.json") def json_sca_findings_test(self, file_name): - testfile = open(file_name) - parser = VeracodeParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(7, len(findings)) - finding = findings[0] - self.assertEqual(finding.title, "Uncontrolled Resource Consumption") - self.assertEqual(finding.severity, "High") - self.assertEqual(finding.cwe, 400) - self.assertEqual(finding.description, ( - '### Meta Information\n' - '**Product ID**: abc123-bca321\n' - '**Component ID**: efg456-gfe654\n' - '**Language**: JAVA\n' - '#### Component Locations\n' - '- path/to/alpha/spring-boot-autoconfigure-2.5.14.jar\n' - '- path/to/beta/spring-boot-autoconfigure-2.5.14.jar\n' - '- path/to/charlie/spring-boot-autoconfigure-2.5.14.jar\n' - '- path/to/delta/spring-boot-autoconfigure-2.5.14.jar\n' - '#### Licenses\n' - '- apache-2.0: Low\n' - ' - Low-risk licenses are typically permissive licenses ' - 'that require you to preserve the copyright and license ' - 'notices, but allow distribution under different terms without ' - 'disclosing source code.\n' - '### Details\n' - 'spring-boot-autoconfigure is vulnerable to Denial Of Service ' - '(DoS). The vulnerability is applicable when the application ' - 'has Spring MVC auto-configuration enabled and uses the Spring ' - 'Boot welcome page, which can be either static or templated, ' - 'and the application is deployed behind a proxy which caches ' - 'the 404 responses. An attacker can cause the application to ' - 'crash by submitting a request to the welcome page which the ' - 'server is unable to properly respond to.' - )) - self.assertEqual(finding.cvssv3, "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H") - self.assertEqual(finding.component_name, "spring-boot-autoconfigure.jar") - self.assertEqual(finding.component_version, "2.5.14") - self.assertEqual(finding.unsaved_tags, ["policy-violation"]) - self.assertEqual(finding.unsaved_vulnerability_ids, ["CVE-2023-20883"]) - finding = findings[3] - self.assertEqual(finding.title, "inflight - SRCCLR-SID-41137") - self.assertEqual(finding.severity, "Medium") - self.assertEqual(finding.cwe, 0) - self.assertEqual(finding.description, ( - '### Meta Information\n' - '**Product ID**: abc123-bca321\n' - '**Component ID**: efg456-gfe654\n' - '**Language**: JAVASCRIPT\n' - '#### Component Locations\n' - '- path/to/alpha/node_modules:inflight\n' - '#### Licenses\n' - '- isc: Low\n' - ' - Low-risk licenses are typically permissive licenses ' - 'that require you to preserve the copyright and license ' - 'notices, but allow distribution under different terms without ' - 'disclosing source code.\n' - '### Details\n' - 'inflight is vulnerable to a Memory Leak. The vulnerability is ' - 'caused by improper memory management due to a lack of ' - 'resource freeing, which can result in Denial of Service ' - 'conditions.' - )) - self.assertEqual(finding.cvssv3, "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H") - self.assertEqual(finding.component_name, "inflight") - self.assertEqual(finding.component_version, "1.0.6") - self.assertEqual(finding.unsaved_tags, ["policy-violation"]) - self.assertEqual(finding.unsaved_vulnerability_ids, ["SRCCLR-SID-41137"]) + with open(file_name) as testfile: + parser = VeracodeParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(7, len(findings)) + finding = findings[0] + self.assertEqual(finding.title, "Uncontrolled Resource Consumption") + self.assertEqual(finding.severity, "High") + self.assertEqual(finding.cwe, 400) + self.assertEqual(finding.description, ( + '### Meta Information\n' + '**Product ID**: abc123-bca321\n' + '**Component ID**: efg456-gfe654\n' + '**Language**: JAVA\n' + '#### Component Locations\n' + '- path/to/alpha/spring-boot-autoconfigure-2.5.14.jar\n' + '- path/to/beta/spring-boot-autoconfigure-2.5.14.jar\n' + '- path/to/charlie/spring-boot-autoconfigure-2.5.14.jar\n' + '- path/to/delta/spring-boot-autoconfigure-2.5.14.jar\n' + '#### Licenses\n' + '- apache-2.0: Low\n' + ' - Low-risk licenses are typically permissive licenses ' + 'that require you to preserve the copyright and license ' + 'notices, but allow distribution under different terms without ' + 'disclosing source code.\n' + '### Details\n' + 'spring-boot-autoconfigure is vulnerable to Denial Of Service ' + '(DoS). The vulnerability is applicable when the application ' + 'has Spring MVC auto-configuration enabled and uses the Spring ' + 'Boot welcome page, which can be either static or templated, ' + 'and the application is deployed behind a proxy which caches ' + 'the 404 responses. An attacker can cause the application to ' + 'crash by submitting a request to the welcome page which the ' + 'server is unable to properly respond to.' + )) + self.assertEqual(finding.cvssv3, "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H") + self.assertEqual(finding.component_name, "spring-boot-autoconfigure.jar") + self.assertEqual(finding.component_version, "2.5.14") + self.assertEqual(finding.unsaved_tags, ["policy-violation"]) + self.assertEqual(finding.unsaved_vulnerability_ids, ["CVE-2023-20883"]) + finding = findings[3] + self.assertEqual(finding.title, "inflight - SRCCLR-SID-41137") + self.assertEqual(finding.severity, "Medium") + self.assertEqual(finding.cwe, 0) + self.assertEqual(finding.description, ( + '### Meta Information\n' + '**Product ID**: abc123-bca321\n' + '**Component ID**: efg456-gfe654\n' + '**Language**: JAVASCRIPT\n' + '#### Component Locations\n' + '- path/to/alpha/node_modules:inflight\n' + '#### Licenses\n' + '- isc: Low\n' + ' - Low-risk licenses are typically permissive licenses ' + 'that require you to preserve the copyright and license ' + 'notices, but allow distribution under different terms without ' + 'disclosing source code.\n' + '### Details\n' + 'inflight is vulnerable to a Memory Leak. The vulnerability is ' + 'caused by improper memory management due to a lack of ' + 'resource freeing, which can result in Denial of Service ' + 'conditions.' + )) + self.assertEqual(finding.cvssv3, "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H") + self.assertEqual(finding.component_name, "inflight") + self.assertEqual(finding.component_version, "1.0.6") + self.assertEqual(finding.unsaved_tags, ["policy-violation"]) + self.assertEqual(finding.unsaved_vulnerability_ids, ["SRCCLR-SID-41137"]) @override_settings(USE_FIRST_SEEN=True) def test_json_sca_findings_list_format_first_seen(self): diff --git a/unittests/tools/test_veracode_sca_parser.py b/unittests/tools/test_veracode_sca_parser.py index ef453d9451..6820cf0490 100644 --- a/unittests/tools/test_veracode_sca_parser.py +++ b/unittests/tools/test_veracode_sca_parser.py @@ -18,46 +18,46 @@ def test_parse_csv(self): self.parse_csv() def parse_csv(self): - testfile = open("unittests/scans/veracode_sca/veracode_sca.csv") - parser = VeracodeScaParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(3, len(findings)) - - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertTrue(finding.active) - self.assertFalse(finding.is_mitigated) - self.assertEqual("aws-java-sdk-s3", finding.component_name) - self.assertEqual("1.11.951", finding.component_version) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2022-31159", finding.unsaved_vulnerability_ids[0]) - self.assertEqual(6.4, finding.cvssv3_score) - self.assertEqual("127637430", finding.unique_id_from_tool) - self.assertEqual(datetime.datetime(2022, 7, 7, 9, 15, 0), finding.date) - - finding = findings[1] - self.assertEqual("Medium", finding.severity) - self.assertTrue(finding.active) - self.assertFalse(finding.is_mitigated) - self.assertEqual("spring-cloud-function-context", finding.component_name) - self.assertEqual("3.2.5", finding.component_version) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2022-22979", finding.unsaved_vulnerability_ids[0]) - self.assertEqual(5, finding.cvssv3_score) - self.assertEqual("122648496", finding.unique_id_from_tool) - self.assertEqual(datetime.datetime(2022, 6, 14, 11, 34, 0), finding.date) - - finding = findings[2] - self.assertEqual("High", finding.severity) - self.assertFalse(finding.active) - self.assertTrue(finding.is_mitigated) - self.assertEqual("commons-configuration2", finding.component_name) - self.assertEqual("2.1.1", finding.component_version) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2022-33980", finding.unsaved_vulnerability_ids[0]) - self.assertEqual(7.5, finding.cvssv3_score) - self.assertEqual("126041205", finding.unique_id_from_tool) - self.assertEqual(datetime.datetime(2022, 7, 2, 23, 19, 0), finding.date) + with open("unittests/scans/veracode_sca/veracode_sca.csv") as testfile: + parser = VeracodeScaParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(3, len(findings)) + + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertTrue(finding.active) + self.assertFalse(finding.is_mitigated) + self.assertEqual("aws-java-sdk-s3", finding.component_name) + self.assertEqual("1.11.951", finding.component_version) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2022-31159", finding.unsaved_vulnerability_ids[0]) + self.assertEqual(6.4, finding.cvssv3_score) + self.assertEqual("127637430", finding.unique_id_from_tool) + self.assertEqual(datetime.datetime(2022, 7, 7, 9, 15, 0), finding.date) + + finding = findings[1] + self.assertEqual("Medium", finding.severity) + self.assertTrue(finding.active) + self.assertFalse(finding.is_mitigated) + self.assertEqual("spring-cloud-function-context", finding.component_name) + self.assertEqual("3.2.5", finding.component_version) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2022-22979", finding.unsaved_vulnerability_ids[0]) + self.assertEqual(5, finding.cvssv3_score) + self.assertEqual("122648496", finding.unique_id_from_tool) + self.assertEqual(datetime.datetime(2022, 6, 14, 11, 34, 0), finding.date) + + finding = findings[2] + self.assertEqual("High", finding.severity) + self.assertFalse(finding.active) + self.assertTrue(finding.is_mitigated) + self.assertEqual("commons-configuration2", finding.component_name) + self.assertEqual("2.1.1", finding.component_version) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2022-33980", finding.unsaved_vulnerability_ids[0]) + self.assertEqual(7.5, finding.cvssv3_score) + self.assertEqual("126041205", finding.unique_id_from_tool) + self.assertEqual(datetime.datetime(2022, 7, 2, 23, 19, 0), finding.date) @override_settings(USE_FIRST_SEEN=True) def test_parse_json_first_seen(self): @@ -67,23 +67,23 @@ def test_parse_json(self): self.parse_json() def parse_json(self): - testfile = open("unittests/scans/veracode_sca/veracode_sca.json") - parser = VeracodeScaParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - - finding = findings[0] - self.assertEqual("High", finding.severity) - self.assertTrue(finding.active) - self.assertFalse(finding.is_mitigated) - self.assertEqual("avatica-core", finding.component_name) - self.assertEqual("1.11.0", finding.component_version) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2022-36364", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", finding.cvssv3) - self.assertEqual(665, finding.cwe) - self.assertEqual("ddcc6e1b-3ed9-45c8-b77a-ead759fb5e2c", finding.unique_id_from_tool) - self.assertEqual(datetime.datetime(2022, 7, 29, 5, 13, 0, 924000).astimezone(UTC), finding.date) + with open("unittests/scans/veracode_sca/veracode_sca.json") as testfile: + parser = VeracodeScaParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + + finding = findings[0] + self.assertEqual("High", finding.severity) + self.assertTrue(finding.active) + self.assertFalse(finding.is_mitigated) + self.assertEqual("avatica-core", finding.component_name) + self.assertEqual("1.11.0", finding.component_version) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2022-36364", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", finding.cvssv3) + self.assertEqual(665, finding.cwe) + self.assertEqual("ddcc6e1b-3ed9-45c8-b77a-ead759fb5e2c", finding.unique_id_from_tool) + self.assertEqual(datetime.datetime(2022, 7, 29, 5, 13, 0, 924000).astimezone(UTC), finding.date) @override_settings(USE_FIRST_SEEN=True) def test_parse_json_fixed_first_seen(self): @@ -93,19 +93,19 @@ def test_parse_json_fixed(self): self.parse_json_fixed() def parse_json_fixed(self): - testfile = open("unittests/scans/veracode_sca/veracode_sca_fixed.json") - parser = VeracodeScaParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) - - finding = findings[0] - self.assertEqual("Medium", finding.severity) - self.assertFalse(finding.active) - self.assertTrue(finding.is_mitigated) - self.assertEqual("aws-java-sdk-s3", finding.component_name) - self.assertEqual("1.11.951", finding.component_version) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2022-31159", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N", finding.cvssv3) - self.assertEqual(22, finding.cwe) - self.assertEqual(datetime.date.today(), finding.mitigated.date()) + with open("unittests/scans/veracode_sca/veracode_sca_fixed.json") as testfile: + parser = VeracodeScaParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertFalse(finding.active) + self.assertTrue(finding.is_mitigated) + self.assertEqual("aws-java-sdk-s3", finding.component_name) + self.assertEqual("1.11.951", finding.component_version) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2022-31159", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N", finding.cvssv3) + self.assertEqual(22, finding.cwe) + self.assertEqual(datetime.date.today(), finding.mitigated.date()) diff --git a/unittests/tools/test_wapiti_parser.py b/unittests/tools/test_wapiti_parser.py index c286388213..5c4373aa7d 100644 --- a/unittests/tools/test_wapiti_parser.py +++ b/unittests/tools/test_wapiti_parser.py @@ -7,61 +7,61 @@ class TestWapitiParser(DojoTestCase): def test_parse_file_3_0_4(self): """Generated with version 3.0.4 on OWASP Juicy Shop""" - testfile = open("unittests/scans/wapiti/juicyshop.xml") - parser = WapitiParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(3, len(findings)) - finding = findings[0] - self.assertEqual("Content Security Policy Configuration: CSP is not set", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual("Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross Site Scripting (XSS) and data injection attacks.", finding.description) - self.assertEqual("Configuring Content Security Policy involves adding the Content-Security-Policy HTTP header to a web page and giving it values to control what resources the user agent is allowed to load for that page.", finding.mitigation) - finding = findings[1] - self.assertEqual("HTTP Secure Headers: X-XSS-Protection is not set", finding.title) - self.assertEqual("Low", finding.severity) - finding = findings[2] - self.assertEqual("HTTP Secure Headers: Strict-Transport-Security is not set", finding.title) - self.assertEqual("Low", finding.severity) + with open("unittests/scans/wapiti/juicyshop.xml") as testfile: + parser = WapitiParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(3, len(findings)) + finding = findings[0] + self.assertEqual("Content Security Policy Configuration: CSP is not set", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual("Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross Site Scripting (XSS) and data injection attacks.", finding.description) + self.assertEqual("Configuring Content Security Policy involves adding the Content-Security-Policy HTTP header to a web page and giving it values to control what resources the user agent is allowed to load for that page.", finding.mitigation) + finding = findings[1] + self.assertEqual("HTTP Secure Headers: X-XSS-Protection is not set", finding.title) + self.assertEqual("Low", finding.severity) + finding = findings[2] + self.assertEqual("HTTP Secure Headers: Strict-Transport-Security is not set", finding.title) + self.assertEqual("Low", finding.severity) def test_parse_file_demo(self): """""" - testfile = open("unittests/scans/wapiti/demo.xml") - parser = WapitiParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(3, len(findings)) - finding = findings[2] - self.assertEqual("Secure Flag cookie: Secure flag is not set in the cookie : csrftoken", finding.title) - self.assertEqual("Low", finding.severity) + with open("unittests/scans/wapiti/demo.xml") as testfile: + parser = WapitiParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(3, len(findings)) + finding = findings[2] + self.assertEqual("Secure Flag cookie: Secure flag is not set in the cookie : csrftoken", finding.title) + self.assertEqual("Low", finding.severity) def test_parse_file_example(self): """""" - testfile = open("unittests/scans/wapiti/example.xml") - parser = WapitiParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(5, len(findings)) - finding = findings[2] - self.assertEqual("HTTP Secure Headers: X-XSS-Protection is not set", finding.title) - self.assertEqual("Low", finding.severity) + with open("unittests/scans/wapiti/example.xml") as testfile: + parser = WapitiParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(5, len(findings)) + finding = findings[2] + self.assertEqual("HTTP Secure Headers: X-XSS-Protection is not set", finding.title) + self.assertEqual("Low", finding.severity) def test_parse_cwe(self): """File to test CWE""" - testfile = open("unittests/scans/wapiti/cwe.xml") - parser = WapitiParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("Cross Site Request Forgery: CSP is not set", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual(352, finding.cwe) + with open("unittests/scans/wapiti/cwe.xml") as testfile: + parser = WapitiParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("Cross Site Request Forgery: CSP is not set", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual(352, finding.cwe) diff --git a/unittests/tools/test_wazuh_parser.py b/unittests/tools/test_wazuh_parser.py index ce408518ed..4f4bcfbb81 100644 --- a/unittests/tools/test_wazuh_parser.py +++ b/unittests/tools/test_wazuh_parser.py @@ -6,48 +6,48 @@ class TestWazuhParser(DojoTestCase): def test_parse_no_findings(self): - testfile = open("unittests/scans/wazuh/no_findings.json") - parser = WazuhParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/wazuh/no_findings.json") as testfile: + parser = WazuhParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_one_finding(self): - testfile = open("unittests/scans/wazuh/one_finding.json") - parser = WazuhParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - self.assertEqual("Medium", finding.severity) - self.assertEqual("CVE-1234-123123", finding.unsaved_vulnerability_ids) - self.assertEqual("asdf", finding.component_name) - self.assertEqual("4.3.1", finding.component_version) - self.assertEqual(5.5, finding.cvssv3_score) + with open("unittests/scans/wazuh/one_finding.json") as testfile: + parser = WazuhParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + self.assertEqual("Medium", finding.severity) + self.assertEqual("CVE-1234-123123", finding.unsaved_vulnerability_ids) + self.assertEqual("asdf", finding.component_name) + self.assertEqual("4.3.1", finding.component_version) + self.assertEqual(5.5, finding.cvssv3_score) def test_parse_many_finding(self): - testfile = open("unittests/scans/wazuh/many_findings.json") - parser = WazuhParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(6, len(findings)) - self.assertEqual("2023-02-08", finding.date) + with open("unittests/scans/wazuh/many_findings.json") as testfile: + parser = WazuhParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(6, len(findings)) + self.assertEqual("2023-02-08", finding.date) def test_parse_one_finding_with_endpoint(self): - testfile = open("unittests/scans/wazuh/one_finding_with_endpoint.json") - parser = WazuhParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - self.assertEqual("Medium", finding.severity) - self.assertEqual("CVE-1234-1234", finding.unsaved_vulnerability_ids) - self.assertEqual(6.5, finding.cvssv3_score) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual("agent-1", endpoint.host) - self.assertEqual("asdf", finding.component_name) - self.assertEqual("1", finding.component_version) - self.assertEqual("2023-12-13", finding.date) + with open("unittests/scans/wazuh/one_finding_with_endpoint.json") as testfile: + parser = WazuhParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + self.assertEqual("Medium", finding.severity) + self.assertEqual("CVE-1234-1234", finding.unsaved_vulnerability_ids) + self.assertEqual(6.5, finding.cvssv3_score) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual("agent-1", endpoint.host) + self.assertEqual("asdf", finding.component_name) + self.assertEqual("1", finding.component_version) + self.assertEqual("2023-12-13", finding.date) diff --git a/unittests/tools/test_wfuzz_parser.py b/unittests/tools/test_wfuzz_parser.py index 05eb69eeba..58f0b12dcb 100644 --- a/unittests/tools/test_wfuzz_parser.py +++ b/unittests/tools/test_wfuzz_parser.py @@ -6,53 +6,53 @@ class TestWFuzzParser(DojoTestCase): def test_parse_no_findings(self): - testfile = open("unittests/scans/wfuzz/no_findings.json") - parser = WFuzzParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/wfuzz/no_findings.json") as testfile: + parser = WFuzzParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_one_finding(self): - testfile = open("unittests/scans/wfuzz/one_finding.json") - parser = WFuzzParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) + with open("unittests/scans/wfuzz/one_finding.json") as testfile: + parser = WFuzzParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) def test_parse_many_finding(self): - testfile = open("unittests/scans/wfuzz/many_findings.json") - parser = WFuzzParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(4, len(findings)) + with open("unittests/scans/wfuzz/many_findings.json") as testfile: + parser = WFuzzParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(4, len(findings)) def test_one_dup_finding(self): - testfile = open("unittests/scans/wfuzz/one_dup_finding.json") - parser = WFuzzParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(4, len(findings)) + with open("unittests/scans/wfuzz/one_dup_finding.json") as testfile: + parser = WFuzzParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(4, len(findings)) def test_issue_7863(self): - testfile = open("unittests/scans/wfuzz/issue_7863.json") - parser = WFuzzParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - self.assertEqual("Medium", findings[0].severity) + with open("unittests/scans/wfuzz/issue_7863.json") as testfile: + parser = WFuzzParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + self.assertEqual("Medium", findings[0].severity) def test_one_finding_responsecode_missing(self): - testfile = open("unittests/scans/wfuzz/one_finding_responsecode_missing.json") - parser = WFuzzParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) + with open("unittests/scans/wfuzz/one_finding_responsecode_missing.json") as testfile: + parser = WFuzzParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) diff --git a/unittests/tools/test_whitehat_sentinel_parser.py b/unittests/tools/test_whitehat_sentinel_parser.py index 6683da4bcd..e5b6b68533 100644 --- a/unittests/tools/test_whitehat_sentinel_parser.py +++ b/unittests/tools/test_whitehat_sentinel_parser.py @@ -8,24 +8,24 @@ class TestWhiteHatSentinelParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): with self.assertRaises(ValueError): - testfile = open("unittests/scans/whitehat_sentinel/empty_file.json") - parser = WhiteHatSentinelParser() - parser.get_findings(testfile, Test()) + with open("unittests/scans/whitehat_sentinel/empty_file.json") as testfile: + parser = WhiteHatSentinelParser() + parser.get_findings(testfile, Test()) def test_parse_file_with_one_vuln_has_one_findings(self): - testfile = open("unittests/scans/whitehat_sentinel/one_vuln.json") - parser = WhiteHatSentinelParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) + with open("unittests/scans/whitehat_sentinel/one_vuln.json") as testfile: + parser = WhiteHatSentinelParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) def test_parse_file_with_multiple_vuln_has_multiple_finding(self): - testfile = open("unittests/scans/whitehat_sentinel/many_vuln.json") - parser = WhiteHatSentinelParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(3, len(findings)) + with open("unittests/scans/whitehat_sentinel/many_vuln.json") as testfile: + parser = WhiteHatSentinelParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(3, len(findings)) def test_parse_file_with_invalid_data(self): with self.assertRaises(ValueError): - testfile = open("unittests/scans/whitehat_sentinel/invalid_data.txt") - parser = WhiteHatSentinelParser() - parser.get_findings(testfile, Test()) + with open("unittests/scans/whitehat_sentinel/invalid_data.txt") as testfile: + parser = WhiteHatSentinelParser() + parser.get_findings(testfile, Test()) diff --git a/unittests/tools/test_wiz_parser.py b/unittests/tools/test_wiz_parser.py index 36b422410a..5b1c91f733 100644 --- a/unittests/tools/test_wiz_parser.py +++ b/unittests/tools/test_wiz_parser.py @@ -5,40 +5,40 @@ class TestWizParser(DojoTestCase): def test_no_findings(self): - testfile = open("unittests/scans/wiz/no_findings.csv") - parser = WizParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(0, len(findings)) + with open("unittests/scans/wiz/no_findings.csv") as testfile: + parser = WizParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(0, len(findings)) def test_one_findings(self): - testfile = open("unittests/scans/wiz/one_finding.csv") - parser = WizParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(1, len(findings)) - finding = findings[0] - self.assertEqual("AKS role/cluster role assigned permissions that contain wildcards ", finding.title) - self.assertEqual("Informational", finding.severity) + with open("unittests/scans/wiz/one_finding.csv") as testfile: + parser = WizParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(1, len(findings)) + finding = findings[0] + self.assertEqual("AKS role/cluster role assigned permissions that contain wildcards ", finding.title) + self.assertEqual("Informational", finding.severity) def test_multiple_findings(self): - testfile = open("unittests/scans/wiz/multiple_findings.csv") - parser = WizParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(98, len(findings)) - finding = findings[0] - self.assertEqual("AKS role/cluster role assigned permissions that contain wildcards ", finding.title) - self.assertEqual("Informational", finding.severity) - finding = findings[1] - self.assertEqual("Unusual activity by a principal from previously unseen country", finding.title) - self.assertEqual("High", finding.severity) - finding = findings[20] - self.assertEqual("User/service account with get/list/watch permissions on secrets in an AKS cluster", finding.title) - self.assertEqual("Informational", finding.severity) + with open("unittests/scans/wiz/multiple_findings.csv") as testfile: + parser = WizParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(98, len(findings)) + finding = findings[0] + self.assertEqual("AKS role/cluster role assigned permissions that contain wildcards ", finding.title) + self.assertEqual("Informational", finding.severity) + finding = findings[1] + self.assertEqual("Unusual activity by a principal from previously unseen country", finding.title) + self.assertEqual("High", finding.severity) + finding = findings[20] + self.assertEqual("User/service account with get/list/watch permissions on secrets in an AKS cluster", finding.title) + self.assertEqual("Informational", finding.severity) diff --git a/unittests/tools/test_wpscan_parser.py b/unittests/tools/test_wpscan_parser.py index b001772ad4..e2dca4b5c8 100644 --- a/unittests/tools/test_wpscan_parser.py +++ b/unittests/tools/test_wpscan_parser.py @@ -10,145 +10,145 @@ class TestWpscanParser(DojoTestCase): def test_parse_file_empty(self): """Report from the tool wich have no data""" - testfile = open("unittests/scans/wpscan/empty.json") - parser = WpscanParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/wpscan/empty.json") as testfile: + parser = WpscanParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_exemple(self): - testfile = open("unittests/scans/wpscan/sample.json") - parser = WpscanParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(4, len(findings)) - finding = findings[0] - self.assertIsNone(finding.unique_id_from_tool) # interesting findings are not vlunerability - self.assertEqual("Info", finding.severity) # it is not a vulnerability so severity should be 'Info' - self.assertEqual("Interesting finding: Headers", finding.title) - self.assertEqual(datetime.datetime(2021, 3, 26, 11, 50, 50), finding.date) + with open("unittests/scans/wpscan/sample.json") as testfile: + parser = WpscanParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(4, len(findings)) + finding = findings[0] + self.assertIsNone(finding.unique_id_from_tool) # interesting findings are not vlunerability + self.assertEqual("Info", finding.severity) # it is not a vulnerability so severity should be 'Info' + self.assertEqual("Interesting finding: Headers", finding.title) + self.assertEqual(datetime.datetime(2021, 3, 26, 11, 50, 50), finding.date) def test_parse_file_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/wpscan/wordpress_no_vuln.json") - parser = WpscanParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(7, len(findings)) + with open("unittests/scans/wpscan/wordpress_no_vuln.json") as testfile: + parser = WpscanParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(7, len(findings)) def test_parse_file_with_one_vuln_has_one_findings(self): - testfile = open("unittests/scans/wpscan/wordpress_one_vuln.json") - parser = WpscanParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(8, len(findings)) - finding = findings[0] - self.assertEqual("8873", finding.unique_id_from_tool) - self.assertNotEqual("Info", finding.severity) # it is a vulnerability so not 'Info' - self.assertEqual("YouTube Embed <= 11.8.1 - Cross-Site Request Forgery (CSRF)", finding.title) - self.assertEqual(datetime.datetime(2019, 7, 2, 19, 11, 16), finding.date) + with open("unittests/scans/wpscan/wordpress_one_vuln.json") as testfile: + parser = WpscanParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(8, len(findings)) + finding = findings[0] + self.assertEqual("8873", finding.unique_id_from_tool) + self.assertNotEqual("Info", finding.severity) # it is a vulnerability so not 'Info' + self.assertEqual("YouTube Embed <= 11.8.1 - Cross-Site Request Forgery (CSRF)", finding.title) + self.assertEqual(datetime.datetime(2019, 7, 2, 19, 11, 16), finding.date) def test_parse_file_with_multiple_vuln_has_multiple_finding(self): - testfile = open("unittests/scans/wpscan/wordpress_many_vuln.json") - parser = WpscanParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(8, len(findings)) - finding = findings[0] - self.assertEqual("8873", finding.unique_id_from_tool) - self.assertNotEqual("Info", finding.severity) # it is a vulnerability so not 'Info' - self.assertEqual("YouTube Embed <= 11.8.1 - Cross-Site Request Forgery (CSRF)", finding.title) - self.assertEqual(datetime.datetime(2019, 7, 2, 19, 11, 16), finding.date) - - def test_parse_file_with_multiple_vuln(self): - testfile = open("unittests/scans/wpscan/wpscan.json") - parser = WpscanParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(6, len(findings)) - - with self.subTest(i=0): + with open("unittests/scans/wpscan/wordpress_many_vuln.json") as testfile: + parser = WpscanParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(8, len(findings)) finding = findings[0] - self.assertEqual("7391118e-eef5-4ff8-a8ea-f6b65f442c63", finding.unique_id_from_tool) + self.assertEqual("8873", finding.unique_id_from_tool) self.assertNotEqual("Info", finding.severity) # it is a vulnerability so not 'Info' - self.assertEqual("Contact Form 7 < 5.3.2 - Unrestricted File Upload", finding.title) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2020-35489", finding.unsaved_vulnerability_ids[0]) - self.assertEqual(datetime.datetime(2021, 3, 17, 12, 21, 6), finding.date) - self.assertEqual("", finding.get_scanner_confidence_text()) # data are => 100% - - with self.subTest(i=4): - finding = findings[4] - self.assertIsNone(finding.unique_id_from_tool) # interesting findings are not vlunerability - self.assertEqual("Info", finding.severity) # it is not a vulnerability so severity should be 'Info' - self.assertEqual("Interesting finding: WordPress readme found: http://example/readme.html", finding.title) - self.assertEqual(datetime.datetime(2021, 3, 17, 12, 21, 6), finding.date) - self.assertEqual("", finding.get_scanner_confidence_text()) # data are => "confidence": 100, + self.assertEqual("YouTube Embed <= 11.8.1 - Cross-Site Request Forgery (CSRF)", finding.title) + self.assertEqual(datetime.datetime(2019, 7, 2, 19, 11, 16), finding.date) + + def test_parse_file_with_multiple_vuln(self): + with open("unittests/scans/wpscan/wpscan.json") as testfile: + parser = WpscanParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(6, len(findings)) + + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("7391118e-eef5-4ff8-a8ea-f6b65f442c63", finding.unique_id_from_tool) + self.assertNotEqual("Info", finding.severity) # it is a vulnerability so not 'Info' + self.assertEqual("Contact Form 7 < 5.3.2 - Unrestricted File Upload", finding.title) + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2020-35489", finding.unsaved_vulnerability_ids[0]) + self.assertEqual(datetime.datetime(2021, 3, 17, 12, 21, 6), finding.date) + self.assertEqual("", finding.get_scanner_confidence_text()) # data are => 100% + + with self.subTest(i=4): + finding = findings[4] + self.assertIsNone(finding.unique_id_from_tool) # interesting findings are not vlunerability + self.assertEqual("Info", finding.severity) # it is not a vulnerability so severity should be 'Info' + self.assertEqual("Interesting finding: WordPress readme found: http://example/readme.html", finding.title) + self.assertEqual(datetime.datetime(2021, 3, 17, 12, 21, 6), finding.date) + self.assertEqual("", finding.get_scanner_confidence_text()) # data are => "confidence": 100, def test_parse_file_with_multiple_vuln_in_version(self): - testfile = open("unittests/scans/wpscan/wordpress_vuln_version.json") - parser = WpscanParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(11, len(findings)) - - with self.subTest(i=2): - finding = findings[2] - self.assertEqual("d40374cf-ee95-40b7-9dd5-dbb160b877b1", finding.unique_id_from_tool) - self.assertNotEqual("Info", finding.severity) # it is a vulnerability so not 'Info' - self.assertEqual("WordPress 2.8.1-4.7.2 - Control Characters in Redirect URL Validation", finding.title) - self.assertEqual("fixed in : 4.6.4", finding.mitigation) - self.assertEqual("", finding.get_scanner_confidence_text()) # data are => 100% + with open("unittests/scans/wpscan/wordpress_vuln_version.json") as testfile: + parser = WpscanParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(11, len(findings)) + + with self.subTest(i=2): + finding = findings[2] + self.assertEqual("d40374cf-ee95-40b7-9dd5-dbb160b877b1", finding.unique_id_from_tool) + self.assertNotEqual("Info", finding.severity) # it is a vulnerability so not 'Info' + self.assertEqual("WordPress 2.8.1-4.7.2 - Control Characters in Redirect URL Validation", finding.title) + self.assertEqual("fixed in : 4.6.4", finding.mitigation) + self.assertEqual("", finding.get_scanner_confidence_text()) # data are => 100% def test_parse_file_issue5774(self): - testfile = open("unittests/scans/wpscan/issue5774.json") - parser = WpscanParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertEqual(59, len(findings)) - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("16353d45-75d1-4820-b93f-daad90c322a8", finding.unique_id_from_tool) - self.assertNotEqual("Info", finding.severity) - self.assertEqual("All in One SEO Pack <= 2.9.1.1 - Authenticated Stored Cross-Site Scripting (XSS)", finding.title) - self.assertEqual("fixed in : 2.10", finding.mitigation) - self.assertEqual(7, finding.scanner_confidence) - self.assertEqual("Tentative", finding.get_scanner_confidence_text()) # data are at 30% - with self.subTest(i=19): - finding = findings[19] - self.assertEqual("WordPress 3.7-4.9.1 - MediaElement Cross-Site Scripting (XSS)", finding.title) - self.assertEqual(2, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2018-5776", finding.unsaved_vulnerability_ids[0]) - self.assertEqual("CVE-2016-9263", finding.unsaved_vulnerability_ids[1]) - with self.subTest(i=30): - finding = findings[0] - self.assertEqual("16353d45-75d1-4820-b93f-daad90c322a8", finding.unique_id_from_tool) - self.assertNotEqual("Info", finding.severity) - self.assertEqual("All in One SEO Pack <= 2.9.1.1 - Authenticated Stored Cross-Site Scripting (XSS)", finding.title) - self.assertEqual("fixed in : 2.10", finding.mitigation) - self.assertEqual("Tentative", finding.get_scanner_confidence_text()) # data are at 30% - - with self.subTest(i=50): - finding = findings[50] - self.assertEqual("6a3ec618-c79e-4b9c-9020-86b157458ac5", finding.unique_id_from_tool) - self.assertNotEqual("Info", finding.severity) - self.assertEqual("WordPress 4.7-5.7 - Authenticated Password Protected Pages Exposure", finding.title) - self.assertEqual("fixed in : 4.7.20", finding.mitigation) - self.assertEqual(0, finding.scanner_confidence) - finding.scanner_confidence = 1 - self.assertEqual("Certain", finding.get_scanner_confidence_text()) # data are => 100% + with open("unittests/scans/wpscan/issue5774.json") as testfile: + parser = WpscanParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertEqual(59, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("16353d45-75d1-4820-b93f-daad90c322a8", finding.unique_id_from_tool) + self.assertNotEqual("Info", finding.severity) + self.assertEqual("All in One SEO Pack <= 2.9.1.1 - Authenticated Stored Cross-Site Scripting (XSS)", finding.title) + self.assertEqual("fixed in : 2.10", finding.mitigation) + self.assertEqual(7, finding.scanner_confidence) + self.assertEqual("Tentative", finding.get_scanner_confidence_text()) # data are at 30% + with self.subTest(i=19): + finding = findings[19] + self.assertEqual("WordPress 3.7-4.9.1 - MediaElement Cross-Site Scripting (XSS)", finding.title) + self.assertEqual(2, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2018-5776", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("CVE-2016-9263", finding.unsaved_vulnerability_ids[1]) + with self.subTest(i=30): + finding = findings[0] + self.assertEqual("16353d45-75d1-4820-b93f-daad90c322a8", finding.unique_id_from_tool) + self.assertNotEqual("Info", finding.severity) + self.assertEqual("All in One SEO Pack <= 2.9.1.1 - Authenticated Stored Cross-Site Scripting (XSS)", finding.title) + self.assertEqual("fixed in : 2.10", finding.mitigation) + self.assertEqual("Tentative", finding.get_scanner_confidence_text()) # data are at 30% + + with self.subTest(i=50): + finding = findings[50] + self.assertEqual("6a3ec618-c79e-4b9c-9020-86b157458ac5", finding.unique_id_from_tool) + self.assertNotEqual("Info", finding.severity) + self.assertEqual("WordPress 4.7-5.7 - Authenticated Password Protected Pages Exposure", finding.title) + self.assertEqual("fixed in : 4.7.20", finding.mitigation) + self.assertEqual(0, finding.scanner_confidence) + finding.scanner_confidence = 1 + self.assertEqual("Certain", finding.get_scanner_confidence_text()) # data are => 100% def test_confidence(self): parser = WpscanParser() diff --git a/unittests/tools/test_xanitizer_parser.py b/unittests/tools/test_xanitizer_parser.py index d4d1b95059..10a6135fd8 100644 --- a/unittests/tools/test_xanitizer_parser.py +++ b/unittests/tools/test_xanitizer_parser.py @@ -6,30 +6,28 @@ class TestXanitizerParser(DojoTestCase): def test_parse_file_with_no_findings(self): - testfile = open("unittests/scans/xanitizer/no-findings.xml") - parser = XanitizerParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(0, len(findings)) + with open("unittests/scans/xanitizer/no-findings.xml") as testfile: + parser = XanitizerParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(0, len(findings)) def test_parse_file_with_one_findings(self): - testfile = open("unittests/scans/xanitizer/one-findings.xml") - parser = XanitizerParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(1, len(findings)) + with open("unittests/scans/xanitizer/one-findings.xml") as testfile: + parser = XanitizerParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) def test_parse_file_with_multiple_findings(self): - testfile = open("unittests/scans/xanitizer/multiple-findings.xml") - parser = XanitizerParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(9, len(findings)) - finding = findings[5] - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("CVE-2015-5211", finding.unsaved_vulnerability_ids[0]) + with open("unittests/scans/xanitizer/multiple-findings.xml") as testfile: + parser = XanitizerParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(9, len(findings)) + finding = findings[5] + self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) + self.assertEqual("CVE-2015-5211", finding.unsaved_vulnerability_ids[0]) def test_parse_file_with_multiple_findings_no_details(self): - testfile = open( - get_unit_tests_path() + "/scans/xanitizer/multiple-findings-no-details.xml" - ) - parser = XanitizerParser() - findings = parser.get_findings(testfile, Test()) - self.assertEqual(9, len(findings)) + with open(get_unit_tests_path() + "/scans/xanitizer/multiple-findings-no-details.xml") as testfile: + parser = XanitizerParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(9, len(findings)) diff --git a/unittests/tools/test_yarn_audit_parser.py b/unittests/tools/test_yarn_audit_parser.py index 77177d3f3a..b97b7daacf 100644 --- a/unittests/tools/test_yarn_audit_parser.py +++ b/unittests/tools/test_yarn_audit_parser.py @@ -16,74 +16,67 @@ def test_yarn_audit_parser_without_file_has_no_findings(self): self.assertEqual(0, len(findings)) def test_yarn_audit_parser_with_no_vuln_has_no_findings(self): - testfile = open("unittests/scans/yarn_audit/yarn_audit_zero_vul.json") - parser = YarnAuditParser() - findings = parser.get_findings(testfile, self.get_test()) - testfile.close() - self.assertEqual(0, len(findings)) + with open("unittests/scans/yarn_audit/yarn_audit_zero_vul.json") as testfile: + parser = YarnAuditParser() + findings = parser.get_findings(testfile, self.get_test()) + self.assertEqual(0, len(findings)) def test_yarn_audit_parser_with_one_criticle_vuln_has_one_findings(self): - testfile = open("unittests/scans/yarn_audit/yarn_audit_one_vul.json") - parser = YarnAuditParser() - findings = parser.get_findings(testfile, self.get_test()) - testfile.close() - self.assertEqual(1, len(findings)) - self.assertEqual("handlebars", findings[0].component_name) - self.assertEqual("4.5.2", findings[0].component_version) + with open("unittests/scans/yarn_audit/yarn_audit_one_vul.json") as testfile: + parser = YarnAuditParser() + findings = parser.get_findings(testfile, self.get_test()) + self.assertEqual(1, len(findings)) + self.assertEqual("handlebars", findings[0].component_name) + self.assertEqual("4.5.2", findings[0].component_version) def test_yarn_audit_parser_with_many_vuln_has_many_findings(self): - testfile = open("unittests/scans/yarn_audit/yarn_audit_many_vul.json") - parser = YarnAuditParser() - findings = parser.get_findings(testfile, self.get_test()) - testfile.close() - self.assertEqual(3, len(findings)) + with open("unittests/scans/yarn_audit/yarn_audit_many_vul.json") as testfile: + parser = YarnAuditParser() + findings = parser.get_findings(testfile, self.get_test()) + self.assertEqual(3, len(findings)) def test_yarn_audit_parser_with_multiple_cwes_per_finding(self): # cwes formatted as escaped list: "cwe": "[\"CWE-346\",\"CWE-453\"]", - testfile = open("unittests/scans/yarn_audit/yarn_audit_multiple_cwes.json") - parser = YarnAuditParser() - findings = parser.get_findings(testfile, self.get_test()) - testfile.close() - self.assertEqual(3, len(findings)) - self.assertEqual(findings[0].cwe, 1333) - self.assertEqual(1, len(findings[0].unsaved_vulnerability_ids)) - self.assertEqual("CVE-2021-3803", findings[0].unsaved_vulnerability_ids[0]) - self.assertEqual(findings[1].cwe, 173) - self.assertEqual(1, len(findings[1].unsaved_vulnerability_ids)) - self.assertEqual("CVE-2022-0235", findings[1].unsaved_vulnerability_ids[0]) - self.assertEqual(findings[2].cwe, 1035) - self.assertEqual(1, len(findings[2].unsaved_vulnerability_ids)) - self.assertEqual("CVE-2021-3807", findings[2].unsaved_vulnerability_ids[0]) + with open("unittests/scans/yarn_audit/yarn_audit_multiple_cwes.json") as testfile: + parser = YarnAuditParser() + findings = parser.get_findings(testfile, self.get_test()) + self.assertEqual(3, len(findings)) + self.assertEqual(findings[0].cwe, 1333) + self.assertEqual(1, len(findings[0].unsaved_vulnerability_ids)) + self.assertEqual("CVE-2021-3803", findings[0].unsaved_vulnerability_ids[0]) + self.assertEqual(findings[1].cwe, 173) + self.assertEqual(1, len(findings[1].unsaved_vulnerability_ids)) + self.assertEqual("CVE-2022-0235", findings[1].unsaved_vulnerability_ids[0]) + self.assertEqual(findings[2].cwe, 1035) + self.assertEqual(1, len(findings[2].unsaved_vulnerability_ids)) + self.assertEqual("CVE-2021-3807", findings[2].unsaved_vulnerability_ids[0]) def test_yarn_audit_parser_with_multiple_cwes_per_finding_list(self): # cwes formatted as proper list: "cwe": ["CWE-918","CWE-1333"], - testfile = open("unittests/scans/yarn_audit/yarn_audit_multiple_cwes2.json") - parser = YarnAuditParser() - findings = parser.get_findings(testfile, self.get_test()) - testfile.close() - self.assertEqual(2, len(findings)) - self.assertEqual(findings[0].cwe, 918) - self.assertEqual(findings[1].cwe, 1035) - self.assertEqual(findings[1].cve, None) - self.assertEqual(findings[1].unsaved_vulnerability_ids[0], "CVE-2021-3807") + with open("unittests/scans/yarn_audit/yarn_audit_multiple_cwes2.json") as testfile: + parser = YarnAuditParser() + findings = parser.get_findings(testfile, self.get_test()) + self.assertEqual(2, len(findings)) + self.assertEqual(findings[0].cwe, 918) + self.assertEqual(findings[1].cwe, 1035) + self.assertEqual(findings[1].cve, None) + self.assertEqual(findings[1].unsaved_vulnerability_ids[0], "CVE-2021-3807") def test_yarn_audit_parser_empty_with_error(self): with self.assertRaises(ValueError) as context: - testfile = open("unittests/scans/yarn_audit/empty_with_error.json") - parser = YarnAuditParser() - parser.get_findings(testfile, self.get_test()) - testfile.close() - self.assertTrue( - "yarn audit report contains errors:" in str(context.exception) - ) - self.assertTrue("ECONNREFUSED" in str(context.exception)) + with open("unittests/scans/yarn_audit/empty_with_error.json") as testfile: + parser = YarnAuditParser() + parser.get_findings(testfile, self.get_test()) + self.assertTrue( + "yarn audit report contains errors:" in str(context.exception) + ) + self.assertTrue("ECONNREFUSED" in str(context.exception)) def test_yarn_audit_parser_issue_6495(self): - testfile = open("unittests/scans/yarn_audit/issue_6495.json") - parser = YarnAuditParser() - findings = parser.get_findings(testfile, self.get_test()) - testfile.close() - self.assertEqual(3, len(findings)) - self.assertEqual(findings[0].cwe, "1321") - self.assertEqual(findings[1].unsaved_vulnerability_ids[0], "CVE-2022-25851") - self.assertEqual(findings[1].cve, None) + with open("unittests/scans/yarn_audit/issue_6495.json") as testfile: + parser = YarnAuditParser() + findings = parser.get_findings(testfile, self.get_test()) + self.assertEqual(3, len(findings)) + self.assertEqual(findings[0].cwe, "1321") + self.assertEqual(findings[1].unsaved_vulnerability_ids[0], "CVE-2022-25851") + self.assertEqual(findings[1].cve, None) diff --git a/unittests/tools/test_zap_parser.py b/unittests/tools/test_zap_parser.py index 7167fb9c5e..b32ac22f46 100644 --- a/unittests/tools/test_zap_parser.py +++ b/unittests/tools/test_zap_parser.py @@ -5,223 +5,223 @@ class TestZapParser(DojoTestCase): def test_parse_no_findings(self): - testfile = open("unittests/scans/zap/empty_2.9.0.xml") - parser = ZapParser() - findings = parser.get_findings(testfile, Test()) - self.assertIsInstance(findings, list) - self.assertEqual(0, len(findings)) + with open("unittests/scans/zap/empty_2.9.0.xml") as testfile: + parser = ZapParser() + findings = parser.get_findings(testfile, Test()) + self.assertIsInstance(findings, list) + self.assertEqual(0, len(findings)) def test_parse_some_findings(self): - testfile = open("unittests/scans/zap/some_2.9.0.xml") - parser = ZapParser() - findings = parser.get_findings(testfile, Test()) - self.assertIsInstance(findings, list) - self.assertEqual(7, len(findings)) - for finding in findings: - self.assertIn(finding.severity, Finding.SEVERITIES) - for endpoint in finding.unsaved_endpoints: - endpoint.clean() + with open("unittests/scans/zap/some_2.9.0.xml") as testfile: + parser = ZapParser() + findings = parser.get_findings(testfile, Test()) + self.assertIsInstance(findings, list) + self.assertEqual(7, len(findings)) + for finding in findings: + self.assertIn(finding.severity, Finding.SEVERITIES) + for endpoint in finding.unsaved_endpoints: + endpoint.clean() def test_parse_some_findings_0(self): - testfile = open("unittests/scans/zap/0_zap_sample.xml") - parser = ZapParser() - findings = parser.get_findings(testfile, Test()) - self.assertIsInstance(findings, list) - self.assertEqual(4, len(findings)) - for finding in findings: - self.assertIn(finding.severity, Finding.SEVERITIES) - for endpoint in finding.unsaved_endpoints: - endpoint.clean() + with open("unittests/scans/zap/0_zap_sample.xml") as testfile: + parser = ZapParser() + findings = parser.get_findings(testfile, Test()) + self.assertIsInstance(findings, list) + self.assertEqual(4, len(findings)) + for finding in findings: + self.assertIn(finding.severity, Finding.SEVERITIES) + for endpoint in finding.unsaved_endpoints: + endpoint.clean() def test_parse_some_findings_1(self): - testfile = open("unittests/scans/zap/1_zap_sample_0_and_new_absent.xml") - parser = ZapParser() - findings = parser.get_findings(testfile, Test()) - self.assertIsInstance(findings, list) - self.assertEqual(4, len(findings)) - for finding in findings: - self.assertIn(finding.severity, Finding.SEVERITIES) - for endpoint in finding.unsaved_endpoints: - endpoint.clean() + with open("unittests/scans/zap/1_zap_sample_0_and_new_absent.xml") as testfile: + parser = ZapParser() + findings = parser.get_findings(testfile, Test()) + self.assertIsInstance(findings, list) + self.assertEqual(4, len(findings)) + for finding in findings: + self.assertIn(finding.severity, Finding.SEVERITIES) + for endpoint in finding.unsaved_endpoints: + endpoint.clean() def test_parse_some_findings_2(self): - testfile = open("unittests/scans/zap/2_zap_sample_0_and_new_endpoint.xml") - parser = ZapParser() - findings = parser.get_findings(testfile, Test()) - self.assertIsInstance(findings, list) - self.assertEqual(4, len(findings)) - for finding in findings: - self.assertIn(finding.severity, Finding.SEVERITIES) - for endpoint in finding.unsaved_endpoints: - endpoint.clean() + with open("unittests/scans/zap/2_zap_sample_0_and_new_endpoint.xml") as testfile: + parser = ZapParser() + findings = parser.get_findings(testfile, Test()) + self.assertIsInstance(findings, list) + self.assertEqual(4, len(findings)) + for finding in findings: + self.assertIn(finding.severity, Finding.SEVERITIES) + for endpoint in finding.unsaved_endpoints: + endpoint.clean() def test_parse_some_findings_3(self): - testfile = open("unittests/scans/zap/3_zap_sampl_0_and_different_severities.xml") - parser = ZapParser() - findings = parser.get_findings(testfile, Test()) - self.assertIsInstance(findings, list) - self.assertEqual(4, len(findings)) - for finding in findings: - self.assertIn(finding.severity, Finding.SEVERITIES) - for endpoint in finding.unsaved_endpoints: - endpoint.clean() + with open("unittests/scans/zap/3_zap_sampl_0_and_different_severities.xml") as testfile: + parser = ZapParser() + findings = parser.get_findings(testfile, Test()) + self.assertIsInstance(findings, list) + self.assertEqual(4, len(findings)) + for finding in findings: + self.assertIn(finding.severity, Finding.SEVERITIES) + for endpoint in finding.unsaved_endpoints: + endpoint.clean() def test_parse_some_findings_5(self): - testfile = open("unittests/scans/zap/5_zap_sample_one.xml") - parser = ZapParser() - findings = parser.get_findings(testfile, Test()) - self.assertIsInstance(findings, list) - self.assertEqual(2, len(findings)) - for finding in findings: - self.assertIn(finding.severity, Finding.SEVERITIES) - for endpoint in finding.unsaved_endpoints: - endpoint.clean() + with open("unittests/scans/zap/5_zap_sample_one.xml") as testfile: + parser = ZapParser() + findings = parser.get_findings(testfile, Test()) + self.assertIsInstance(findings, list) + self.assertEqual(2, len(findings)) + for finding in findings: + self.assertIn(finding.severity, Finding.SEVERITIES) + for endpoint in finding.unsaved_endpoints: + endpoint.clean() def test_parse_issue4360(self): """Report from GitHub issue 4360 see: https://github.com/DefectDojo/django-DefectDojo/issues/4360 """ - testfile = open("unittests/scans/zap/dvwa_baseline_dojo.xml") - parser = ZapParser() - findings = parser.get_findings(testfile, Test()) - self.assertIsInstance(findings, list) - self.assertEqual(19, len(findings)) - for finding in findings: - self.assertIn(finding.severity, Finding.SEVERITIES) - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("X-Frame-Options Header Not Set", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertEqual("10020", finding.vuln_id_from_tool) - self.assertEqual(11, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual("172.17.0.2", endpoint.host) - self.assertEqual(80, endpoint.port) - endpoint = finding.unsaved_endpoints[1] - self.assertEqual("http", endpoint.protocol) - self.assertEqual("172.17.0.2", endpoint.host) - self.assertEqual("vulnerabilities/sqli_blind/", endpoint.path) - with self.subTest(i=18): - finding = findings[18] - self.assertEqual("Private IP Disclosure", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual("2", finding.vuln_id_from_tool) - self.assertEqual(3, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] + with open("unittests/scans/zap/dvwa_baseline_dojo.xml") as testfile: + parser = ZapParser() + findings = parser.get_findings(testfile, Test()) + self.assertIsInstance(findings, list) + self.assertEqual(19, len(findings)) + for finding in findings: + self.assertIn(finding.severity, Finding.SEVERITIES) + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("X-Frame-Options Header Not Set", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertEqual("10020", finding.vuln_id_from_tool) + self.assertEqual(11, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual("172.17.0.2", endpoint.host) + self.assertEqual(80, endpoint.port) + endpoint = finding.unsaved_endpoints[1] + self.assertEqual("http", endpoint.protocol) + self.assertEqual("172.17.0.2", endpoint.host) + self.assertEqual("vulnerabilities/sqli_blind/", endpoint.path) + with self.subTest(i=18): + finding = findings[18] + self.assertEqual("Private IP Disclosure", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual("2", finding.vuln_id_from_tool) + self.assertEqual(3, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] def test_parse_issue4697(self): """Report from GitHub issue 4697 see: https://github.com/DefectDojo/django-DefectDojo/issues/4697 """ - testfile = open("unittests/scans/zap/zap-results-first-scan.xml") - parser = ZapParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertIsInstance(findings, list) - self.assertEqual(15, len(findings)) - for finding in findings: - self.assertIn(finding.severity, Finding.SEVERITIES) - for endpoint in finding.unsaved_endpoints: - endpoint.clean() + with open("unittests/scans/zap/zap-results-first-scan.xml") as testfile: + parser = ZapParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertIsInstance(findings, list) + self.assertEqual(15, len(findings)) + for finding in findings: + self.assertIn(finding.severity, Finding.SEVERITIES) + for endpoint in finding.unsaved_endpoints: + endpoint.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("User Controllable HTML Element Attribute (Potential XSS)", finding.title) - self.assertEqual("Info", finding.severity) - self.assertEqual("10031", finding.vuln_id_from_tool) - self.assertEqual(11, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual("http", endpoint.protocol) - self.assertEqual("bodgeit.securecodebox-demo.svc", endpoint.host) - self.assertEqual(8080, endpoint.port) - endpoint = finding.unsaved_endpoints[1] - self.assertEqual("http", endpoint.protocol) - self.assertEqual("bodgeit.securecodebox-demo.svc", endpoint.host) - self.assertEqual("bodgeit/product.jsp", endpoint.path) - with self.subTest(i=14): - finding = findings[14] - self.assertEqual("PII Disclosure", finding.title) - self.assertEqual("High", finding.severity) - self.assertEqual("10062", finding.vuln_id_from_tool) - self.assertEqual(359, finding.cwe) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual("http", endpoint.protocol) - self.assertEqual("bodgeit.securecodebox-demo.svc", endpoint.host) - self.assertEqual("bodgeit/contact.jsp", endpoint.path) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("User Controllable HTML Element Attribute (Potential XSS)", finding.title) + self.assertEqual("Info", finding.severity) + self.assertEqual("10031", finding.vuln_id_from_tool) + self.assertEqual(11, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual("http", endpoint.protocol) + self.assertEqual("bodgeit.securecodebox-demo.svc", endpoint.host) + self.assertEqual(8080, endpoint.port) + endpoint = finding.unsaved_endpoints[1] + self.assertEqual("http", endpoint.protocol) + self.assertEqual("bodgeit.securecodebox-demo.svc", endpoint.host) + self.assertEqual("bodgeit/product.jsp", endpoint.path) + with self.subTest(i=14): + finding = findings[14] + self.assertEqual("PII Disclosure", finding.title) + self.assertEqual("High", finding.severity) + self.assertEqual("10062", finding.vuln_id_from_tool) + self.assertEqual(359, finding.cwe) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual("http", endpoint.protocol) + self.assertEqual("bodgeit.securecodebox-demo.svc", endpoint.host) + self.assertEqual("bodgeit/contact.jsp", endpoint.path) def test_parse_juicy(self): """Generated with OWASP Juicy shop""" - testfile = open("unittests/scans/zap/juicy2.xml") - parser = ZapParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertIsInstance(findings, list) - self.assertEqual(6, len(findings)) - for finding in findings: - self.assertIn(finding.severity, Finding.SEVERITIES) - for endpoint in finding.unsaved_endpoints: - endpoint.clean() + with open("unittests/scans/zap/juicy2.xml") as testfile: + parser = ZapParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertIsInstance(findings, list) + self.assertEqual(6, len(findings)) + for finding in findings: + self.assertIn(finding.severity, Finding.SEVERITIES) + for endpoint in finding.unsaved_endpoints: + endpoint.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Incomplete or No Cache-control Header Set", finding.title) - self.assertEqual("Low", finding.severity) - self.assertEqual("10015", finding.vuln_id_from_tool) - self.assertEqual(20, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual("https", endpoint.protocol) - self.assertEqual("juice-shop.herokuapp.com", endpoint.host) - self.assertEqual(443, endpoint.port) - endpoint = finding.unsaved_endpoints[1] - self.assertEqual("https", endpoint.protocol) - self.assertEqual("juice-shop.herokuapp.com", endpoint.host) - self.assertEqual("assets/public/polyfills-es2018.js", endpoint.path) - with self.subTest(i=5): - finding = findings[5] - self.assertEqual("CSP: Wildcard Directive", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertEqual("10055", finding.vuln_id_from_tool) - self.assertEqual(693, finding.cwe) - self.assertEqual(2, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual("https", endpoint.protocol) - self.assertEqual("juice-shop.herokuapp.com", endpoint.host) - self.assertEqual("assets", endpoint.path) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Incomplete or No Cache-control Header Set", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual("10015", finding.vuln_id_from_tool) + self.assertEqual(20, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual("https", endpoint.protocol) + self.assertEqual("juice-shop.herokuapp.com", endpoint.host) + self.assertEqual(443, endpoint.port) + endpoint = finding.unsaved_endpoints[1] + self.assertEqual("https", endpoint.protocol) + self.assertEqual("juice-shop.herokuapp.com", endpoint.host) + self.assertEqual("assets/public/polyfills-es2018.js", endpoint.path) + with self.subTest(i=5): + finding = findings[5] + self.assertEqual("CSP: Wildcard Directive", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertEqual("10055", finding.vuln_id_from_tool) + self.assertEqual(693, finding.cwe) + self.assertEqual(2, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual("https", endpoint.protocol) + self.assertEqual("juice-shop.herokuapp.com", endpoint.host) + self.assertEqual("assets", endpoint.path) def test_parse_xml_plus_format(self): - testfile = open("unittests/scans/zap/zap-xml-plus-format.xml") - parser = ZapParser() - findings = parser.get_findings(testfile, Test()) - for finding in findings: - for endpoint in finding.unsaved_endpoints: - endpoint.clean() - self.assertIsInstance(findings, list) - self.assertEqual(1, len(findings)) - for finding in findings: - self.assertIn(finding.severity, Finding.SEVERITIES) - for endpoint in finding.unsaved_endpoints: - endpoint.clean() + with open("unittests/scans/zap/zap-xml-plus-format.xml") as testfile: + parser = ZapParser() + findings = parser.get_findings(testfile, Test()) + for finding in findings: + for endpoint in finding.unsaved_endpoints: + endpoint.clean() + self.assertIsInstance(findings, list) + self.assertEqual(1, len(findings)) + for finding in findings: + self.assertIn(finding.severity, Finding.SEVERITIES) + for endpoint in finding.unsaved_endpoints: + endpoint.clean() - with self.subTest(i=0): - finding = findings[0] - self.assertEqual("Insecure HTTP Method - PUT", finding.title) - self.assertEqual("Medium", finding.severity) - self.assertEqual("90028", finding.vuln_id_from_tool) - self.assertEqual(1, len(finding.unsaved_endpoints)) - endpoint = finding.unsaved_endpoints[0] - self.assertEqual("http", endpoint.protocol) - self.assertEqual("localhost", endpoint.host) - self.assertEqual(8080, endpoint.port) - # Check request and response pair - request_pair = finding.unsaved_req_resp[0] - request = request_pair["req"] - response = request_pair["resp"] - self.assertEqual('HTTP/1.1 403 Forbidden\nServer: Apache-Coyote/1.1\nContent-Type: text/html;charset=utf-8\nContent-Language: en\nContent-Length: 1004\nDate: Fri, 30 Sep 2022 06:40:15 GMT\n\nApache Tomcat/8.0.37 - Error report

HTTP Status 403 -

type Status report

message

description Access to the specified resource has been forbidden.


Apache Tomcat/8.0.37

', response) - self.assertEqual('PUT http://localhost:8080/bodgeit/js/qndto7n63d HTTP/1.1\nHost: localhost:8080\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:105.0) Gecko/20100101 Firefox/105.0\nAccept: */*\nAccept-Language: de,en-US;q=0.7,en;q=0.3\nConnection: keep-alive\nReferer: https://localhost:8080/bodgeit/\nCookie: JSESSIONID=9E75E26E50F681208096FFAA0B566901\nSec-Fetch-Dest: script\nSec-Fetch-Mode: no-cors\nSec-Fetch-Site: same-origin\nContent-Length: 35\n\n"J0O0glajHdR0Mgp":"UToh9IpCY5zh3CB"', request) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Insecure HTTP Method - PUT", finding.title) + self.assertEqual("Medium", finding.severity) + self.assertEqual("90028", finding.vuln_id_from_tool) + self.assertEqual(1, len(finding.unsaved_endpoints)) + endpoint = finding.unsaved_endpoints[0] + self.assertEqual("http", endpoint.protocol) + self.assertEqual("localhost", endpoint.host) + self.assertEqual(8080, endpoint.port) + # Check request and response pair + request_pair = finding.unsaved_req_resp[0] + request = request_pair["req"] + response = request_pair["resp"] + self.assertEqual('HTTP/1.1 403 Forbidden\nServer: Apache-Coyote/1.1\nContent-Type: text/html;charset=utf-8\nContent-Language: en\nContent-Length: 1004\nDate: Fri, 30 Sep 2022 06:40:15 GMT\n\nApache Tomcat/8.0.37 - Error report

HTTP Status 403 -

type Status report

message

description Access to the specified resource has been forbidden.


Apache Tomcat/8.0.37

', response) + self.assertEqual('PUT http://localhost:8080/bodgeit/js/qndto7n63d HTTP/1.1\nHost: localhost:8080\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:105.0) Gecko/20100101 Firefox/105.0\nAccept: */*\nAccept-Language: de,en-US;q=0.7,en;q=0.3\nConnection: keep-alive\nReferer: https://localhost:8080/bodgeit/\nCookie: JSESSIONID=9E75E26E50F681208096FFAA0B566901\nSec-Fetch-Dest: script\nSec-Fetch-Mode: no-cors\nSec-Fetch-Site: same-origin\nContent-Length: 35\n\n"J0O0glajHdR0Mgp":"UToh9IpCY5zh3CB"', request) From 377b792bd811b6fef4889653f1be9e29e4004b60 Mon Sep 17 00:00:00 2001 From: kiblik Date: Tue, 30 Apr 2024 16:32:50 +0200 Subject: [PATCH 099/138] Ruff: add and fix C4 (#9889) * Ruff: add and fix C4 Signed-off-by: kiblik <5609770+kiblik@users.noreply.github.com> * Update dojo/finding/views.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> Signed-off-by: kiblik <5609770+kiblik@users.noreply.github.com> * Fix SQ --------- Signed-off-by: kiblik <5609770+kiblik@users.noreply.github.com> Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> --- dojo/api_v2/prefetch/prefetcher.py | 6 +-- dojo/api_v2/prefetch/schema.py | 2 +- dojo/api_v2/serializers.py | 8 +-- dojo/api_v2/views.py | 2 +- dojo/filters.py | 2 +- dojo/finding/views.py | 6 +-- dojo/importers/importer/importer.py | 2 +- dojo/importers/reimporter/reimporter.py | 20 +++---- dojo/metrics/views.py | 8 +-- dojo/models.py | 52 ++++++------------- dojo/notifications/helper.py | 8 +-- dojo/product/views.py | 6 +-- dojo/reports/views.py | 4 +- dojo/templatetags/display_tags.py | 2 +- dojo/tools/acunetix/parse_acunetix360_json.py | 4 +- dojo/tools/acunetix/parse_acunetix_xml.py | 4 +- dojo/tools/anchore_engine/parser.py | 2 +- dojo/tools/anchore_enterprise/parser.py | 2 +- dojo/tools/anchore_grype/parser.py | 4 +- dojo/tools/anchorectl_policies/parser.py | 2 +- dojo/tools/anchorectl_vulns/parser.py | 2 +- dojo/tools/api_bugcrowd/api_client.py | 4 +- dojo/tools/api_vulners/parser.py | 8 +-- dojo/tools/appspider/parser.py | 6 +-- dojo/tools/arachni/parser.py | 2 +- dojo/tools/asff/parser.py | 2 +- dojo/tools/auditjs/parser.py | 2 +- dojo/tools/aws_prowler/parser.py | 4 +- dojo/tools/aws_prowler_v3/parser.py | 2 +- dojo/tools/awssecurityhub/guardduty.py | 4 +- dojo/tools/awssecurityhub/inspector.py | 4 +- dojo/tools/bandit/parser.py | 2 +- dojo/tools/bearer_cli/parser.py | 2 +- dojo/tools/blackduck/importer.py | 6 +-- dojo/tools/blackduck/parser.py | 2 +- .../blackduck_binary_analysis/importer.py | 2 +- .../tools/blackduck_binary_analysis/parser.py | 2 +- .../blackduck_component_risk/importer.py | 4 +- dojo/tools/brakeman/parser.py | 2 +- dojo/tools/bugcrowd/parser.py | 4 +- dojo/tools/bundler_audit/parser.py | 2 +- dojo/tools/burp/parser.py | 8 +-- dojo/tools/burp_api/parser.py | 2 +- dojo/tools/burp_dastardly/parser.py | 2 +- dojo/tools/burp_enterprise/parser.py | 12 ++--- dojo/tools/burp_graphql/parser.py | 8 +-- dojo/tools/checkmarx/parser.py | 6 +-- dojo/tools/clair/clairklar_parser.py | 4 +- dojo/tools/clair/parser.py | 2 +- dojo/tools/cloudsploit/parser.py | 2 +- dojo/tools/cobalt/parser.py | 4 +- dojo/tools/contrast/parser.py | 2 +- dojo/tools/coverity_api/parser.py | 2 +- dojo/tools/crashtest_security/parser.py | 8 +-- dojo/tools/cred_scan/parser.py | 2 +- dojo/tools/cyclonedx/json_parser.py | 2 +- dojo/tools/cyclonedx/xml_parser.py | 4 +- dojo/tools/dependency_check/parser.py | 2 +- dojo/tools/dependency_track/parser.py | 8 +-- dojo/tools/dsop/parser.py | 12 ++--- dojo/tools/eslint/parser.py | 2 +- dojo/tools/factory.py | 10 ++-- dojo/tools/fortify/fpr_parser.py | 2 +- dojo/tools/generic/parser.py | 4 +- dojo/tools/ggshield/parser.py | 2 +- dojo/tools/github_vulnerability/parser.py | 6 +-- dojo/tools/gitleaks/parser.py | 4 +- dojo/tools/gosec/parser.py | 2 +- dojo/tools/h1/parser.py | 4 +- dojo/tools/harbor_vulnerability/parser.py | 4 +- dojo/tools/hcl_appscan/parser.py | 2 +- dojo/tools/ibm_app/parser.py | 4 +- dojo/tools/immuniweb/parser.py | 4 +- dojo/tools/intsights/json_handler.py | 2 +- dojo/tools/intsights/parser.py | 2 +- .../jfrog_xray_api_summary_artifact/parser.py | 4 +- .../parser.py | 2 +- dojo/tools/jfrogxray/parser.py | 2 +- dojo/tools/kiuwan/parser.py | 2 +- dojo/tools/kubeaudit/parser.py | 2 +- dojo/tools/kubehunter/parser.py | 2 +- dojo/tools/mend/parser.py | 4 +- dojo/tools/microfocus_webinspect/parser.py | 2 +- dojo/tools/mozilla_observatory/parser.py | 2 +- dojo/tools/ms_defender/parser.py | 12 ++--- dojo/tools/netsparker/parser.py | 2 +- dojo/tools/neuvector/parser.py | 4 +- dojo/tools/neuvector_compliance/parser.py | 4 +- dojo/tools/nexpose/parser.py | 16 +++--- dojo/tools/nikto/json_parser.py | 2 +- dojo/tools/nikto/xml_parser.py | 2 +- dojo/tools/nmap/parser.py | 6 +-- dojo/tools/npm_audit/parser.py | 2 +- dojo/tools/nuclei/parser.py | 4 +- dojo/tools/openscap/parser.py | 2 +- dojo/tools/openvas/csv_parser.py | 8 +-- dojo/tools/ort/parser.py | 4 +- dojo/tools/ossindex_devaudit/parser.py | 6 +-- dojo/tools/osv_scanner/parser.py | 4 +- dojo/tools/outpost24/parser.py | 2 +- dojo/tools/php_security_audit_v2/parser.py | 2 +- dojo/tools/pip_audit/parser.py | 8 +-- dojo/tools/pmd/parser.py | 2 +- dojo/tools/popeye/parser.py | 2 +- dojo/tools/qualys/parser.py | 2 +- dojo/tools/qualys_infrascan_webgui/parser.py | 2 +- dojo/tools/qualys_webapp/parser.py | 8 +-- dojo/tools/redhatsatellite/parser.py | 4 +- dojo/tools/risk_recon/parser.py | 2 +- dojo/tools/rubocop/parser.py | 2 +- dojo/tools/rusty_hog/parser.py | 2 +- dojo/tools/sarif/parser.py | 14 ++--- dojo/tools/scantist/parser.py | 2 +- dojo/tools/scout_suite/parser.py | 2 +- dojo/tools/semgrep/parser.py | 2 +- dojo/tools/skf/parser.py | 4 +- dojo/tools/solar_appscreener/parser.py | 2 +- .../tools/sonarqube/sonarqube_restapi_json.py | 4 +- dojo/tools/sonarqube/sonarqube_restapi_zip.py | 2 +- dojo/tools/sonarqube/soprasteria_html.py | 4 +- dojo/tools/sonarqube/soprasteria_json.py | 2 +- dojo/tools/spotbugs/parser.py | 6 +-- dojo/tools/ssh_audit/parser.py | 20 +++---- dojo/tools/ssl_labs/parser.py | 2 +- dojo/tools/sslscan/parser.py | 4 +- dojo/tools/sslyze/parser.py | 2 +- dojo/tools/sslyze/parser_json.py | 2 +- dojo/tools/sslyze/parser_xml.py | 4 +- dojo/tools/sysdig_reports/parser.py | 8 +-- dojo/tools/talisman/parser.py | 2 +- dojo/tools/terrascan/parser.py | 2 +- dojo/tools/testssl/parser.py | 2 +- dojo/tools/tfsec/parser.py | 2 +- dojo/tools/threagile/parser.py | 2 +- dojo/tools/trivy/parser.py | 6 +-- dojo/tools/trivy_operator/checks_handler.py | 2 +- .../trivy_operator/compliance_handler.py | 2 +- dojo/tools/trivy_operator/parser.py | 8 +-- dojo/tools/trivy_operator/secrets_handler.py | 2 +- .../trivy_operator/vulnerability_handler.py | 4 +- dojo/tools/trufflehog3/parser.py | 2 +- dojo/tools/twistlock/parser.py | 6 +-- dojo/tools/vcg/parser.py | 8 +-- dojo/tools/veracode/xml_parser.py | 11 ++-- dojo/tools/wapiti/parser.py | 2 +- dojo/tools/wazuh/parser.py | 2 +- dojo/tools/whitehat_sentinel/parser.py | 4 +- dojo/tools/wpscan/parser.py | 4 +- dojo/tools/xanitizer/parser.py | 6 +-- dojo/tools/yarn_audit/parser.py | 6 +-- dojo/tools/zap/parser.py | 2 +- dojo/utils.py | 16 +++--- ruff.toml | 1 + unittests/test_apiv2_metadata.py | 4 +- unittests/test_apply_finding_template.py | 4 +- unittests/test_bulk_risk_acceptance_api.py | 10 ++-- unittests/test_rest_framework.py | 6 +-- .../tools/test_api_sonarqube_importer.py | 2 +- unittests/tools/test_api_sonarqube_parser.py | 2 +- unittests/tools/test_aqua_parser.py | 2 +- unittests/tools/test_openvas_parser.py | 2 +- unittests/tools/test_vcg_parser.py | 2 +- 162 files changed, 347 insertions(+), 375 deletions(-) diff --git a/dojo/api_v2/prefetch/prefetcher.py b/dojo/api_v2/prefetch/prefetcher.py index 5d228165f5..c97cc3fab7 100644 --- a/dojo/api_v2/prefetch/prefetcher.py +++ b/dojo/api_v2/prefetch/prefetcher.py @@ -20,7 +20,7 @@ def _build_serializers(): def _is_model_serializer(obj): return inspect.isclass(obj) and issubclass(obj, ModelSerializer) - serializers = dict() + serializers = {} # We process all the serializers found in the module SERIALIZER_DEFS_MODULE. We restrict the scope to avoid # processing all the classes in the symbol table available_serializers = inspect.getmembers( @@ -37,7 +37,7 @@ def _is_model_serializer(obj): def __init__(self): self._serializers = _Prefetcher._build_serializers() - self._prefetch_data = dict() + self._prefetch_data = {} def _find_serializer(self, field_type): """Find the best suited serializer for the given type. @@ -92,7 +92,7 @@ def _prefetch(self, entry, fields_to_fetch): ) if field_to_fetch not in self._prefetch_data: - self._prefetch_data[field_to_fetch] = dict() + self._prefetch_data[field_to_fetch] = {} # Should not fail as django always generate an id field for data in field_data_list: diff --git a/dojo/api_v2/prefetch/schema.py b/dojo/api_v2/prefetch/schema.py index 6fc0868147..48892c4381 100644 --- a/dojo/api_v2/prefetch/schema.py +++ b/dojo/api_v2/prefetch/schema.py @@ -3,7 +3,7 @@ def _get_path_to_GET_serializer_map(generator): - path_to_GET_serializer = dict() + path_to_GET_serializer = {} for ( path, path_pattern, diff --git a/dojo/api_v2/serializers.py b/dojo/api_v2/serializers.py index d743b1c597..47eda0f620 100644 --- a/dojo/api_v2/serializers.py +++ b/dojo/api_v2/serializers.py @@ -1725,7 +1725,7 @@ def update(self, instance, validated_data): # Save vulnerability ids and pop them if "vulnerability_id_set" in validated_data: vulnerability_id_set = validated_data.pop("vulnerability_id_set") - vulnerability_ids = list() + vulnerability_ids = [] if vulnerability_id_set: for vulnerability_id in vulnerability_id_set: vulnerability_ids.append( @@ -1870,7 +1870,7 @@ def create(self, validated_data): new_finding = super(TaggitSerializer, self).create(validated_data) if vulnerability_id_set: - vulnerability_ids = list() + vulnerability_ids = [] for vulnerability_id in vulnerability_id_set: vulnerability_ids.append(vulnerability_id["vulnerability_id"]) validated_data["cve"] = vulnerability_ids[0] @@ -1967,7 +1967,7 @@ def create(self, validated_data): ) if vulnerability_id_set: - vulnerability_ids = list() + vulnerability_ids = [] for vulnerability_id in vulnerability_id_set: vulnerability_ids.append(vulnerability_id["vulnerability_id"]) validated_data["cve"] = vulnerability_ids[0] @@ -1984,7 +1984,7 @@ def update(self, instance, validated_data): vulnerability_id_set = validated_data.pop( "vulnerability_id_template_set" ) - vulnerability_ids = list() + vulnerability_ids = [] if vulnerability_id_set: for vulnerability_id in vulnerability_id_set: vulnerability_ids.append( diff --git a/dojo/api_v2/views.py b/dojo/api_v2/views.py index c130a735f6..334c4d746b 100644 --- a/dojo/api_v2/views.py +++ b/dojo/api_v2/views.py @@ -2949,7 +2949,7 @@ def report_generate(request, obj, options): ) report_name = "Engagement Report: " + str(engagement) - ids = set(finding.id for finding in findings.qs) + ids = set(finding.id for finding in findings.qs) # noqa: C401 ids = get_endpoint_ids( Endpoint.objects.filter(product=engagement.product).distinct() ) diff --git a/dojo/filters.py b/dojo/filters.py index 92bf923754..c58e8ea37f 100644 --- a/dojo/filters.py +++ b/dojo/filters.py @@ -236,7 +236,7 @@ def get_earliest_finding(queryset=None): def cwe_options(queryset): - cwe = dict() + cwe = {} cwe = dict([cwe, cwe] for cwe in queryset.order_by().values_list('cwe', flat=True).distinct() if isinstance(cwe, int) and cwe is not None and cwe > 0) diff --git a/dojo/finding/views.py b/dojo/finding/views.py index fe0b7a7ee9..efe026e9ec 100644 --- a/dojo/finding/views.py +++ b/dojo/finding/views.py @@ -2692,7 +2692,7 @@ def finding_bulk_update_all(request, pid=None): finding_to_update = request.POST.getlist("finding_to_update") finds = Finding.objects.filter(id__in=finding_to_update).order_by("id") total_find_count = finds.count() - prods = set([find.test.engagement.product for find in finds]) + prods = set(find.test.engagement.product for find in finds) # noqa: C401 if request.POST.get("delete_bulk_findings"): if form.is_valid() and finding_to_update: if pid is not None: @@ -2996,8 +2996,8 @@ def finding_bulk_update_all(request, pid=None): error_counts = defaultdict(lambda: 0) success_count = 0 - finding_groups = set( - [find.finding_group for find in finds if find.has_finding_group] + finding_groups = set( # noqa: C401 + find.finding_group for find in finds if find.has_finding_group ) logger.debug("finding_groups: %s", finding_groups) groups_pushed_to_jira = False diff --git a/dojo/importers/importer/importer.py b/dojo/importers/importer/importer.py index 1be23a01e8..d89a41f0cd 100644 --- a/dojo/importers/importer/importer.py +++ b/dojo/importers/importer/importer.py @@ -257,7 +257,7 @@ def close_old_findings(self, test, scan_date_time, user, push_to_jira=None, serv old_finding.save(dedupe_option=False, push_to_jira=push_to_jira) if is_finding_groups_enabled() and push_to_jira: - for finding_group in set([finding.finding_group for finding in old_findings if finding.finding_group is not None]): + for finding_group in set(finding.finding_group for finding in old_findings if finding.finding_group is not None): # noqa: C401 jira_helper.push_to_jira(finding_group) return old_findings diff --git a/dojo/importers/reimporter/reimporter.py b/dojo/importers/reimporter/reimporter.py index 0128d0daaa..dac0c8e8e4 100644 --- a/dojo/importers/reimporter/reimporter.py +++ b/dojo/importers/reimporter/reimporter.py @@ -451,12 +451,10 @@ def process_parsed_findings( jira_helper.push_to_jira(findings[0]) if is_finding_groups_enabled() and push_to_jira: - for finding_group in set( - [ - finding.finding_group - for finding in reactivated_items + unchanged_items - if finding.finding_group is not None and not finding.is_mitigated - ] + for finding_group in set( # noqa: C401 + finding.finding_group + for finding in reactivated_items + unchanged_items + if finding.finding_group is not None and not finding.is_mitigated ): jira_helper.push_to_jira(finding_group) @@ -540,12 +538,10 @@ def close_old_findings( mitigated_findings.append(finding) if is_finding_groups_enabled() and push_to_jira: - for finding_group in set( - [ - finding.finding_group - for finding in to_mitigate - if finding.finding_group is not None - ] + for finding_group in set( # noqa: C401 + finding.finding_group + for finding in to_mitigate + if finding.finding_group is not None ): jira_helper.push_to_jira(finding_group) diff --git a/dojo/metrics/views.py b/dojo/metrics/views.py index cc2a726f49..09933edc51 100644 --- a/dojo/metrics/views.py +++ b/dojo/metrics/views.py @@ -405,7 +405,7 @@ def metrics(request, mtype): # legacy code calls has 'prod_type' as 'related_name' for product.... so weird looking prefetch prod_type = prod_type.prefetch_related('prod_type') - filters = dict() + filters = {} if view == 'Finding': page_name = _('Product Type Metrics by Findings') filters = finding_querys(prod_type, request) @@ -428,8 +428,8 @@ def metrics(request, mtype): for obj in filters['closed'] ]) - punchcard = list() - ticks = list() + punchcard = [] + ticks = [] if 'view' in request.GET and 'dashboard' == request.GET['view']: punchcard, ticks = get_punchcard_data(queryset_check(filters['all']), filters['start_date'], filters['weeks_between'], view) @@ -1015,7 +1015,7 @@ def view_engineer(request, eid): mitigated__isnull=True, active=True).count() vulns[product.id] = f_count - od = OrderedDict(sorted(list(vulns.items()), key=itemgetter(1))) + od = OrderedDict(sorted(vulns.items(), key=itemgetter(1))) items = list(od.items()) items.reverse() top = items[: 10] diff --git a/dojo/models.py b/dojo/models.py index 157e1ec7e7..6d18e724a4 100755 --- a/dojo/models.py +++ b/dojo/models.py @@ -1656,7 +1656,7 @@ def clean(self): if self.path or self.path == '': while len(self.path) > 0 and self.path[0] == "/": # Endpoint store "root-less" path self.path = self.path[1:] - if any([null_char in self.path for null_char in null_char_list]): + if any(null_char in self.path for null_char in null_char_list): old_value = self.path if 'postgres' in db_type: action_string = 'Postgres does not accept NULL character. Attempting to replace with %00...' @@ -1669,7 +1669,7 @@ def clean(self): if self.query or self.query == '': if len(self.query) > 0 and self.query[0] == "?": self.query = self.query[1:] - if any([null_char in self.query for null_char in null_char_list]): + if any(null_char in self.query for null_char in null_char_list): old_value = self.query if 'postgres' in db_type: action_string = 'Postgres does not accept NULL character. Attempting to replace with %00...' @@ -1682,7 +1682,7 @@ def clean(self): if self.fragment or self.fragment == '': if len(self.fragment) > 0 and self.fragment[0] == "#": self.fragment = self.fragment[1:] - if any([null_char in self.fragment for null_char in null_char_list]): + if any(null_char in self.fragment for null_char in null_char_list): old_value = self.fragment if 'postgres' in db_type: action_string = 'Postgres does not accept NULL character. Attempting to replace with %00...' @@ -2698,24 +2698,16 @@ def get_vulnerability_ids(self): if self.unsaved_vulnerability_ids: deduplicationLogger.debug("get_vulnerability_ids before the finding was saved") # convert list of unsaved vulnerability_ids to the list of their canonical representation - vulnerability_id_str_list = list( - map( - lambda vulnerability_id: str(vulnerability_id), - self.unsaved_vulnerability_ids - )) + vulnerability_id_str_list = [str(vulnerability_id) for vulnerability_id in self.unsaved_vulnerability_ids] # deduplicate (usually done upon saving finding) and sort endpoints - vulnerability_id_str = ''.join(sorted(list(dict.fromkeys(vulnerability_id_str_list)))) + vulnerability_id_str = ''.join(sorted(dict.fromkeys(vulnerability_id_str_list))) else: deduplicationLogger.debug("finding has no unsaved vulnerability references") else: vulnerability_ids = Vulnerability_Id.objects.filter(finding=self) deduplicationLogger.debug("get_vulnerability_ids after the finding was saved. Vulnerability references count: " + str(vulnerability_ids.count())) # convert list of vulnerability_ids to the list of their canonical representation - vulnerability_id_str_list = list( - map( - lambda vulnerability_id: str(vulnerability_id), - vulnerability_ids.all() - )) + vulnerability_id_str_list = [str(vulnerability_id) for vulnerability_id in vulnerability_ids.all()] # sort vulnerability_ids strings vulnerability_id_str = ''.join(sorted(vulnerability_id_str_list)) return vulnerability_id_str @@ -2728,17 +2720,11 @@ def get_endpoints(self): if len(self.unsaved_endpoints) > 0: deduplicationLogger.debug("get_endpoints before the finding was saved") # convert list of unsaved endpoints to the list of their canonical representation - endpoint_str_list = list( - map( - lambda endpoint: str(endpoint), - self.unsaved_endpoints - )) + endpoint_str_list = [str(endpoint) for endpoint in self.unsaved_endpoints] # deduplicate (usually done upon saving finding) and sort endpoints endpoint_str = ''.join( sorted( - list( - dict.fromkeys(endpoint_str_list) - ))) + dict.fromkeys(endpoint_str_list))) else: # we can get here when the parser defines static_finding=True but leaves dynamic_finding defaulted # In this case, before saving the finding, both static_finding and dynamic_finding are True @@ -2747,11 +2733,7 @@ def get_endpoints(self): else: deduplicationLogger.debug("get_endpoints: after the finding was saved. Endpoints count: " + str(self.endpoints.count())) # convert list of endpoints to the list of their canonical representation - endpoint_str_list = list( - map( - lambda endpoint: str(endpoint), - self.endpoints.all() - )) + endpoint_str_list = [str(endpoint) for endpoint in self.endpoints.all()] # sort endpoints strings endpoint_str = ''.join( sorted( @@ -3304,7 +3286,7 @@ def get_references_with_links(self): def vulnerability_ids(self): # Get vulnerability ids from database and convert to list of strings vulnerability_ids_model = self.vulnerability_id_set.all() - vulnerability_ids = list() + vulnerability_ids = [] for vulnerability_id in vulnerability_ids_model: vulnerability_ids.append(vulnerability_id.vulnerability_id) @@ -3398,7 +3380,7 @@ def has_jira_issue(self): def severity(self): if not self.findings.all(): return None - max_number_severity = max([Finding.get_number_severity(find.severity) for find in self.findings.all()]) + max_number_severity = max(Finding.get_number_severity(find.severity) for find in self.findings.all()) return Finding.get_severity(max_number_severity) @cached_property @@ -3414,7 +3396,7 @@ def age(self): if not self.findings.all(): return None - return max([find.age for find in self.findings.all()]) + return max(find.age for find in self.findings.all()) @cached_property def sla_days_remaining_internal(self): @@ -3436,20 +3418,20 @@ def status(self): if not self.findings.all(): return None - if any([find.active for find in self.findings.all()]): + if any(find.active for find in self.findings.all()): return 'Active' - if all([find.is_mitigated for find in self.findings.all()]): + if all(find.is_mitigated for find in self.findings.all()): return 'Mitigated' return 'Inactive' @cached_property def mitigated(self): - return all([find.mitigated is not None for find in self.findings.all()]) + return all(find.mitigated is not None for find in self.findings.all()) def get_sla_start_date(self): - return min([find.get_sla_start_date() for find in self.findings.all()]) + return min(find.get_sla_start_date() for find in self.findings.all()) def get_absolute_url(self): from django.urls import reverse @@ -3503,7 +3485,7 @@ def get_absolute_url(self): def vulnerability_ids(self): # Get vulnerability ids from database and convert to list of strings vulnerability_ids_model = self.vulnerability_id_template_set.all() - vulnerability_ids = list() + vulnerability_ids = [] for vulnerability_id in vulnerability_ids_model: vulnerability_ids.append(vulnerability_id.vulnerability_id) diff --git a/dojo/notifications/helper.py b/dojo/notifications/helper.py index 1ee9a9be20..c492b407f6 100644 --- a/dojo/notifications/helper.py +++ b/dojo/notifications/helper.py @@ -391,10 +391,10 @@ def notify_test_created(test): def notify_scan_added(test, updated_count, new_findings=[], findings_mitigated=[], findings_reactivated=[], findings_untouched=[]): logger.debug("Scan added notifications") - new_findings = sorted(list(new_findings), key=lambda x: x.numerical_severity) - findings_mitigated = sorted(list(findings_mitigated), key=lambda x: x.numerical_severity) - findings_reactivated = sorted(list(findings_reactivated), key=lambda x: x.numerical_severity) - findings_untouched = sorted(list(findings_untouched), key=lambda x: x.numerical_severity) + new_findings = sorted(new_findings, key=lambda x: x.numerical_severity) + findings_mitigated = sorted(findings_mitigated, key=lambda x: x.numerical_severity) + findings_reactivated = sorted(findings_reactivated, key=lambda x: x.numerical_severity) + findings_untouched = sorted(findings_untouched, key=lambda x: x.numerical_severity) title = 'Created/Updated ' + str(updated_count) + " findings for " + str(test.engagement.product) + ': ' + str(test.engagement.name) + ': ' + str(test) diff --git a/dojo/product/views.py b/dojo/product/views.py index ec62a10004..55362b5f18 100755 --- a/dojo/product/views.py +++ b/dojo/product/views.py @@ -307,7 +307,7 @@ def identify_view(request): def finding_querys(request, prod): - filters = dict() + filters = {} findings_query = Finding.objects.filter(test__engagement__product=prod) # prefetch only what's needed to avoid lots of repeated queries findings_query = findings_query.prefetch_related( @@ -376,7 +376,7 @@ def finding_querys(request, prod): def endpoint_querys(request, prod): - filters = dict() + filters = {} endpoints_query = Endpoint_Status.objects.filter(finding__test__engagement__product=prod, finding__severity__in=( 'Critical', 'High', 'Medium', 'Low', 'Info')).prefetch_related( @@ -474,7 +474,7 @@ def view_product_metrics(request, pid): inactive_engs_page = get_page_items(request, result.qs, 10) - filters = dict() + filters = {} if view == 'Finding': filters = finding_querys(request, prod) elif view == 'Endpoint': diff --git a/dojo/reports/views.py b/dojo/reports/views.py index b6c3024bb0..b6782a317b 100644 --- a/dojo/reports/views.py +++ b/dojo/reports/views.py @@ -436,7 +436,7 @@ def generate_report(request, obj, host_view=False): report_title = "Product Report" findings = ReportFindingFilter(request.GET, product=product, queryset=prefetch_related_findings_for_report(Finding.objects.filter( test__engagement__product=product))) - ids = set(finding.id for finding in findings.qs) + ids = set(finding.id for finding in findings.qs) # noqa: C401 engagements = Engagement.objects.filter(test__finding__id__in=ids).distinct() tests = Test.objects.filter(finding__id__in=ids).distinct() endpoints = Endpoint.objects.filter(product=product).distinct() @@ -467,7 +467,7 @@ def generate_report(request, obj, host_view=False): template = 'dojo/engagement_pdf_report.html' report_title = "Engagement Report" - ids = set(finding.id for finding in findings.qs) + ids = set(finding.id for finding in findings.qs) # noqa: C401 tests = Test.objects.filter(finding__id__in=ids).distinct() endpoints = Endpoint.objects.filter(product=engagement.product).distinct() diff --git a/dojo/templatetags/display_tags.py b/dojo/templatetags/display_tags.py index b07d74ff77..f09fca50a8 100644 --- a/dojo/templatetags/display_tags.py +++ b/dojo/templatetags/display_tags.py @@ -797,7 +797,7 @@ def first_vulnerability_id(finding): def additional_vulnerability_ids(finding): vulnerability_ids = finding.vulnerability_ids if vulnerability_ids and len(vulnerability_ids) > 1: - references = list() + references = [] for vulnerability_id in vulnerability_ids[1:]: references.append(vulnerability_id) return references diff --git a/dojo/tools/acunetix/parse_acunetix360_json.py b/dojo/tools/acunetix/parse_acunetix360_json.py index 0f8c01c581..75fb523820 100644 --- a/dojo/tools/acunetix/parse_acunetix360_json.py +++ b/dojo/tools/acunetix/parse_acunetix360_json.py @@ -8,9 +8,9 @@ class AcunetixJSONParser: """This parser is written for Acunetix JSON Findings.""" def get_findings(self, filename, test): - dupes = dict() + dupes = {} data = json.load(filename) - dupes = dict() + dupes = {} scan_date = parser.parse(data["Generated"]) text_maker = html2text.HTML2Text() text_maker.body_width = 0 diff --git a/dojo/tools/acunetix/parse_acunetix_xml.py b/dojo/tools/acunetix/parse_acunetix_xml.py index 529da45e99..da84cbe853 100644 --- a/dojo/tools/acunetix/parse_acunetix_xml.py +++ b/dojo/tools/acunetix/parse_acunetix_xml.py @@ -12,7 +12,7 @@ class AcunetixXMLParser: """This parser is written for Acunetix XML reports""" def get_findings(self, filename, test): - dupes = dict() + dupes = {} root = parse(filename).getroot() for scan in root.findall("Scan"): start_url = scan.findtext("StartURL") @@ -81,7 +81,7 @@ def get_findings(self, filename, test): ) ) # add requests - finding.unsaved_req_resp = list() + finding.unsaved_req_resp = [] if len(item.findall("TechnicalDetails/Request")): finding.dynamic_finding = ( True # if there is some requests it's dynamic diff --git a/dojo/tools/anchore_engine/parser.py b/dojo/tools/anchore_engine/parser.py index f734b4a489..aeb2aab875 100644 --- a/dojo/tools/anchore_engine/parser.py +++ b/dojo/tools/anchore_engine/parser.py @@ -15,7 +15,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, filename, test): data = json.load(filename) - dupes = dict() + dupes = {} for item in data["vulnerabilities"]: vulnerability_id = item.get("vuln") diff --git a/dojo/tools/anchore_enterprise/parser.py b/dojo/tools/anchore_enterprise/parser.py index 82dad174d7..0ba332d696 100644 --- a/dojo/tools/anchore_enterprise/parser.py +++ b/dojo/tools/anchore_enterprise/parser.py @@ -27,7 +27,7 @@ def get_findings(self, filename, test): data = json.loads(content) find_date = datetime.now() - items = list() + items = [] try: for checks in data: for policies in checks.values(): diff --git a/dojo/tools/anchore_grype/parser.py b/dojo/tools/anchore_grype/parser.py index 94b7188cf7..f129a7c9b3 100644 --- a/dojo/tools/anchore_grype/parser.py +++ b/dojo/tools/anchore_grype/parser.py @@ -25,7 +25,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, file, test): data = json.load(file) - dupes = dict() + dupes = {} for item in data.get("matches", []): vulnerability = item["vulnerability"] vuln_id = vulnerability["id"] @@ -203,7 +203,7 @@ def get_cvss(self, cvss): return None def get_vulnerability_ids(self, vuln_id, related_vulnerabilities): - vulnerability_ids = list() + vulnerability_ids = [] if vuln_id: vulnerability_ids.append(vuln_id) if related_vulnerabilities: diff --git a/dojo/tools/anchorectl_policies/parser.py b/dojo/tools/anchorectl_policies/parser.py index 3de3f5d0c1..e02d169be2 100644 --- a/dojo/tools/anchorectl_policies/parser.py +++ b/dojo/tools/anchorectl_policies/parser.py @@ -27,7 +27,7 @@ def get_findings(self, filename, test): data = json.loads(content) find_date = datetime.now() - items = list() + items = [] try: for image in data: if image['detail'] is not None: diff --git a/dojo/tools/anchorectl_vulns/parser.py b/dojo/tools/anchorectl_vulns/parser.py index 652ac821af..70371a955b 100644 --- a/dojo/tools/anchorectl_vulns/parser.py +++ b/dojo/tools/anchorectl_vulns/parser.py @@ -15,7 +15,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, filename, test): data = json.load(filename) - dupes = dict() + dupes = {} for item in data: vulnerability_id = item.get("vuln") diff --git a/dojo/tools/api_bugcrowd/api_client.py b/dojo/tools/api_bugcrowd/api_client.py index f1207bd77a..ad72f9174e 100644 --- a/dojo/tools/api_bugcrowd/api_client.py +++ b/dojo/tools/api_bugcrowd/api_client.py @@ -91,7 +91,7 @@ def test_connection(self): progs = list(filter(lambda prog: prog["type"] == "program", data)) program_names = ", ".join( - list(map(lambda p: p["attributes"]["code"], progs)) + [p["attributes"]["code"] for p in progs] ) # Request targets to validate the org token response_targets = self.session.get( @@ -104,7 +104,7 @@ def test_connection(self): filter(lambda prog: prog["type"] == "target", data_targets) ) target_names = ", ".join( - list(map(lambda p: p["attributes"]["name"], targets)) + [p["attributes"]["name"] for p in targets] ) return ( f'With {total_subs} submissions, you have access to the "{program_names}" ' diff --git a/dojo/tools/api_vulners/parser.py b/dojo/tools/api_vulners/parser.py index 50674e5130..04969f19c3 100644 --- a/dojo/tools/api_vulners/parser.py +++ b/dojo/tools/api_vulners/parser.py @@ -42,9 +42,9 @@ def get_findings(self, file, test): findings = [] if file: - data = json.load(file).get("data", dict()) - report = data.get("report", list()) - vulns = data.get("vulns", dict()) + data = json.load(file).get("data", {}) + report = data.get("report", []) + vulns = data.get("vulns", {}) else: report = VulnersImporter().get_findings(test) vulns_id = [vuln.get("vulnID") for vuln in report] @@ -53,7 +53,7 @@ def get_findings(self, file, test): # for each issue found for component in report: id = component.get("vulnID") - vuln = vulns.get(id, dict()) + vuln = vulns.get(id, {}) title = component.get("title", id) family = component.get("family") agentip = component.get("agentip") diff --git a/dojo/tools/appspider/parser.py b/dojo/tools/appspider/parser.py index 6b76df3718..8cb0753f0c 100644 --- a/dojo/tools/appspider/parser.py +++ b/dojo/tools/appspider/parser.py @@ -29,7 +29,7 @@ def get_findings(self, filename, test): "At this time it is the only file that is consumable by DefectDojo." ) - dupes = dict() + dupes = {} for finding in root.iter("Vuln"): severity = self.convert_severity(finding.find("AttackScore").text) @@ -41,8 +41,8 @@ def get_findings(self, filename, test): cwe = int(finding.find("CweId").text) dupe_key = severity + title - unsaved_endpoints = list() - unsaved_req_resp = list() + unsaved_endpoints = [] + unsaved_req_resp = [] if title is None: title = "" diff --git a/dojo/tools/arachni/parser.py b/dojo/tools/arachni/parser.py index 334b671b01..7ca6528de0 100755 --- a/dojo/tools/arachni/parser.py +++ b/dojo/tools/arachni/parser.py @@ -74,7 +74,7 @@ def get_item(self, item_node, report_date): resp += str(key) + ": " + str(value) + "\n\n" resp += "\n\n\n" + force_str(respz["body"]) - unsaved_req_resp = list() + unsaved_req_resp = [] if request is not None and respz is not None: unsaved_req_resp.append({"req": req, "resp": resp}) diff --git a/dojo/tools/asff/parser.py b/dojo/tools/asff/parser.py index a936a831f3..f47dd87645 100644 --- a/dojo/tools/asff/parser.py +++ b/dojo/tools/asff/parser.py @@ -26,7 +26,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, file, test): data = json.load(file) - result = list() + result = [] for item in data: if item.get("Remediation"): mitigation = item.get("Remediation").get("Recommendation").get("Text") diff --git a/dojo/tools/auditjs/parser.py b/dojo/tools/auditjs/parser.py index 6249f1b045..9cd6f8399d 100644 --- a/dojo/tools/auditjs/parser.py +++ b/dojo/tools/auditjs/parser.py @@ -39,7 +39,7 @@ def get_findings(self, filename, test): raise ValueError( "Invalid JSON format. Are you sure you used --json option ?" ) - dupes = dict() + dupes = {} for dependency in data: # reading package name in format pkg:npm/PACKAGE_NAME@PACKAGE_VERSION diff --git a/dojo/tools/aws_prowler/parser.py b/dojo/tools/aws_prowler/parser.py index 9659262fb8..9b92261c60 100644 --- a/dojo/tools/aws_prowler/parser.py +++ b/dojo/tools/aws_prowler/parser.py @@ -34,7 +34,7 @@ def process_csv(self, file, test): content = content.decode("utf-8") csv.field_size_limit(int(sys.maxsize / 10)) # the request/resp are big reader = csv.DictReader(io.StringIO(content)) - dupes = dict() + dupes = {} account = None @@ -130,7 +130,7 @@ def process_csv(self, file, test): return list(dupes.values()) def process_json(self, file, test): - dupes = dict() + dupes = {} data = file.readlines() for issue in data: diff --git a/dojo/tools/aws_prowler_v3/parser.py b/dojo/tools/aws_prowler_v3/parser.py index e0e6910fd7..2154141c1f 100644 --- a/dojo/tools/aws_prowler_v3/parser.py +++ b/dojo/tools/aws_prowler_v3/parser.py @@ -26,7 +26,7 @@ def get_findings(self, file, test): raise ValueError('Unknown file format') def process_json(self, file, test): - dupes = dict() + dupes = {} data = json.load(file) for deserialized in data: diff --git a/dojo/tools/awssecurityhub/guardduty.py b/dojo/tools/awssecurityhub/guardduty.py index 7a663dcf1d..5ec977e46d 100644 --- a/dojo/tools/awssecurityhub/guardduty.py +++ b/dojo/tools/awssecurityhub/guardduty.py @@ -34,7 +34,7 @@ def get_item(self, finding: dict, test): description += f"AwsAccountId: {finding.get('AwsAccountId', '')}\n" description += f"Region: {finding.get('Region', '')}\n" title_suffix = "" - hosts = list() + hosts = [] for resource in finding.get("Resources", []): component_name = resource.get("Type") if component_name in ("AwsEcrContainerImage", "AwsEc2Instance"): @@ -73,7 +73,7 @@ def get_item(self, finding: dict, test): dynamic_finding=False, component_name=component_name, ) - result.unsaved_endpoints = list() + result.unsaved_endpoints = [] result.unsaved_endpoints.extend(hosts) if epss_score is not None: result.epss_score = epss_score diff --git a/dojo/tools/awssecurityhub/inspector.py b/dojo/tools/awssecurityhub/inspector.py index ce0b7701ad..2eecd309c2 100644 --- a/dojo/tools/awssecurityhub/inspector.py +++ b/dojo/tools/awssecurityhub/inspector.py @@ -47,7 +47,7 @@ def get_item(self, finding: dict, test): else: mitigated = datetime.utcnow() title_suffix = "" - hosts = list() + hosts = [] for resource in finding.get("Resources", []): component_name = resource.get("Type") hosts.append(Endpoint(host=f"{component_name} {resource.get('Id')}")) @@ -85,7 +85,7 @@ def get_item(self, finding: dict, test): dynamic_finding=False, component_name=component_name, ) - result.unsaved_endpoints = list() + result.unsaved_endpoints = [] result.unsaved_endpoints.extend(hosts) if epss_score is not None: result.epss_score = epss_score diff --git a/dojo/tools/bandit/parser.py b/dojo/tools/bandit/parser.py index e1f8327756..1641e37327 100644 --- a/dojo/tools/bandit/parser.py +++ b/dojo/tools/bandit/parser.py @@ -17,7 +17,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, filename, test): data = json.load(filename) - results = list() + results = [] if "generated_at" in data: find_date = dateutil.parser.parse(data["generated_at"]) diff --git a/dojo/tools/bearer_cli/parser.py b/dojo/tools/bearer_cli/parser.py index 856b752c28..c0a9735150 100644 --- a/dojo/tools/bearer_cli/parser.py +++ b/dojo/tools/bearer_cli/parser.py @@ -19,7 +19,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, file, test): data = json.load(file) - items = list() + items = [] dupes = set() for content in data: diff --git a/dojo/tools/blackduck/importer.py b/dojo/tools/blackduck/importer.py index 8ab2c0d89d..7c1e098a37 100644 --- a/dojo/tools/blackduck/importer.py +++ b/dojo/tools/blackduck/importer.py @@ -32,7 +32,7 @@ def _process_csvfile(self, report): If passed in a regular security.csv, process it. No file information then. """ - security_issues = dict() + security_issues = {} with open(str(report)) as f: security_issues = self.__partition_by_key(f) @@ -46,8 +46,8 @@ def _process_zipfile(self, report): Will take a zip file, look for security.csv and files.csv and union them on project id. This allows to have the file component for a vulnerability. """ - files = dict() - security_issues = dict() + files = {} + security_issues = {} with zipfile.ZipFile(str(report)) as zip: for full_file_name in zip.namelist(): diff --git a/dojo/tools/blackduck/parser.py b/dojo/tools/blackduck/parser.py index 94c35e9881..ea05cdb231 100644 --- a/dojo/tools/blackduck/parser.py +++ b/dojo/tools/blackduck/parser.py @@ -33,7 +33,7 @@ def normalize_findings(self, filename): return findings def ingest_findings(self, normalized_findings, test): - dupes = dict() + dupes = {} for i in normalized_findings: vulnerability_id = i.vuln_id cwe = 0 # need a way to automaticall retrieve that see #1119 diff --git a/dojo/tools/blackduck_binary_analysis/importer.py b/dojo/tools/blackduck_binary_analysis/importer.py index 3060838d7e..2c7528ae2d 100644 --- a/dojo/tools/blackduck_binary_analysis/importer.py +++ b/dojo/tools/blackduck_binary_analysis/importer.py @@ -26,7 +26,7 @@ def _process_csvfile(self, report, orig_report_name): """ If passed a CSV file, process. """ - vulnerabilities = dict() + vulnerabilities = {} with open(str(report)) as f: vulnerabilities = self.__partition_by_key(f) diff --git a/dojo/tools/blackduck_binary_analysis/parser.py b/dojo/tools/blackduck_binary_analysis/parser.py index baab6cd935..eb47fc7c7c 100644 --- a/dojo/tools/blackduck_binary_analysis/parser.py +++ b/dojo/tools/blackduck_binary_analysis/parser.py @@ -33,7 +33,7 @@ def sort_findings(self, filename): return findings def ingest_findings(self, sorted_findings, test): - findings = dict() + findings = {} for i in sorted_findings: file_path = str(i.object_full_path) object_sha1 = i.object_sha1 diff --git a/dojo/tools/blackduck_component_risk/importer.py b/dojo/tools/blackduck_component_risk/importer.py index da1f8c53cc..87f4160188 100644 --- a/dojo/tools/blackduck_component_risk/importer.py +++ b/dojo/tools/blackduck_component_risk/importer.py @@ -39,8 +39,8 @@ def _process_zipfile(self, report: Path) -> (dict, dict, dict): :param report: the file :return: (dict, dict, dict) """ - components = dict() - source = dict() + components = {} + source = {} try: with zipfile.ZipFile(str(report)) as zip: c_file = False diff --git a/dojo/tools/brakeman/parser.py b/dojo/tools/brakeman/parser.py index 50d130a13f..dfd23fa43c 100644 --- a/dojo/tools/brakeman/parser.py +++ b/dojo/tools/brakeman/parser.py @@ -26,7 +26,7 @@ def get_findings(self, filename, test): data = json.loads(str(tree, "utf-8")) except BaseException: data = json.loads(tree) - dupes = dict() + dupes = {} find_date = parser.parse(data["scan_info"]["end_time"]) for item in data["warnings"]: diff --git a/dojo/tools/bugcrowd/parser.py b/dojo/tools/bugcrowd/parser.py index 1414e711a1..fcd36b1344 100644 --- a/dojo/tools/bugcrowd/parser.py +++ b/dojo/tools/bugcrowd/parser.py @@ -31,7 +31,7 @@ def get_findings(self, filename, test): for row in reader: csvarray.append(row) - dupes = dict() + dupes = {} for row in csvarray: finding = Finding(test=test) @@ -128,7 +128,7 @@ def get_findings(self, filename, test): finding.date = parser.parse(row.get("submitted_at")) if url: - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] finding.unsaved_endpoints.append(self.get_endpoint(url)) if finding is not None: diff --git a/dojo/tools/bundler_audit/parser.py b/dojo/tools/bundler_audit/parser.py index a098e6e3e6..c960bb374c 100644 --- a/dojo/tools/bundler_audit/parser.py +++ b/dojo/tools/bundler_audit/parser.py @@ -21,7 +21,7 @@ def get_findings(self, filename, test): if isinstance(lines, bytes): lines = lines.decode("utf-8") # passes in unittests, but would fail in production - dupes = dict() + dupes = {} find_date = datetime.now() warnings = lines.split("\n\n") diff --git a/dojo/tools/burp/parser.py b/dojo/tools/burp/parser.py index 82b24118d7..cb7e461f33 100755 --- a/dojo/tools/burp/parser.py +++ b/dojo/tools/burp/parser.py @@ -124,8 +124,8 @@ def get_clean_base64(value): def do_clean_cwe(value): if value is None: - return list() - cwes = list() + return [] + cwes = [] if len(value) > 0: for x in value: if x.text is not None: @@ -145,7 +145,7 @@ def get_item(item_node, test): if rparameter: parameter = rparameter.group(1) - unsaved_req_resp = list() + unsaved_req_resp = [] for request_response in item_node.findall("./requestresponse"): request = get_clean_base64(request_response.findall("request")[0].text) if request_response.findall("response"): @@ -160,7 +160,7 @@ def get_item(item_node, test): collab_text = "" for event in item_node.findall("./collaboratorEvent"): - collab_details = list() + collab_details = [] collab_details.append(event.findall("interactionType")[0].text) collab_details.append(event.findall("originIp")[0].text) collab_details.append(event.findall("time")[0].text) diff --git a/dojo/tools/burp_api/parser.py b/dojo/tools/burp_api/parser.py index 01f30faffb..97d8d40ef7 100644 --- a/dojo/tools/burp_api/parser.py +++ b/dojo/tools/burp_api/parser.py @@ -33,7 +33,7 @@ def get_findings(self, file, test): items = [] # for each issue found - for issue_event in tree.get("issue_events", list()): + for issue_event in tree.get("issue_events", []): if ( "issue_found" == issue_event.get("type") and "issue" in issue_event diff --git a/dojo/tools/burp_dastardly/parser.py b/dojo/tools/burp_dastardly/parser.py index 70ee436a81..686fb59e1a 100755 --- a/dojo/tools/burp_dastardly/parser.py +++ b/dojo/tools/burp_dastardly/parser.py @@ -23,7 +23,7 @@ def get_findings(self, xml_output, test): return self.get_items(tree, test) def get_items(self, tree, test): - items = list() + items = [] for node in tree.findall("testsuite"): if int(node.attrib["failures"]) != 0: name = node.attrib["name"] diff --git a/dojo/tools/burp_enterprise/parser.py b/dojo/tools/burp_enterprise/parser.py index b54603ea99..4dc08625fb 100644 --- a/dojo/tools/burp_enterprise/parser.py +++ b/dojo/tools/burp_enterprise/parser.py @@ -70,7 +70,7 @@ def get_content(self, container): # Get the endpoints and severities associated with each vulnerability def pre_allocate_items(self, tree): - items = list() + items = [] endpoint_text = tree.xpath( "/html/body/div/div[contains(@class, 'section')]/h1" ) @@ -97,7 +97,7 @@ def pre_allocate_items(self, tree): else: endpoint = item_list[0].text.strip() severity = item_list[1].text.strip() - vuln = dict() + vuln = {} vuln["Severity"] = severity vuln["Title"] = title vuln["Description"] = "" @@ -119,7 +119,7 @@ def get_items(self, tree, test): "/html/body/div/div[contains(@class, 'section details')]/div[contains(@class, 'issue-container')]" ) if len(vulns) == 0: - return list() + return [] dict_index = 0 description = ["Issue detail:", "Issue description"] @@ -200,7 +200,7 @@ def create_findings(self, items, test): # Dictonary to hold the aggregated findings with: # - key: the concatenated aggregate keys # - value: the finding - dupes = dict() + dupes = {} for details in items: if details.get("Description") == "": continue @@ -234,14 +234,14 @@ def create_findings(self, items, test): if len(details.get("Request")) > 0: requests = details.get("Request").split("SPLITTER")[:-1] responses = details.get("Response").split("SPLITTER")[:-1] - unsaved_req_resp = list() + unsaved_req_resp = [] for index in range(0, len(requests)): unsaved_req_resp.append( {"req": requests[index], "resp": responses[index]} ) find.unsaved_req_resp = unsaved_req_resp - find.unsaved_endpoints = list() + find.unsaved_endpoints = [] dupes[aggregateKeys] = find for url in details.get("Endpoint"): diff --git a/dojo/tools/burp_graphql/parser.py b/dojo/tools/burp_graphql/parser.py index 34ebfbdbdf..4f2cce8a24 100644 --- a/dojo/tools/burp_graphql/parser.py +++ b/dojo/tools/burp_graphql/parser.py @@ -30,7 +30,7 @@ def get_findings(self, filename, test): def create_findings(self, scan_data, test): finding_data = self.parse_findings(scan_data) - items = list() + items = [] for issue in finding_data: find = Finding( @@ -58,7 +58,7 @@ def create_findings(self, scan_data, test): return items def parse_findings(self, scan_data): - issue_dict = dict() + issue_dict = {} for issue in scan_data: if not issue.get("issue_type") or not issue["issue_type"].get( @@ -95,7 +95,7 @@ def combine_findings(self, finding, issue): ) def create_finding(self, issue): - finding = dict() + finding = {} finding["Impact"] = "" finding["Description"] = "" finding["Mitigation"] = "" @@ -169,7 +169,7 @@ def create_finding(self, issue): def parse_evidence(self, evidence): evidence_len = len(evidence) - req_resp_list = list() + req_resp_list = [] i = 0 while i < evidence_len: diff --git a/dojo/tools/checkmarx/parser.py b/dojo/tools/checkmarx/parser.py index 3f67f97a51..1cfdfdac25 100755 --- a/dojo/tools/checkmarx/parser.py +++ b/dojo/tools/checkmarx/parser.py @@ -47,12 +47,12 @@ def _get_findings_xml(self, filename, test): cxscan = ElementTree.parse(filename) root = cxscan.getroot() - dupes = dict() - language_list = dict() + dupes = {} + language_list = {} # Dictionary to hold the vuln_id_from_tool values: # - key: the concatenated aggregate keys # - value: a list of vuln_id_from_tool - vuln_ids_from_tool = dict() + vuln_ids_from_tool = {} for query in root.findall("Query"): _name, _cwe, categories, _queryId = self.getQueryElements(query) language = "" diff --git a/dojo/tools/clair/clairklar_parser.py b/dojo/tools/clair/clairklar_parser.py index 263c18872f..f942ad30aa 100644 --- a/dojo/tools/clair/clairklar_parser.py +++ b/dojo/tools/clair/clairklar_parser.py @@ -5,7 +5,7 @@ class ClairKlarScan: def get_items_klar(self, tree, test): - items = list() + items = [] clair_severities = [ "Unknown", "Negligible", @@ -22,7 +22,7 @@ def get_items_klar(self, tree, test): return items def set_items_for_severity(self, tree, test, severity): - items = list() + items = [] tree_severity = tree.get(severity) if tree_severity: for data in self.get_items_clairklar(tree_severity, test): diff --git a/dojo/tools/clair/parser.py b/dojo/tools/clair/parser.py index 269bbcf5a0..592c7afae4 100644 --- a/dojo/tools/clair/parser.py +++ b/dojo/tools/clair/parser.py @@ -21,7 +21,7 @@ def get_findings(self, json_output, test): elif self.scanner == "clairklar": return ClairKlarScan().get_items_klar(tree, test) else: - return list() + return [] def parse_json(self, json_output): try: diff --git a/dojo/tools/cloudsploit/parser.py b/dojo/tools/cloudsploit/parser.py index b7b7d346e1..22e8de1a2b 100644 --- a/dojo/tools/cloudsploit/parser.py +++ b/dojo/tools/cloudsploit/parser.py @@ -25,7 +25,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, file, test): data = json.load(file) find_date = datetime.now() - dupes = dict() + dupes = {} for item in data: title = item["title"] if isinstance(item["region"], str): diff --git a/dojo/tools/cobalt/parser.py b/dojo/tools/cobalt/parser.py index f84ebbf12c..2e4a74f41f 100644 --- a/dojo/tools/cobalt/parser.py +++ b/dojo/tools/cobalt/parser.py @@ -19,7 +19,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, filename, test): if filename is None: - return list() + return [] content = filename.read() if isinstance(content, bytes): @@ -27,7 +27,7 @@ def get_findings(self, filename, test): reader = csv.DictReader( io.StringIO(content), delimiter=",", quotechar='"' ) - dupes = dict() + dupes = {} for row in reader: finding = Finding(test=test) finding.title = ( diff --git a/dojo/tools/contrast/parser.py b/dojo/tools/contrast/parser.py index e535260658..17d566ea5e 100644 --- a/dojo/tools/contrast/parser.py +++ b/dojo/tools/contrast/parser.py @@ -25,7 +25,7 @@ def get_findings(self, filename, test): content = content.decode("utf-8") csv.field_size_limit(int(sys.maxsize / 10)) # the request/resp are big reader = csv.DictReader(io.StringIO(content)) - dupes = dict() + dupes = {} for row in reader: # Vulnerability Name,Vulnerability ID,Category,Rule diff --git a/dojo/tools/coverity_api/parser.py b/dojo/tools/coverity_api/parser.py index 38c361e882..8acba51e37 100644 --- a/dojo/tools/coverity_api/parser.py +++ b/dojo/tools/coverity_api/parser.py @@ -25,7 +25,7 @@ def get_findings(self, file, test): file.name, ) - items = list() + items = [] for issue in tree["viewContentsV1"]["rows"]: # get only security findings if "Security" != issue.get("displayIssueKind"): diff --git a/dojo/tools/crashtest_security/parser.py b/dojo/tools/crashtest_security/parser.py index efe086ed4f..b33273a2f9 100755 --- a/dojo/tools/crashtest_security/parser.py +++ b/dojo/tools/crashtest_security/parser.py @@ -34,7 +34,7 @@ def get_findings(self, file, test): ) # Iterate scanner which contain the items - items = list() + items = [] for scanner in crashtest_scan["findings"].values(): # Iterate all findings of the scanner for finding in scanner: @@ -154,7 +154,7 @@ def get_findings(self, xml_output, test): if tree: return self.get_items(tree, test) else: - return list() + return [] def parse_xml(self, xml_output): """ @@ -174,7 +174,7 @@ def get_items(self, tree, test): @return items A list of Host instances """ - items = list() + items = [] # Get all testcases for node in tree.findall(".//testcase"): @@ -240,7 +240,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, filename, test): if filename is None: - return list() + return [] if filename.name.lower().endswith(".xml"): return CrashtestSecurityXmlParser().get_findings(filename, test) diff --git a/dojo/tools/cred_scan/parser.py b/dojo/tools/cred_scan/parser.py index 9a8ab21e5d..bbca3b687a 100644 --- a/dojo/tools/cred_scan/parser.py +++ b/dojo/tools/cred_scan/parser.py @@ -30,7 +30,7 @@ def get_findings(self, filename, test): io.StringIO(content), delimiter=",", quotechar='"' ) - dupes = dict() + dupes = {} for row in reader: # Create the description description = row.get("Description", "Description not provided") diff --git a/dojo/tools/cyclonedx/json_parser.py b/dojo/tools/cyclonedx/json_parser.py index 9ee31275fc..ddd1dfbd7b 100644 --- a/dojo/tools/cyclonedx/json_parser.py +++ b/dojo/tools/cyclonedx/json_parser.py @@ -86,7 +86,7 @@ def _get_findings_json(self, file, test): finding.severity = Cyclonedxhelper().fix_severity(severity) else: finding.severity = cvssv3.severities()[0] - vulnerability_ids = list() + vulnerability_ids = [] # set id as first vulnerability id if vulnerability.get("id"): vulnerability_ids.append(vulnerability.get("id")) diff --git a/dojo/tools/cyclonedx/xml_parser.py b/dojo/tools/cyclonedx/xml_parser.py index 517dbc5478..81daf1b3cb 100644 --- a/dojo/tools/cyclonedx/xml_parser.py +++ b/dojo/tools/cyclonedx/xml_parser.py @@ -158,7 +158,7 @@ def manage_vulnerability_legacy( ) if len(cwes) > 0: finding.cwe = cwes[0] - vulnerability_ids = list() + vulnerability_ids = [] # set id as first vulnerability id if vuln_id: vulnerability_ids.append(vuln_id) @@ -207,7 +207,7 @@ def _manage_vulnerability_xml( if url: references += f"**URL:** {url}\n" references += "\n" - vulnerability_ids = list() + vulnerability_ids = [] # set id as first vulnerability id if vuln_id: vulnerability_ids.append(vuln_id) diff --git a/dojo/tools/dependency_check/parser.py b/dojo/tools/dependency_check/parser.py index 01ff28e2fd..493089dbce 100644 --- a/dojo/tools/dependency_check/parser.py +++ b/dojo/tools/dependency_check/parser.py @@ -347,7 +347,7 @@ def get_description_for_scan_types(self, scan_type): return "OWASP Dependency Check output can be imported in Xml format." def get_findings(self, filename, test): - dupes = dict() + dupes = {} namespace = "" content = filename.read() # 'utf-8' This line is to pass a unittest in test_parsers.TestParsers.test_file_existence. diff --git a/dojo/tools/dependency_track/parser.py b/dojo/tools/dependency_track/parser.py index c4e3dad351..4540297e98 100644 --- a/dojo/tools/dependency_track/parser.py +++ b/dojo/tools/dependency_track/parser.py @@ -265,7 +265,7 @@ def get_findings(self, file, test): # Exit if file is not provided if file is None: - return list() + return [] # Load the contents of the JSON file into a dictionary data = file.read() @@ -276,15 +276,15 @@ def get_findings(self, file, test): # Exit if file is an empty JSON dictionary if len(findings_export_dict.keys()) == 0: - return list() + return [] # Make sure the findings key exists in the dictionary and that it is not null or an empty list # If it is null or an empty list then exit if 'findings' not in findings_export_dict or not findings_export_dict['findings']: - return list() + return [] # Start with an empty list of findings - items = list() + items = [] # If we have gotten this far then there should be one or more findings # Loop through each finding from Dependency Track diff --git a/dojo/tools/dsop/parser.py b/dojo/tools/dsop/parser.py index 597e69c105..64bdc2250e 100644 --- a/dojo/tools/dsop/parser.py +++ b/dojo/tools/dsop/parser.py @@ -16,7 +16,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, file, test): book = load_workbook(file) - items = list() + items = [] self.__parse_disa(test, items, book["OpenSCAP - DISA Compliance"]) self.__parse_oval(test, items, book["OpenSCAP - OVAL Results"]) self.__parse_twistlock( @@ -29,7 +29,7 @@ def get_findings(self, file, test): return items def __parse_disa(self, test, items, sheet): - headers = dict() + headers = {} first = True for row in sheet.iter_rows(min_row=1, values_only=True): if first: @@ -75,7 +75,7 @@ def __parse_disa(self, test, items, sheet): def __parse_oval(self, test, items, sheet): severity_pattern = re.compile(r"\((.*)\)") - headers = dict() + headers = {} first = True for row in sheet.iter_rows(min_row=1, values_only=True): if first: @@ -121,7 +121,7 @@ def __parse_oval(self, test, items, sheet): items.append(finding) def __parse_twistlock(self, test, items, sheet): - headers = dict() + headers = {} first = True for row in sheet.iter_rows(min_row=1, values_only=True): if first: @@ -170,7 +170,7 @@ def __parse_twistlock(self, test, items, sheet): items.append(finding) def __parse_anchore(self, test, items, sheet): - headers = dict() + headers = {} first = True for row in sheet.iter_rows(min_row=1, values_only=True): if first: @@ -208,7 +208,7 @@ def __parse_anchore(self, test, items, sheet): items.append(finding) def __parse_anchore_compliance(self, test, items, sheet): - headers = dict() + headers = {} first = True for row in sheet.iter_rows(min_row=1, values_only=True): if first: diff --git a/dojo/tools/eslint/parser.py b/dojo/tools/eslint/parser.py index df8628f533..2b698e7b17 100644 --- a/dojo/tools/eslint/parser.py +++ b/dojo/tools/eslint/parser.py @@ -28,7 +28,7 @@ def get_findings(self, filename, test): except Exception: data = json.loads(tree) - items = list() + items = [] for item in data: findingdetail = "" diff --git a/dojo/tools/factory.py b/dojo/tools/factory.py index 55549cccd7..84cfaafa90 100755 --- a/dojo/tools/factory.py +++ b/dojo/tools/factory.py @@ -43,17 +43,17 @@ def get_parser(scan_type): def get_scan_types_sorted(): - res = list() + res = [] for key in PARSERS: res.append((key, PARSERS[key].get_description_for_scan_types(key))) - return sorted(tuple(res), key=lambda x: x[0].lower()) + return sorted(res, key=lambda x: x[0].lower()) def get_choices_sorted(): - res = list() + res = [] for key in PARSERS: res.append((key, key)) - return sorted(tuple(res), key=lambda x: x[1].lower()) + return sorted(res, key=lambda x: x[1].lower()) def requires_file(scan_type): @@ -68,7 +68,7 @@ def requires_file(scan_type): def get_api_scan_configuration_hints(): - res = list() + res = [] for name, parser in PARSERS.items(): if hasattr(parser, "api_scan_configuration_hint"): scan_types = parser.get_scan_types() diff --git a/dojo/tools/fortify/fpr_parser.py b/dojo/tools/fortify/fpr_parser.py index 8110a23cb9..811bfd4f82 100644 --- a/dojo/tools/fortify/fpr_parser.py +++ b/dojo/tools/fortify/fpr_parser.py @@ -18,7 +18,7 @@ def parse_fpr(self, filename, test): namespace = matches.group(0) except BaseException: namespace = "" - items = list() + items = [] for child in root: if "Vulnerabilities" in child.tag: for vuln in child: diff --git a/dojo/tools/generic/parser.py b/dojo/tools/generic/parser.py index 156fee56f1..d93feccc2b 100644 --- a/dojo/tools/generic/parser.py +++ b/dojo/tools/generic/parser.py @@ -50,7 +50,7 @@ def _get_test_json(self, data): type=data.get("type", self.ID), version=data.get("version"), ) - test_internal.findings = list() + test_internal.findings = [] for item in data.get("findings", []): # remove endpoints of the dictionnary unsaved_endpoints = None @@ -167,7 +167,7 @@ def _get_findings_csv(self, filename): io.StringIO(content), delimiter=",", quotechar='"' ) - dupes = dict() + dupes = {} for row in reader: finding = Finding( title=row["Title"], diff --git a/dojo/tools/ggshield/parser.py b/dojo/tools/ggshield/parser.py index a5b362f00b..d0bc8f5abc 100755 --- a/dojo/tools/ggshield/parser.py +++ b/dojo/tools/ggshield/parser.py @@ -24,7 +24,7 @@ def get_findings(self, filename, test): """ json_data = json.load(filename) issues = json_data.get("scans") - dupes = dict() + dupes = {} for issue in issues: if issue.get("total_incidents") > 0: diff --git a/dojo/tools/github_vulnerability/parser.py b/dojo/tools/github_vulnerability/parser.py index da848f1b7c..6a83b832cf 100644 --- a/dojo/tools/github_vulnerability/parser.py +++ b/dojo/tools/github_vulnerability/parser.py @@ -31,7 +31,7 @@ def get_findings(self, filename, test): ) if "url" in data["data"]["repository"]: repository_url = data["data"]["repository"]["url"] - dupes = dict() + dupes = {} for alert in vulnerabilityAlerts["nodes"]: description = alert["securityVulnerability"]["advisory"][ "description" @@ -79,7 +79,7 @@ def get_findings(self, filename, test): ]: finding.references += ref["url"] + "\r\n" if "identifiers" in alert["securityVulnerability"]["advisory"]: - unsaved_vulnerability_ids = list() + unsaved_vulnerability_ids = [] for identifier in alert["securityVulnerability"]["advisory"][ "identifiers" ]: @@ -132,7 +132,7 @@ def get_findings(self, filename, test): dupes[dupe_key] = finding return list(dupes.values()) elif isinstance(data, list): - findings = list() + findings = [] for vuln in data: url = vuln["url"] html_url = vuln["html_url"] diff --git a/dojo/tools/gitleaks/parser.py b/dojo/tools/gitleaks/parser.py index ae53b19227..f7ab81873f 100644 --- a/dojo/tools/gitleaks/parser.py +++ b/dojo/tools/gitleaks/parser.py @@ -25,9 +25,9 @@ def get_findings(self, filename, test): issues = json.load(filename) # empty report are just null object if issues is None: - return list() + return [] - dupes = dict() + dupes = {} for issue in issues: if issue.get("rule"): diff --git a/dojo/tools/gosec/parser.py b/dojo/tools/gosec/parser.py index 3efcbd9385..69056d9281 100644 --- a/dojo/tools/gosec/parser.py +++ b/dojo/tools/gosec/parser.py @@ -19,7 +19,7 @@ def get_findings(self, filename, test): data = json.loads(str(tree, "utf-8")) except Exception: data = json.loads(tree) - dupes = dict() + dupes = {} for item in data["Issues"]: impact = "" diff --git a/dojo/tools/h1/parser.py b/dojo/tools/h1/parser.py index 48c367684f..9708bedfc0 100644 --- a/dojo/tools/h1/parser.py +++ b/dojo/tools/h1/parser.py @@ -33,7 +33,7 @@ def get_findings(self, file, test): except Exception: tree = json.loads(data) # Convert JSON report to DefectDojo format - dupes = dict() + dupes = {} for content in tree["data"]: # Get all relevant data date = content["attributes"]["created_at"] @@ -114,7 +114,7 @@ def get_findings(self, file, test): cwe=cwe, dynamic_finding=False ) - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] dupes[dupe_key] = finding return dupes.values() diff --git a/dojo/tools/harbor_vulnerability/parser.py b/dojo/tools/harbor_vulnerability/parser.py index 5d7db07ed1..4186544b21 100644 --- a/dojo/tools/harbor_vulnerability/parser.py +++ b/dojo/tools/harbor_vulnerability/parser.py @@ -25,7 +25,7 @@ def get_findings(self, filename, test): data = json.loads(tree) # When doing dictionary, we can detect duplications - dupes = dict() + dupes = {} try: vulnerability = data["vulnerabilities"] # json output of https://pypi.org/project/harborapi/ @@ -39,7 +39,7 @@ def get_findings(self, filename, test): # Early exit if empty if 'vulnerability' not in locals() or vulnerability is None: - return list() + return [] for item in vulnerability: id = item.get("id") diff --git a/dojo/tools/hcl_appscan/parser.py b/dojo/tools/hcl_appscan/parser.py index b29cc465d7..0ac4adddd8 100755 --- a/dojo/tools/hcl_appscan/parser.py +++ b/dojo/tools/hcl_appscan/parser.py @@ -107,7 +107,7 @@ def get_findings(self, file, test): ) findings.append(finding) try: - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] endpoint = Endpoint(host=host, port=port) finding.unsaved_endpoints.append(endpoint) except UnboundLocalError: diff --git a/dojo/tools/ibm_app/parser.py b/dojo/tools/ibm_app/parser.py index f4389a9c5b..3ef856063d 100644 --- a/dojo/tools/ibm_app/parser.py +++ b/dojo/tools/ibm_app/parser.py @@ -30,7 +30,7 @@ def get_findings(self, file, test): # self.hosts = self.fetch_host_details() issue_types = self.fetch_issue_types(root) - dupes = dict() + dupes = {} # Now time to loop through individual issues and perform necessary # actions for issue in root.iter("issue-group"): @@ -107,7 +107,7 @@ def get_findings(self, file, test): finding.unsaved_vulnerability_ids = [ vulnerability_id ] - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] dupes[dupe_key] = finding # in case empty string is returned as url diff --git a/dojo/tools/immuniweb/parser.py b/dojo/tools/immuniweb/parser.py index 9b7af871d9..fdd90c9c8b 100644 --- a/dojo/tools/immuniweb/parser.py +++ b/dojo/tools/immuniweb/parser.py @@ -26,7 +26,7 @@ def get_findings(self, file, test): "This does not look like a valid expected Immuniweb XML file." ) - dupes = dict() + dupes = {} for vulnerability in root.iter("Vulnerability"): """ @@ -83,7 +83,7 @@ def get_findings(self, file, test): ) if vulnerability_id: finding.unsaved_vulnerability_ids = [vulnerability_id] - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] dupes[dupe_key] = finding finding.unsaved_endpoints.append(Endpoint.from_uri(url)) diff --git a/dojo/tools/intsights/json_handler.py b/dojo/tools/intsights/json_handler.py index 3455548b09..ec315ac101 100644 --- a/dojo/tools/intsights/json_handler.py +++ b/dojo/tools/intsights/json_handler.py @@ -14,7 +14,7 @@ def _parse_json(self, json_file) -> [dict]: original_alerts = json.load(json_file) for original_alert in original_alerts.get("Alerts", []): - alert = dict() + alert = {} alert["alert_id"] = original_alert["_id"] alert["title"] = original_alert["Details"]["Title"] alert["description"] = original_alert["Details"]["Description"] diff --git a/dojo/tools/intsights/parser.py b/dojo/tools/intsights/parser.py index 094dc4d795..2ad4d7ae92 100644 --- a/dojo/tools/intsights/parser.py +++ b/dojo/tools/intsights/parser.py @@ -43,7 +43,7 @@ def _build_finding_description(self, alert: dict) -> str: return description def get_findings(self, file, test): - duplicates = dict() + duplicates = {} if file.name.lower().endswith(".json"): alerts = IntSightsJSONParser()._parse_json( file, diff --git a/dojo/tools/jfrog_xray_api_summary_artifact/parser.py b/dojo/tools/jfrog_xray_api_summary_artifact/parser.py index 09a6066d04..43a8145ffb 100644 --- a/dojo/tools/jfrog_xray_api_summary_artifact/parser.py +++ b/dojo/tools/jfrog_xray_api_summary_artifact/parser.py @@ -75,7 +75,7 @@ def get_item( # Some entries have no CVE entries, despite they exist. Example # CVE-2017-1000502. cves = vulnerability.get("cves", []) - vulnerability_ids = list() + vulnerability_ids = [] if cves: if len(cves[0].get("cwe", [])) > 0: cwe = decode_cwe_number(cves[0].get("cwe", [])[0]) @@ -138,7 +138,7 @@ def get_item( finding.unsaved_vulnerability_ids = vulnerability_ids # Add vulnerability ids - vulnerability_ids = list() + vulnerability_ids = [] if cves and "cve" in cves[0]: vulnerability_ids.append(cves[0]["cve"]) if "issue_id" in vulnerability: diff --git a/dojo/tools/jfrog_xray_on_demand_binary_scan/parser.py b/dojo/tools/jfrog_xray_on_demand_binary_scan/parser.py index 0839ef5acf..786635b3ff 100644 --- a/dojo/tools/jfrog_xray_on_demand_binary_scan/parser.py +++ b/dojo/tools/jfrog_xray_on_demand_binary_scan/parser.py @@ -150,7 +150,7 @@ def get_item_set(vulnerability): severity = get_severity(vulnerability) references = get_references(vulnerability) vuln_id_from_tool = get_vuln_id_from_tool(vulnerability) - vulnerability_ids = list() + vulnerability_ids = [] cvssv3 = None cvss_v3 = "No CVSS v3 score." # Some entries have no CVE entries, despite they exist. Example CVE-2017-1000502. diff --git a/dojo/tools/jfrogxray/parser.py b/dojo/tools/jfrogxray/parser.py index 5017bdb7d3..36ffa900cf 100644 --- a/dojo/tools/jfrogxray/parser.py +++ b/dojo/tools/jfrogxray/parser.py @@ -73,7 +73,7 @@ def get_item(vulnerability, test): else: severity = "Info" - vulnerability_ids = list() + vulnerability_ids = [] cwe = None cvssv3 = None cvss_v3 = "No CVSS v3 score." diff --git a/dojo/tools/kiuwan/parser.py b/dojo/tools/kiuwan/parser.py index 98ba9b2952..4eeb8146af 100644 --- a/dojo/tools/kiuwan/parser.py +++ b/dojo/tools/kiuwan/parser.py @@ -47,7 +47,7 @@ def get_findings(self, filename, test): for row in reader: csvarray.append(row) - dupes = dict() + dupes = {} for row in csvarray: finding = Finding(test=test) findingdict = {} diff --git a/dojo/tools/kubeaudit/parser.py b/dojo/tools/kubeaudit/parser.py index 4b37d6d8ee..2fc887685c 100644 --- a/dojo/tools/kubeaudit/parser.py +++ b/dojo/tools/kubeaudit/parser.py @@ -25,7 +25,7 @@ def severity_mapping(self, input): def get_findings(self, filename, test): lines = filename.readlines() - findings = list() + findings = [] for line in lines: try: tree = json.loads(str(line, "utf-8")) diff --git a/dojo/tools/kubehunter/parser.py b/dojo/tools/kubehunter/parser.py index c7688033dd..af60ef19da 100644 --- a/dojo/tools/kubehunter/parser.py +++ b/dojo/tools/kubehunter/parser.py @@ -20,7 +20,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, file, test): data = json.load(file) - dupes = dict() + dupes = {} # Find any missing attribute vulnerabilities = data['vulnerabilities'] diff --git a/dojo/tools/mend/parser.py b/dojo/tools/mend/parser.py index 965a725d32..5fc6464526 100644 --- a/dojo/tools/mend/parser.py +++ b/dojo/tools/mend/parser.py @@ -21,7 +21,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, file, test): if file is None: - return list() + return [] data = file.read() try: @@ -155,7 +155,7 @@ def create_finding_key(f: Finding) -> str: + f.title.encode("utf-8") ).hexdigest() - dupes = dict() + dupes = {} for finding in findings: dupe_key = create_finding_key(finding) if dupe_key not in dupes: diff --git a/dojo/tools/microfocus_webinspect/parser.py b/dojo/tools/microfocus_webinspect/parser.py index c6c5ccd7a4..228a861c7c 100644 --- a/dojo/tools/microfocus_webinspect/parser.py +++ b/dojo/tools/microfocus_webinspect/parser.py @@ -28,7 +28,7 @@ def get_findings(self, file, test): "This doesn't seem to be a valid Webinspect xml file." ) - dupes = dict() + dupes = {} for session in root: url = session.find("URL").text endpoint = Endpoint.from_uri(url) diff --git a/dojo/tools/mozilla_observatory/parser.py b/dojo/tools/mozilla_observatory/parser.py index 2f901de698..1d88b3cf11 100644 --- a/dojo/tools/mozilla_observatory/parser.py +++ b/dojo/tools/mozilla_observatory/parser.py @@ -30,7 +30,7 @@ def get_findings(self, file, test): else: nodes = data - findings = list() + findings = [] for key in nodes: node = nodes[key] diff --git a/dojo/tools/ms_defender/parser.py b/dojo/tools/ms_defender/parser.py index ab6346fac0..6cf4ba3cf3 100644 --- a/dojo/tools/ms_defender/parser.py +++ b/dojo/tools/ms_defender/parser.py @@ -34,15 +34,15 @@ def get_findings(self, file, test): if zipdata.get('machines/') is None or zipdata.get('vulnerabilities/') is None: return [] else: - vulnerabilityfiles = list() - machinefiles = list() + vulnerabilityfiles = [] + machinefiles = [] for content in list(zipdata): if "vulnerabilities/" in content and "vulnerabilities/" != content: vulnerabilityfiles.append(content) if "machines/" in content and "machines/" != content: machinefiles.append(content) - vulnerabilities = list() - machines = list() + vulnerabilities = [] + machines = [] for vulnerabilityfile in vulnerabilityfiles: output = json.loads(zipdata[vulnerabilityfile].decode('ascii'))['value'] for data in output: @@ -82,7 +82,7 @@ def process_json(self, vulnerability): if vulnerability['cveId'] is not None: finding.cve = vulnerability['cveId'] self.findings.append(finding) - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] def process_zip(self, vulnerability, machine): description = "" @@ -132,7 +132,7 @@ def process_zip(self, vulnerability, machine): if vulnerability['cveId'] is not None: finding.cve = vulnerability['cveId'] self.findings.append(finding) - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] if machine['computerDnsName'] is not None: finding.unsaved_endpoints.append(Endpoint(host=str(machine['computerDnsName']))) if machine['lastIpAddress'] is not None: diff --git a/dojo/tools/netsparker/parser.py b/dojo/tools/netsparker/parser.py index 37714c2c0f..f574dbb67b 100644 --- a/dojo/tools/netsparker/parser.py +++ b/dojo/tools/netsparker/parser.py @@ -22,7 +22,7 @@ def get_findings(self, filename, test): data = json.loads(str(tree, "utf-8-sig")) except Exception: data = json.loads(tree) - dupes = dict() + dupes = {} if "UTC" in data["Generated"]: scan_date = datetime.datetime.strptime( data["Generated"].split(" ")[0], "%d/%m/%Y" diff --git a/dojo/tools/neuvector/parser.py b/dojo/tools/neuvector/parser.py index b4e77abb11..e09429387e 100644 --- a/dojo/tools/neuvector/parser.py +++ b/dojo/tools/neuvector/parser.py @@ -15,7 +15,7 @@ def parse(self, json_output, test): tree = self.parse_json(json_output) items = [] if tree: - items = [data for data in self.get_items(tree, test)] + items = list(self.get_items(tree, test)) return items def parse_json(self, json_output): @@ -139,7 +139,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, filename, test): if filename is None: - return list() + return [] if filename.name.lower().endswith(".json"): return NeuVectorJsonParser().parse(filename, test) diff --git a/dojo/tools/neuvector_compliance/parser.py b/dojo/tools/neuvector_compliance/parser.py index c16ecebe4b..32f02d1be1 100644 --- a/dojo/tools/neuvector_compliance/parser.py +++ b/dojo/tools/neuvector_compliance/parser.py @@ -11,7 +11,7 @@ def parse(json_output, test): tree = parse_json(json_output) items = [] if tree: - items = [data for data in get_items(tree, test)] + items = list(get_items(tree, test)) return items @@ -145,7 +145,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, filename, test): if filename is None: - return list() + return [] if filename.name.lower().endswith(".json"): return parse(filename, test) diff --git a/dojo/tools/nexpose/parser.py b/dojo/tools/nexpose/parser.py index 8a9e5dfdb8..1af6630a96 100644 --- a/dojo/tools/nexpose/parser.py +++ b/dojo/tools/nexpose/parser.py @@ -106,7 +106,7 @@ def parse_tests_type(self, node, vulnsDefinitions): @return vulns A list of vulnerabilities according to vulnsDefinitions """ - vulns = list() + vulns = [] for tests in node.findall("tests"): for test in tests.findall("test"): @@ -143,7 +143,7 @@ def get_vuln_definitions(self, tree): """ @returns vulns A dict of Vulnerability Definitions """ - vulns = dict() + vulns = {} url_index = 0 for vulnsDef in tree.findall("VulnerabilityDefinitions"): for vulnDef in vulnsDef.findall("vulnerability"): @@ -163,10 +163,10 @@ def get_vuln_definitions(self, tree): "desc": "", "name": vulnDef.get("title"), "vector": vulnDef.get("cvssVector"), # this is CVSS v2 - "refs": dict(), + "refs": {}, "resolution": "", "severity": sev, - "tags": list(), + "tags": [], } for item in list(vulnDef): if item.tag == "description": @@ -208,14 +208,14 @@ def get_vuln_definitions(self, tree): return vulns def get_items(self, tree, vulns, test): - hosts = list() + hosts = [] for nodes in tree.findall("nodes"): for node in nodes.findall("node"): - host = dict() + host = {} host["name"] = node.get("address") host["hostnames"] = set() host["os"] = "" - host["services"] = list() + host["services"] = [] host["vulns"] = self.parse_tests_type(node, vulns) host["vulns"].append( @@ -365,6 +365,6 @@ def findings(dupe_key, dupes, test, vuln): # update CVE if "CVE" in vuln.get("refs", {}): find.unsaved_vulnerability_ids = [vuln["refs"]["CVE"]] - find.unsaved_endpoints = list() + find.unsaved_endpoints = [] dupes[dupe_key] = find return find diff --git a/dojo/tools/nikto/json_parser.py b/dojo/tools/nikto/json_parser.py index dc463d8385..4e4509c490 100644 --- a/dojo/tools/nikto/json_parser.py +++ b/dojo/tools/nikto/json_parser.py @@ -7,7 +7,7 @@ def process_json(self, file, test): data = json.load(file) if len(data) == 1 and isinstance(data, list): data = data[0] - dupes = dict() + dupes = {} host = data.get("host") port = data.get("port") if port is not None: diff --git a/dojo/tools/nikto/xml_parser.py b/dojo/tools/nikto/xml_parser.py index 2686c3e8f6..7397029290 100644 --- a/dojo/tools/nikto/xml_parser.py +++ b/dojo/tools/nikto/xml_parser.py @@ -9,7 +9,7 @@ class NiktoXMLParser: def process_xml(self, file, test): - dupes = dict() + dupes = {} tree = ET.parse(file) root = tree.getroot() scan = root.find("scandetails") diff --git a/dojo/tools/nmap/parser.py b/dojo/tools/nmap/parser.py index 6c62a1af88..5aceea62cd 100755 --- a/dojo/tools/nmap/parser.py +++ b/dojo/tools/nmap/parser.py @@ -18,7 +18,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, file, test): tree = parse(file) root = tree.getroot() - dupes = dict() + dupes = {} if "nmaprun" not in root.tag: raise ValueError("This doesn't seem to be a valid Nmap xml file.") @@ -126,7 +126,7 @@ def get_findings(self, file, test): mitigation="N/A", impact="No impact provided", ) - find.unsaved_endpoints = list() + find.unsaved_endpoints = [] dupes[dupe_key] = find if report_date: find.date = report_date @@ -160,7 +160,7 @@ def manage_vulner_script( component_cpe = CPE(component_element.attrib["key"]) for vuln in component_element.findall("table"): # convert elements in dict - vuln_attributes = dict() + vuln_attributes = {} for elem in vuln.findall("elem"): vuln_attributes[elem.attrib["key"].lower()] = elem.text diff --git a/dojo/tools/npm_audit/parser.py b/dojo/tools/npm_audit/parser.py index f1255d5475..b78e6f5e38 100644 --- a/dojo/tools/npm_audit/parser.py +++ b/dojo/tools/npm_audit/parser.py @@ -148,7 +148,7 @@ def get_item(item_node, test): ) if len(item_node["cves"]) > 0: - dojo_finding.unsaved_vulnerability_ids = list() + dojo_finding.unsaved_vulnerability_ids = [] for vulnerability_id in item_node["cves"]: dojo_finding.unsaved_vulnerability_ids.append(vulnerability_id) diff --git a/dojo/tools/nuclei/parser.py b/dojo/tools/nuclei/parser.py index f26f888811..2318b1dc64 100644 --- a/dojo/tools/nuclei/parser.py +++ b/dojo/tools/nuclei/parser.py @@ -94,9 +94,7 @@ def get_findings(self, filename, test): if classification: if "cve-id" in classification and classification["cve-id"]: cve_ids = classification["cve-id"] - finding.unsaved_vulnerability_ids = list( - map(lambda x: x.upper(), cve_ids) - ) + finding.unsaved_vulnerability_ids = [x.upper() for x in cve_ids] if ( "cwe-id" in classification and classification["cwe-id"] diff --git a/dojo/tools/openscap/parser.py b/dojo/tools/openscap/parser.py index 25bb392cdd..884ac1f571 100644 --- a/dojo/tools/openscap/parser.py +++ b/dojo/tools/openscap/parser.py @@ -49,7 +49,7 @@ def get_findings(self, file, test): for ip in test_result.findall(f"./{namespace}target-address"): ips.append(ip.text) - dupes = dict() + dupes = {} # run both rule, and rule-result in parallel so that we can get title # for failed test from rule. for rule_result in test_result.findall( diff --git a/dojo/tools/openvas/csv_parser.py b/dojo/tools/openvas/csv_parser.py index 00c5c09991..d6c4f80b4a 100644 --- a/dojo/tools/openvas/csv_parser.py +++ b/dojo/tools/openvas/csv_parser.py @@ -260,7 +260,7 @@ def create_chain(self): return date_column_strategy def read_column_names(self, row): - column_names = dict() + column_names = {} index = 0 for column in row: column_names[index] = column @@ -268,8 +268,8 @@ def read_column_names(self, row): return column_names def get_findings(self, filename, test): - column_names = dict() - dupes = dict() + column_names = {} + dupes = {} chain = self.create_chain() content = filename.read() if isinstance(content, bytes): @@ -278,7 +278,7 @@ def get_findings(self, filename, test): row_number = 0 for row in reader: finding = Finding(test=test) - finding.unsaved_vulnerability_ids = list() + finding.unsaved_vulnerability_ids = [] finding.unsaved_endpoints = [Endpoint()] if row_number == 0: column_names = self.read_column_names(row) diff --git a/dojo/tools/ort/parser.py b/dojo/tools/ort/parser.py index d59b48be43..306d78374f 100644 --- a/dojo/tools/ort/parser.py +++ b/dojo/tools/ort/parser.py @@ -19,13 +19,13 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, json_output, test): if json_output is None: - return list() + return [] evaluated_model = self.parse_json(json_output) if evaluated_model: return self.get_items(evaluated_model, test) else: - return list() + return [] def parse_json(self, json_output): try: diff --git a/dojo/tools/ossindex_devaudit/parser.py b/dojo/tools/ossindex_devaudit/parser.py index f5ada25b3c..883d25eb1c 100644 --- a/dojo/tools/ossindex_devaudit/parser.py +++ b/dojo/tools/ossindex_devaudit/parser.py @@ -23,9 +23,9 @@ def get_findings(self, json_file, test): tree = self.parse_json(json_file) if tree: - return list([data for data in self.get_items(tree, test)]) + return list(self.get_items(tree, test)) else: - return list() + return [] def parse_json(self, json_file): if json_file is None: @@ -40,7 +40,7 @@ def parse_json(self, json_file): def get_items(self, tree, test): items = {} - results = {key: value for (key, value) in tree.items()} + results = dict(tree.items()) for package in results.get("Packages", []): package_data = package["Package"] if len(package.get("Vulnerabilities", [])) > 0: diff --git a/dojo/tools/osv_scanner/parser.py b/dojo/tools/osv_scanner/parser.py index 0e8608a2fe..7c411e3884 100644 --- a/dojo/tools/osv_scanner/parser.py +++ b/dojo/tools/osv_scanner/parser.py @@ -28,7 +28,7 @@ def get_findings(self, file, test): data = json.load(file) except json.decoder.JSONDecodeError: return [] - findings = list() + findings = [] for result in data["results"]: source_path = result["source"]["path"] source_type = result["source"]["type"] @@ -69,7 +69,7 @@ def get_findings(self, file, test): references=reference, ) if vulnerabilityid != "": - finding.unsaved_vulnerability_ids = list() + finding.unsaved_vulnerability_ids = [] finding.unsaved_vulnerability_ids.append(vulnerabilityid) findings.append(finding) return findings diff --git a/dojo/tools/outpost24/parser.py b/dojo/tools/outpost24/parser.py index 097664e757..6d42ee855e 100644 --- a/dojo/tools/outpost24/parser.py +++ b/dojo/tools/outpost24/parser.py @@ -19,7 +19,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, file, test): tree = ElementTree.parse(file) - items = list() + items = [] for detail in tree.iterfind(".//detaillist/detail"): # finding details title = detail.findtext("name") diff --git a/dojo/tools/php_security_audit_v2/parser.py b/dojo/tools/php_security_audit_v2/parser.py index 36fe5b48a7..91b7e4c6c3 100644 --- a/dojo/tools/php_security_audit_v2/parser.py +++ b/dojo/tools/php_security_audit_v2/parser.py @@ -20,7 +20,7 @@ def get_findings(self, filename, test): data = json.loads(str(tree, "utf-8")) except Exception: data = json.loads(tree) - dupes = dict() + dupes = {} for filepath, report in list(data["files"].items()): errors = report.get("errors") or 0 diff --git a/dojo/tools/pip_audit/parser.py b/dojo/tools/pip_audit/parser.py index 4b3ffba9b1..b3e023d3c6 100644 --- a/dojo/tools/pip_audit/parser.py +++ b/dojo/tools/pip_audit/parser.py @@ -40,7 +40,7 @@ def get_findings(self, scan_file, test): def get_file_findings(data, test): """Return the findings in the vluns array inside the dependencies key.""" - findings = list() + findings = [] for dependency in data["dependencies"]: item_findings = get_item_findings(dependency, test) if item_findings is not None: @@ -50,7 +50,7 @@ def get_file_findings(data, test): def get_legacy_findings(data, test): """Return the findings gathered from the vulns element.""" - findings = list() + findings = [] for item in data: item_findings = get_item_findings(item, test) if item_findings is not None: @@ -60,7 +60,7 @@ def get_legacy_findings(data, test): def get_item_findings(item, test): """Return list of Findings.""" - findings = list() + findings = [] vulnerabilities = item.get("vulns", []) if vulnerabilities: component_name = item["name"] @@ -99,7 +99,7 @@ def get_item_findings(item, test): static_finding=True, dynamic_finding=False, ) - vulnerability_ids = list() + vulnerability_ids = [] if vuln_id: vulnerability_ids.append(vuln_id) if vulnerability_ids: diff --git a/dojo/tools/pmd/parser.py b/dojo/tools/pmd/parser.py index 2eea92daae..f63f366752 100644 --- a/dojo/tools/pmd/parser.py +++ b/dojo/tools/pmd/parser.py @@ -15,7 +15,7 @@ def get_description_for_scan_types(self, scan_type): return "CSV Report" def get_findings(self, filename, test): - dupes = dict() + dupes = {} content = filename.read() if isinstance(content, bytes): diff --git a/dojo/tools/popeye/parser.py b/dojo/tools/popeye/parser.py index 12548d0dca..75603e26cf 100644 --- a/dojo/tools/popeye/parser.py +++ b/dojo/tools/popeye/parser.py @@ -21,7 +21,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, file, test): data = json.load(file) - dupes = dict() + dupes = {} for sanitizer in data["popeye"]["sanitizers"]: issues = sanitizer.get("issues") if issues: diff --git a/dojo/tools/qualys/parser.py b/dojo/tools/qualys/parser.py index 68bc6ecfb7..c8a69763d9 100644 --- a/dojo/tools/qualys/parser.py +++ b/dojo/tools/qualys/parser.py @@ -279,7 +279,7 @@ def parse_finding(host, tree): if _temp.get("CVSS_value") is not None: finding.cvssv3_score = _temp.get("CVSS_value") finding.verified = True - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] finding.unsaved_endpoints.append(ep) ret_rows.append(finding) return ret_rows diff --git a/dojo/tools/qualys_infrascan_webgui/parser.py b/dojo/tools/qualys_infrascan_webgui/parser.py index 1cd6f2bf14..1ac6909eea 100644 --- a/dojo/tools/qualys_infrascan_webgui/parser.py +++ b/dojo/tools/qualys_infrascan_webgui/parser.py @@ -104,7 +104,7 @@ def issue_r(raw_row, vuln, scan_date): vuln_id_from_tool=_gid, date=scan_date, ) - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] finding.unsaved_endpoints.append(ep) ret_rows.append(finding) return ret_rows diff --git a/dojo/tools/qualys_webapp/parser.py b/dojo/tools/qualys_webapp/parser.py index 4cd236f739..cac7cb395f 100644 --- a/dojo/tools/qualys_webapp/parser.py +++ b/dojo/tools/qualys_webapp/parser.py @@ -58,8 +58,8 @@ def attach_unique_extras( # finding should always be none, since unique ID's are being used if finding is None: finding = Finding() - finding.unsaved_req_resp = list() - finding.unsaved_endpoints = list() + finding.unsaved_req_resp = [] + finding.unsaved_endpoints = [] if date is not None: finding.date = date finding.vuln_id_from_tool = str(qid) @@ -119,8 +119,8 @@ def attach_unique_extras( def attach_extras(endpoints, requests, responses, finding, date, qid, test): if finding is None: finding = Finding() - finding.unsaved_req_resp = list() - finding.unsaved_endpoints = list() + finding.unsaved_req_resp = [] + finding.unsaved_endpoints = [] finding.test = test if date is not None: finding.date = date diff --git a/dojo/tools/redhatsatellite/parser.py b/dojo/tools/redhatsatellite/parser.py index 7f70e5b1f8..34ff2a8321 100644 --- a/dojo/tools/redhatsatellite/parser.py +++ b/dojo/tools/redhatsatellite/parser.py @@ -26,7 +26,7 @@ def severity_mapping(self, input): return severity def get_findings(self, filename, test): - findings = list() + findings = [] tree = filename.read() try: data = json.loads(str(tree, "utf-8")) @@ -72,7 +72,7 @@ def get_findings(self, filename, test): dynamic_finding=True, ) if errata_id is not None: - find.unsaved_vulnerability_ids = list() + find.unsaved_vulnerability_ids = [] find.unsaved_vulnerability_ids.append(errata_id) if cves is not None: for cve in cves: diff --git a/dojo/tools/risk_recon/parser.py b/dojo/tools/risk_recon/parser.py index 21bbfbbdbe..f75921f6ea 100644 --- a/dojo/tools/risk_recon/parser.py +++ b/dojo/tools/risk_recon/parser.py @@ -37,7 +37,7 @@ def get_findings(self, filename, test): return self._get_findings_internal(findings, test) def _get_findings_internal(self, findings, test): - dupes = dict() + dupes = {} for item in findings: findingdetail = "" title = ( diff --git a/dojo/tools/rubocop/parser.py b/dojo/tools/rubocop/parser.py index db18a4619b..f0454a7652 100644 --- a/dojo/tools/rubocop/parser.py +++ b/dojo/tools/rubocop/parser.py @@ -36,7 +36,7 @@ def requires_file(self, scan_type): def get_findings(self, scan_file, test): """Load a file as JSON file and create findings""" data = json.load(scan_file) - findings = list() + findings = [] for vuln_file in data.get("files", []): path = vuln_file.get("path") for offense in vuln_file.get("offenses", []): diff --git a/dojo/tools/rusty_hog/parser.py b/dojo/tools/rusty_hog/parser.py index 0488270e09..4b870ee796 100644 --- a/dojo/tools/rusty_hog/parser.py +++ b/dojo/tools/rusty_hog/parser.py @@ -33,7 +33,7 @@ def get_items(self, json_output, scanner, test): def get_tests(self, scan_type, handle): tree = self.parse_json(handle) - tests = list() + tests = [] parsername = "Rusty Hog" for node in tree: if ( diff --git a/dojo/tools/sarif/parser.py b/dojo/tools/sarif/parser.py index 67af4d28bf..e6afa42d2d 100644 --- a/dojo/tools/sarif/parser.py +++ b/dojo/tools/sarif/parser.py @@ -31,16 +31,16 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, filehandle, test): """For simple interface of parser contract we just aggregate everything""" tree = json.load(filehandle) - items = list() + items = [] # for each runs we just aggregate everything - for run in tree.get("runs", list()): + for run in tree.get("runs", []): items.extend(self.__get_items_from_run(run)) return items def get_tests(self, scan_type, handle): tree = json.load(handle) - tests = list() - for run in tree.get("runs", list()): + tests = [] + for run in tree.get("runs", []): test = ParserTest( name=run["tool"]["driver"]["name"], type=run["tool"]["driver"]["name"], @@ -51,13 +51,13 @@ def get_tests(self, scan_type, handle): return tests def __get_items_from_run(self, run): - items = list() + items = [] # load rules rules = get_rules(run) artifacts = get_artifacts(run) # get the timestamp of the run if possible run_date = self.__get_last_invocation_date(run) - for result in run.get("results", list()): + for result in run.get("results", []): item = get_item(result, rules, artifacts, run_date) if item is not None: items.append(item) @@ -462,7 +462,7 @@ def get_fingerprints_hashes(values): Method that generate a `unique_id_from_tool` data from the `fingerprints` attribute. - for now, we take the value of the last version of the first hash method. """ - fingerprints = dict() + fingerprints = {} for key in values: if "/" in key: key_method = key.split("/")[-2] diff --git a/dojo/tools/scantist/parser.py b/dojo/tools/scantist/parser.py index 0da36bbe19..b2b3b5f302 100644 --- a/dojo/tools/scantist/parser.py +++ b/dojo/tools/scantist/parser.py @@ -77,7 +77,7 @@ def get_findings(vuln, test): finding.unsaved_vulnerability_ids = [vulnerability_id] return finding - items = dict() + items = {} for node in tree: item = get_findings(node, test) diff --git a/dojo/tools/scout_suite/parser.py b/dojo/tools/scout_suite/parser.py index 9e2d305c66..03293e586b 100644 --- a/dojo/tools/scout_suite/parser.py +++ b/dojo/tools/scout_suite/parser.py @@ -69,7 +69,7 @@ def get_tests(self, scan_type, handle): ] ) - tests = list() + tests = [] test = ParserTest( name=self.ID, type=data["provider_name"], diff --git a/dojo/tools/semgrep/parser.py b/dojo/tools/semgrep/parser.py index 1ffd44ce33..762b471638 100644 --- a/dojo/tools/semgrep/parser.py +++ b/dojo/tools/semgrep/parser.py @@ -16,7 +16,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, filename, test): data = json.load(filename) - dupes = dict() + dupes = {} if "results" in data: for item in data.get("results", []): diff --git a/dojo/tools/skf/parser.py b/dojo/tools/skf/parser.py index b71673c6af..74ec86bba4 100644 --- a/dojo/tools/skf/parser.py +++ b/dojo/tools/skf/parser.py @@ -96,14 +96,14 @@ def get_findings(self, filename, test): if isinstance(content, bytes): content = content.decode("utf-8") - column_names = dict() + column_names = {} chain = self.create_chain() row_number = 0 reader = csv.reader( io.StringIO(content), delimiter=",", quotechar='"', escapechar="\\" ) - dupes = dict() + dupes = {} for row in reader: finding = Finding(test=test) finding.severity = "Info" diff --git a/dojo/tools/solar_appscreener/parser.py b/dojo/tools/solar_appscreener/parser.py index 3130201b08..2c161631ce 100644 --- a/dojo/tools/solar_appscreener/parser.py +++ b/dojo/tools/solar_appscreener/parser.py @@ -32,7 +32,7 @@ def get_findings(self, filename, test): for row in reader: csvarray.append(row) - items = list() + items = [] for row in csvarray: finding = Finding(test=test) finding.title = row.get("Vulnerability", "") diff --git a/dojo/tools/sonarqube/sonarqube_restapi_json.py b/dojo/tools/sonarqube/sonarqube_restapi_json.py index 8e8fb8c108..53771467d6 100644 --- a/dojo/tools/sonarqube/sonarqube_restapi_json.py +++ b/dojo/tools/sonarqube/sonarqube_restapi_json.py @@ -107,7 +107,7 @@ def get_json_items(self, json_content, test, mode): cvssv3_score=cvss, tags=["vulnerability"], ) - vulnids = list() + vulnids = [] if "Reference: CVE" in message: cve_pattern = r'Reference: CVE-\d{4}-\d{4,7}' cves = re.findall(cve_pattern, message) @@ -128,7 +128,7 @@ def get_json_items(self, json_content, test, mode): cves = re.findall(cve_pattern, message) for cve in cves: vulnids.append(cve.split("References: ")[1]) - item.unsaved_vulnerability_ids = list() + item.unsaved_vulnerability_ids = [] for vulnid in vulnids: item.unsaved_vulnerability_ids.append(vulnid) elif issue.get("type") == "CODE_SMELL": diff --git a/dojo/tools/sonarqube/sonarqube_restapi_zip.py b/dojo/tools/sonarqube/sonarqube_restapi_zip.py index 651ef9f2d5..42169e793b 100644 --- a/dojo/tools/sonarqube/sonarqube_restapi_zip.py +++ b/dojo/tools/sonarqube/sonarqube_restapi_zip.py @@ -4,7 +4,7 @@ class SonarQubeRESTAPIZIP: def get_items(self, files, test, mode): - total_findings_per_file = list() + total_findings_per_file = [] for dictkey in files.keys(): if dictkey.endswith(".json"): json_content = json.loads(files[dictkey].decode('ascii')) diff --git a/dojo/tools/sonarqube/soprasteria_html.py b/dojo/tools/sonarqube/soprasteria_html.py index a3e87d0f35..8ee2054427 100644 --- a/dojo/tools/sonarqube/soprasteria_html.py +++ b/dojo/tools/sonarqube/soprasteria_html.py @@ -10,7 +10,7 @@ def get_items(self, tree, test, mode): detailTbody = tree.xpath( "/html/body/div[contains(@class,'detail')]/table/tbody" ) - dupes = dict() + dupes = {} if len(detailTbody) == 2: # First is "Detail of the Detected Vulnerabilities" (not present if no vuln) # Second is "Known Security Rules" @@ -18,7 +18,7 @@ def get_items(self, tree, test, mode): rules_table = list(detailTbody[1].xpath("tr")) # iterate over the rules once to get the information we need - rulesDic = dict() + rulesDic = {} for rule in rules_table: rule_properties = list(rule.iter("td")) rule_name = list(rule_properties[0].iter("a"))[0].text.strip() diff --git a/dojo/tools/sonarqube/soprasteria_json.py b/dojo/tools/sonarqube/soprasteria_json.py index f2e5ae107f..bfd52a69de 100644 --- a/dojo/tools/sonarqube/soprasteria_json.py +++ b/dojo/tools/sonarqube/soprasteria_json.py @@ -6,7 +6,7 @@ class SonarQubeSoprasteriaJSON: def get_json_items(self, json_content, test, mode): - dupes = dict() + dupes = {} rules = json_content["rules"] issues = json_content["issues"] for issue in issues: diff --git a/dojo/tools/spotbugs/parser.py b/dojo/tools/spotbugs/parser.py index 979ee20ef0..47aeedb98c 100644 --- a/dojo/tools/spotbugs/parser.py +++ b/dojo/tools/spotbugs/parser.py @@ -17,9 +17,9 @@ def get_description_for_scan_types(self, scan_type): return "XML report of textui cli." def get_findings(self, filename, test): - mitigation_patterns = dict() - reference_patterns = dict() - dupes = dict() + mitigation_patterns = {} + reference_patterns = {} + dupes = {} SEVERITY = {"1": "High", "2": "Medium", "3": "Low"} diff --git a/dojo/tools/ssh_audit/parser.py b/dojo/tools/ssh_audit/parser.py index eb681ba078..efd21be1b8 100644 --- a/dojo/tools/ssh_audit/parser.py +++ b/dojo/tools/ssh_audit/parser.py @@ -51,7 +51,7 @@ def get_findings(self, filename, test): severity=severity, static_finding=False) items.append(finding) - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] endpoint = Endpoint(host=data['target'].split(':')[0], port=data['target'].split(':')[1]) finding.unsaved_endpoints.append(endpoint) for kex in data['kex']: @@ -69,7 +69,7 @@ def get_findings(self, filename, test): severity=severity, static_finding=False) items.append(finding) - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] endpoint = Endpoint(host=data['target'].split(':')[0], port=data['target'].split(':')[1]) finding.unsaved_endpoints.append(endpoint) elif 'fail' in kex['notes']: @@ -85,7 +85,7 @@ def get_findings(self, filename, test): severity=severity, static_finding=False) items.append(finding) - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] endpoint = Endpoint(host=data['target'].split(':')[0], port=data['target'].split(':')[1]) finding.unsaved_endpoints.append(endpoint) elif 'warn' in kex['notes']: @@ -101,7 +101,7 @@ def get_findings(self, filename, test): severity=severity, static_finding=False) items.append(finding) - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] endpoint = Endpoint(host=data['target'].split(':')[0], port=data['target'].split(':')[1]) finding.unsaved_endpoints.append(endpoint) for key in data['key']: @@ -121,7 +121,7 @@ def get_findings(self, filename, test): severity=severity, static_finding=False) items.append(finding) - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] endpoint = Endpoint(host=data['target'].split(':')[0], port=data['target'].split(':')[1]) finding.unsaved_endpoints.append(endpoint) elif 'fail' in key['notes']: @@ -139,7 +139,7 @@ def get_findings(self, filename, test): severity=severity, static_finding=False) items.append(finding) - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] endpoint = Endpoint(host=data['target'].split(':')[0], port=data['target'].split(':')[1]) finding.unsaved_endpoints.append(endpoint) elif 'warn' in key['notes']: @@ -157,7 +157,7 @@ def get_findings(self, filename, test): severity=severity, static_finding=False) items.append(finding) - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] endpoint = Endpoint(host=data['target'].split(':')[0], port=data['target'].split(':')[1]) finding.unsaved_endpoints.append(endpoint) for mac in data['mac']: @@ -175,7 +175,7 @@ def get_findings(self, filename, test): severity=severity, static_finding=False) items.append(finding) - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] endpoint = Endpoint(host=data['target'].split(':')[0], port=data['target'].split(':')[1]) finding.unsaved_endpoints.append(endpoint) elif 'fail' in mac['notes']: @@ -191,7 +191,7 @@ def get_findings(self, filename, test): severity=severity, static_finding=False) items.append(finding) - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] endpoint = Endpoint(host=data['target'].split(':')[0], port=data['target'].split(':')[1]) finding.unsaved_endpoints.append(endpoint) elif 'warn' in mac['notes']: @@ -207,7 +207,7 @@ def get_findings(self, filename, test): severity=severity, static_finding=False) items.append(finding) - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] endpoint = Endpoint(host=data['target'].split(':')[0], port=data['target'].split(':')[1]) finding.unsaved_endpoints.append(endpoint) return items diff --git a/dojo/tools/ssl_labs/parser.py b/dojo/tools/ssl_labs/parser.py index 6ac5d11c9c..9a8e2336dd 100644 --- a/dojo/tools/ssl_labs/parser.py +++ b/dojo/tools/ssl_labs/parser.py @@ -333,7 +333,7 @@ def get_findings(self, filename, test): dynamic_finding=True, ) dupes[dupe_key] = find - find.unsaved_endpoints = list() + find.unsaved_endpoints = [] find.unsaved_endpoints.append( Endpoint(host=hostName, port=port, protocol=protocol) diff --git a/dojo/tools/sslscan/parser.py b/dojo/tools/sslscan/parser.py index 540b9cdab7..ed6ab585a9 100644 --- a/dojo/tools/sslscan/parser.py +++ b/dojo/tools/sslscan/parser.py @@ -26,7 +26,7 @@ def get_findings(self, file, test): raise NamespaceErr( "This doesn't seem to be a valid sslscan xml file." ) - dupes = dict() + dupes = {} for ssltest in root: for target in ssltest: title = "" @@ -85,7 +85,7 @@ def get_findings(self, file, test): severity=severity, dynamic_finding=True, ) - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] dupes[dupe_key] = finding if host: diff --git a/dojo/tools/sslyze/parser.py b/dojo/tools/sslyze/parser.py index d8b4fa0d6d..ba742d43a2 100644 --- a/dojo/tools/sslyze/parser.py +++ b/dojo/tools/sslyze/parser.py @@ -18,7 +18,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, filename, test): if filename is None: - return list() + return [] if filename.name.lower().endswith(".xml"): return SSLyzeXMLParser().get_findings(filename, test) diff --git a/dojo/tools/sslyze/parser_json.py b/dojo/tools/sslyze/parser_json.py index 505b42bd24..3409576b6f 100644 --- a/dojo/tools/sslyze/parser_json.py +++ b/dojo/tools/sslyze/parser_json.py @@ -587,7 +587,7 @@ def get_finding( if vulnerability_id: finding.unsaved_vulnerability_ids = [vulnerability_id] if endpoint is not None: - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] finding.unsaved_endpoints.append(endpoint) return finding diff --git a/dojo/tools/sslyze/parser_xml.py b/dojo/tools/sslyze/parser_xml.py index bb99bb7d3e..7c59bce50b 100644 --- a/dojo/tools/sslyze/parser_xml.py +++ b/dojo/tools/sslyze/parser_xml.py @@ -60,7 +60,7 @@ def get_findings(self, file, test): ) results = root.find("results") - dupes = dict() + dupes = {} for target in results: host = target.attrib["host"] port = target.attrib["port"] @@ -153,7 +153,7 @@ def get_findings(self, file, test): severity=severity, dynamic_finding=True, ) - finding.unsaved_endpoints = list() + finding.unsaved_endpoints = [] dupes[dupe_key] = finding if host is not None: diff --git a/dojo/tools/sysdig_reports/parser.py b/dojo/tools/sysdig_reports/parser.py index 7c0820c2c6..633780c48b 100644 --- a/dojo/tools/sysdig_reports/parser.py +++ b/dojo/tools/sysdig_reports/parser.py @@ -39,8 +39,8 @@ def get_findings(self, filename, test): def parse_json(self, data, test): vulnerability = data.get("data", None) if not vulnerability: - return list() - findings = list() + return [] + findings = [] for item in vulnerability: imageId = item.get('imageId', '') imagePullString = item.get('imagePullString', '') @@ -103,7 +103,7 @@ def parse_json(self, data, test): component_version=packageVersion, ) if vulnName != '': - find.unsaved_vulnerability_ids = list() + find.unsaved_vulnerability_ids = [] find.unsaved_vulnerability_ids.append(vulnName) findings.append(find) return findings @@ -120,7 +120,7 @@ def parse_csv(self, arr_data, test): else: finding.title = f"{row.vulnerability_id} - {row.package_name}" finding.vuln_id_from_tool = row.vulnerability_id - finding.unsaved_vulnerability_ids = list() + finding.unsaved_vulnerability_ids = [] finding.unsaved_vulnerability_ids.append(row.vulnerability_id) finding.severity = row.severity # Set Component Version diff --git a/dojo/tools/talisman/parser.py b/dojo/tools/talisman/parser.py index d42b4e6a8d..20d2874c40 100644 --- a/dojo/tools/talisman/parser.py +++ b/dojo/tools/talisman/parser.py @@ -32,7 +32,7 @@ def get_findings(self, filename, test): Converts a Talisman JSON report to DefectDojo findings """ if filename is None: - return list() + return [] json_data = json.load(filename) results = json_data.get("results") diff --git a/dojo/tools/terrascan/parser.py b/dojo/tools/terrascan/parser.py index 87958813c3..2810ffcaaa 100644 --- a/dojo/tools/terrascan/parser.py +++ b/dojo/tools/terrascan/parser.py @@ -30,7 +30,7 @@ def get_findings(self, filename, test): if "results" not in data and "violations" not in data.get("results"): raise ValueError("missing mandatory attribute 'results'") if data.get("results").get("violations") is None: - return list() + return [] for item in data.get("results").get("violations"): rule_name = item.get("rule_name") description = item.get("description") diff --git a/dojo/tools/testssl/parser.py b/dojo/tools/testssl/parser.py index 4e28abf944..01369ea439 100644 --- a/dojo/tools/testssl/parser.py +++ b/dojo/tools/testssl/parser.py @@ -23,7 +23,7 @@ def get_findings(self, filename, test): io.StringIO(content), delimiter=",", quotechar='"' ) - dupes = dict() + dupes = {} for row in reader: # filter 'OK' # possible values: LOW|MEDIUM|HIGH|CRITICAL + WARN|OK|INFO diff --git a/dojo/tools/tfsec/parser.py b/dojo/tools/tfsec/parser.py index c4fdc02919..7fc671121a 100644 --- a/dojo/tools/tfsec/parser.py +++ b/dojo/tools/tfsec/parser.py @@ -36,7 +36,7 @@ def get_findings(self, filename, test): "Incorrect TFSec scan, missing attribute 'results'" ) if data.get("results") is None: - return list() + return [] for item in data.get("results"): if item.get("passed", None): continue diff --git a/dojo/tools/threagile/parser.py b/dojo/tools/threagile/parser.py index aa1d968055..61a2487420 100644 --- a/dojo/tools/threagile/parser.py +++ b/dojo/tools/threagile/parser.py @@ -75,7 +75,7 @@ def get_items(self, tree, test): if not isinstance(tree, list): raise TypeError("Invalid ThreAgile risks file") if not tree: - return list() + return [] findings = [] for item in tree: for field in self.REQUIRED_FIELDS: diff --git a/dojo/tools/trivy/parser.py b/dojo/tools/trivy/parser.py index 262ee0736a..66c720938a 100644 --- a/dojo/tools/trivy/parser.py +++ b/dojo/tools/trivy/parser.py @@ -80,7 +80,7 @@ def get_findings(self, scan_file, test): # Legacy format is empty if data is None: - return list() + return [] # Legacy format with results elif isinstance(data, list): return self.get_result_items(test, data) @@ -92,7 +92,7 @@ def get_findings(self, scan_file, test): results = data.get("Results", []) return self.get_result_items(test, results, artifact_name=artifact_name) elif cluster_name: - findings = list() + findings = [] vulnerabilities = data.get("Vulnerabilities", []) for service in vulnerabilities: namespace = service.get("Namespace") @@ -150,7 +150,7 @@ def get_findings(self, scan_file, test): ) def get_result_items(self, test, results, service_name=None, artifact_name=""): - items = list() + items = [] for target_data in results: if ( not isinstance(target_data, dict) diff --git a/dojo/tools/trivy_operator/checks_handler.py b/dojo/tools/trivy_operator/checks_handler.py index b4507c7255..e6a1ccd8bb 100644 --- a/dojo/tools/trivy_operator/checks_handler.py +++ b/dojo/tools/trivy_operator/checks_handler.py @@ -11,7 +11,7 @@ class TrivyChecksHandler: def handle_checks(self, service, checks, test): - findings = list() + findings = [] for check in checks: check_title = check.get("title") check_severity = TRIVY_SEVERITIES[check.get("severity")] diff --git a/dojo/tools/trivy_operator/compliance_handler.py b/dojo/tools/trivy_operator/compliance_handler.py index 45815282d2..9e27c56ddf 100644 --- a/dojo/tools/trivy_operator/compliance_handler.py +++ b/dojo/tools/trivy_operator/compliance_handler.py @@ -11,7 +11,7 @@ class TrivyComplianceHandler: def handle_compliance(self, benchmarkreport, test): - findings = list() + findings = [] for result in benchmarkreport.get("results"): for check in result.get("checks"): description = "**detailReport description:** " + benchmarkreport.get("description") + "\n" diff --git a/dojo/tools/trivy_operator/parser.py b/dojo/tools/trivy_operator/parser.py index 70666fcc47..e11d5cbb2d 100644 --- a/dojo/tools/trivy_operator/parser.py +++ b/dojo/tools/trivy_operator/parser.py @@ -28,18 +28,18 @@ def get_findings(self, scan_file, test): data = json.loads(scan_data) if data is None: - return list() + return [] metadata = data.get("metadata", None) if metadata is None: - return list() + return [] labels = metadata.get("labels", None) if labels is None: - return list() + return [] report = data.get("report", None) benchmark = data.get("status", None) if benchmark is not None: benchmarkreport = benchmark.get("detailReport", None) - findings = list() + findings = [] if report is not None: resource_namespace = labels.get( "trivy-operator.resource.namespace", "" diff --git a/dojo/tools/trivy_operator/secrets_handler.py b/dojo/tools/trivy_operator/secrets_handler.py index c8c623f856..c5e767a1bc 100644 --- a/dojo/tools/trivy_operator/secrets_handler.py +++ b/dojo/tools/trivy_operator/secrets_handler.py @@ -16,7 +16,7 @@ class TrivySecretsHandler: def handle_secrets(self, service, secrets, test): - findings = list() + findings = [] for secret in secrets: secret_title = secret.get("title") secret_category = secret.get("category") diff --git a/dojo/tools/trivy_operator/vulnerability_handler.py b/dojo/tools/trivy_operator/vulnerability_handler.py index c166e65298..bdd282648e 100644 --- a/dojo/tools/trivy_operator/vulnerability_handler.py +++ b/dojo/tools/trivy_operator/vulnerability_handler.py @@ -15,7 +15,7 @@ class TrivyVulnerabilityHandler: def handle_vulns(self, service, vulnerabilities, test): - findings = list() + findings = [] for vulnerability in vulnerabilities: vuln_id = vulnerability.get("vulnerabilityID", "0") severity = TRIVY_SEVERITIES[vulnerability.get("severity")] @@ -25,7 +25,7 @@ def handle_vulns(self, service, vulnerabilities, test): package_version = vulnerability.get("installedVersion") cvssv3_score = vulnerability.get("score") - finding_tags = list() + finding_tags = [] target_target = None target_class = None package_path = None diff --git a/dojo/tools/trufflehog3/parser.py b/dojo/tools/trufflehog3/parser.py index 95dc198df3..9b22661840 100644 --- a/dojo/tools/trufflehog3/parser.py +++ b/dojo/tools/trufflehog3/parser.py @@ -17,7 +17,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, filename, test): data = json.load(filename) - dupes = dict() + dupes = {} for json_data in data: if json_data.get("reason"): diff --git a/dojo/tools/twistlock/parser.py b/dojo/tools/twistlock/parser.py index d760ed343b..7009c61c62 100644 --- a/dojo/tools/twistlock/parser.py +++ b/dojo/tools/twistlock/parser.py @@ -69,7 +69,7 @@ def parse(self, filename, test): if filename is None: return content = filename.read() - dupes = dict() + dupes = {} if isinstance(content, bytes): content = content.decode("utf-8") reader = csv.DictReader( @@ -97,7 +97,7 @@ def parse(self, json_output, test): tree = self.parse_json(json_output) items = [] if tree: - items = [data for data in self.get_items(tree, test)] + items = list(self.get_items(tree, test)) return items def parse_json(self, json_output): @@ -213,7 +213,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, filename, test): if filename is None: - return list() + return [] if filename.name.lower().endswith(".json"): return TwistlockJsonParser().parse(filename, test) diff --git a/dojo/tools/vcg/parser.py b/dojo/tools/vcg/parser.py index 05515d6dbd..86b1f75cc0 100644 --- a/dojo/tools/vcg/parser.py +++ b/dojo/tools/vcg/parser.py @@ -47,7 +47,7 @@ def __init__(self): self.filename = "" self.line = "" self.code_line = "" - self.priority_mapping = dict() + self.priority_mapping = {} self.priority_mapping[1] = "Critical" self.priority_mapping[2] = "High" self.priority_mapping[3] = "Medium" @@ -101,7 +101,7 @@ def parse_issue(self, issue, test): return finding def parse(self, content, test): - dupes = dict() + dupes = {} if content is None: return dupes @@ -172,7 +172,7 @@ def parse_issue(self, row, test): return finding def parse(self, content, test): - dupes = dict() + dupes = {} if isinstance(content, bytes): content = content.decode("utf-8") reader = csv.reader(io.StringIO(content), delimiter=",", quotechar='"') @@ -213,7 +213,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, filename, test): if filename is None: - return list() + return [] content = filename.read() # 'utf-8' This line was added to pass a unittest in test_parsers.TestParsers.test_file_existence. diff --git a/dojo/tools/veracode/xml_parser.py b/dojo/tools/veracode/xml_parser.py index 3751bfcb00..e7d64f8df1 100644 --- a/dojo/tools/veracode/xml_parser.py +++ b/dojo/tools/veracode/xml_parser.py @@ -33,7 +33,7 @@ def get_findings(self, filename, test): root.attrib["last_update_time"], "%Y-%m-%d %H:%M:%S %Z" ) - dupes = dict() + dupes = {} # Get SAST findings # This assumes `` only exists within the `` @@ -51,15 +51,10 @@ def get_findings(self, filename, test): ) # Bullet list of recommendations: mitigation_text += "".join( - list( - map( - lambda x: " * " + x.get("text") + "\n", - category_node.findall( + [" * " + x.get("text") + "\n" for x in category_node.findall( "x:recommendations/x:para/x:bulletitem", namespaces=XML_NAMESPACE, - ), - ) - ) + )] ) for flaw_node in category_node.findall( diff --git a/dojo/tools/wapiti/parser.py b/dojo/tools/wapiti/parser.py index 3703e2226d..64937b9889 100644 --- a/dojo/tools/wapiti/parser.py +++ b/dojo/tools/wapiti/parser.py @@ -45,7 +45,7 @@ def get_findings(self, file, test): url = root.findtext('report_infos/info[@name="target"]') - dupes = dict() + dupes = {} for vulnerability in root.findall("vulnerabilities/vulnerability"): category = vulnerability.attrib["name"] description = vulnerability.findtext("description") diff --git a/dojo/tools/wazuh/parser.py b/dojo/tools/wazuh/parser.py index f4899d9cca..e7ec473eb6 100644 --- a/dojo/tools/wazuh/parser.py +++ b/dojo/tools/wazuh/parser.py @@ -25,7 +25,7 @@ def get_findings(self, file, test): return [] # Detect duplications - dupes = dict() + dupes = {} # Loop through each element in the list vulnerabilities = data.get("data", {}).get("affected_items", []) diff --git a/dojo/tools/whitehat_sentinel/parser.py b/dojo/tools/whitehat_sentinel/parser.py index c83b6f8778..ca4cb8acb8 100644 --- a/dojo/tools/whitehat_sentinel/parser.py +++ b/dojo/tools/whitehat_sentinel/parser.py @@ -28,7 +28,7 @@ def get_findings(self, file, test): findings_collection = json.load(file) if not findings_collection.keys(): - return list() + return [] # Make sure the findings key exists in the dictionary and that it is # not null or an empty list @@ -198,7 +198,7 @@ def _convert_whitehat_sentinel_vulns_to_dojo_finding( test: The test ID that the DefectDojo finding should be associated with Returns: A DefectDojo Finding object """ - dupes = dict() + dupes = {} for whitehat_vuln in whitehat_sentinel_vulns: date_created = whitehat_vuln["found"].split("T")[0] diff --git a/dojo/tools/wpscan/parser.py b/dojo/tools/wpscan/parser.py index 6fc25a4385..30f523265c 100644 --- a/dojo/tools/wpscan/parser.py +++ b/dojo/tools/wpscan/parser.py @@ -65,7 +65,7 @@ def get_vulnerabilities( finding.mitigation = "fixed in : " + vul["fixed_in"] # manage CVE if "cve" in vul["references"]: - finding.unsaved_vulnerability_ids = list() + finding.unsaved_vulnerability_ids = [] for vulnerability_id in vul["references"]["cve"]: finding.unsaved_vulnerability_ids.append( f"CVE-{vulnerability_id}" @@ -90,7 +90,7 @@ def get_findings(self, file, test): if "start_time" in tree: report_date = datetime.utcfromtimestamp(tree.get("start_time")) - dupes = dict() + dupes = {} # manage plugin findings for plugin in tree.get("plugins", []): node = tree["plugins"][plugin] diff --git a/dojo/tools/xanitizer/parser.py b/dojo/tools/xanitizer/parser.py index 80b3096b4e..211448e944 100644 --- a/dojo/tools/xanitizer/parser.py +++ b/dojo/tools/xanitizer/parser.py @@ -19,13 +19,13 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, filename, test): if filename is None: - return list() + return [] root = self.parse_xml(filename) if root is not None: return self.get_findings_internal(root, test) else: - return list() + return [] def parse_xml(self, filename): try: @@ -42,7 +42,7 @@ def parse_xml(self, filename): return root def get_findings_internal(self, root, test): - items = list() + items = [] globalDate = root.get("timeStamp", default=None) if globalDate is not None: diff --git a/dojo/tools/yarn_audit/parser.py b/dojo/tools/yarn_audit/parser.py index b1670a0a7b..6eaaecb7e4 100644 --- a/dojo/tools/yarn_audit/parser.py +++ b/dojo/tools/yarn_audit/parser.py @@ -16,7 +16,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, json_output, test): if json_output is None: - return list() + return [] tree = None lines = json_output.read() if isinstance(lines, bytes): @@ -98,7 +98,7 @@ def get_items_auditci(self, tree, test): # https://github.com/DefectDojo/django dynamic_finding=False, ) if tree.get("advisories").get(element).get("cves") != []: - dojo_finding.unsaved_vulnerability_ids = list() + dojo_finding.unsaved_vulnerability_ids = [] for cve in tree.get("advisories").get(element).get("cves"): dojo_finding.unsaved_vulnerability_ids.append(cve) if tree.get("advisories").get(element).get("cwe") != []: @@ -172,7 +172,7 @@ def get_item_yarn(self, item_node, test): dynamic_finding=False, ) if len(item_node["cves"]) > 0: - dojo_finding.unsaved_vulnerability_ids = list() + dojo_finding.unsaved_vulnerability_ids = [] for vulnerability_id in item_node["cves"]: dojo_finding.unsaved_vulnerability_ids.append(vulnerability_id) return dojo_finding diff --git a/dojo/tools/zap/parser.py b/dojo/tools/zap/parser.py index b835c1543e..f8e983f152 100755 --- a/dojo/tools/zap/parser.py +++ b/dojo/tools/zap/parser.py @@ -27,7 +27,7 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, file, test): tree = ET.parse(file) - items = list() + items = [] for node in tree.findall("site"): for item in node.findall("alerts/alertitem"): finding = Finding( diff --git a/dojo/utils.py b/dojo/utils.py index 226cb166bd..73d98fcecc 100644 --- a/dojo/utils.py +++ b/dojo/utils.py @@ -786,8 +786,8 @@ def get_punchcard_data(objs, start_date, weeks, view='Finding'): # map from python to javascript, do not use week numbers or day numbers from database. day_offset = {0: 5, 1: 4, 2: 3, 3: 2, 4: 1, 5: 0, 6: 6} - punchcard = list() - ticks = list() + punchcard = [] + ticks = [] highest_day_count = 0 tick = 0 day_counts = [0, 0, 0, 0, 0, 0, 0] @@ -870,8 +870,8 @@ def get_period_counts_legacy(findings, period_interval, start_date, relative_delta='months'): - opened_in_period = list() - accepted_in_period = list() + opened_in_period = [] + accepted_in_period = [] opened_in_period.append( ['Timestamp', 'Date', 'S0', 'S1', 'S2', 'S3', 'Total', 'Closed']) accepted_in_period.append( @@ -965,9 +965,9 @@ def get_period_counts(findings, start_date = datetime(start_date.year, start_date.month, start_date.day, tzinfo=tz) - opened_in_period = list() - active_in_period = list() - accepted_in_period = list() + opened_in_period = [] + active_in_period = [] + accepted_in_period = [] opened_in_period.append( ['Timestamp', 'Date', 'S0', 'S1', 'S2', 'S3', 'Total', 'Closed']) active_in_period.append( @@ -1358,7 +1358,7 @@ def reopen_external_issue(find, note, external_issue_provider, **kwargs): def process_notifications(request, note, parent_url, parent_title): regex = re.compile(r'(?:\A|\s)@(\w+)\b') - usernames_to_check = set([un.lower() for un in regex.findall(note.entry)]) + usernames_to_check = set(un.lower() for un in regex.findall(note.entry)) # noqa: C401 users_to_notify = [ User.objects.filter(username=username).get() diff --git a/ruff.toml b/ruff.toml index 031f505f50..30152d6cb9 100644 --- a/ruff.toml +++ b/ruff.toml @@ -39,6 +39,7 @@ select = [ "YTT", "ASYNC", "TRIO", + "C4", "ICN", "LOG", "SLOT", diff --git a/unittests/test_apiv2_metadata.py b/unittests/test_apiv2_metadata.py index 6da260ec32..ae24b07adc 100644 --- a/unittests/test_apiv2_metadata.py +++ b/unittests/test_apiv2_metadata.py @@ -35,7 +35,7 @@ def test_query_metadata(self): def test_query_product_endpoint(self): r = self.client.get(reverse('product-detail', args=(1,))) - self.assertIn(dict(name='foo', value='bar'), r.json()['product_meta']) + self.assertIn({'name': 'foo', 'value': 'bar'}, r.json()['product_meta']) def test_delete(self): r = self.client.delete(reverse('metadata-detail', args=(self.mid,))) @@ -45,7 +45,7 @@ def test_delete(self): self.assertEqual(r.status_code, 404) r = self.client.get(reverse('product-detail', args=(1,))) - self.assertNotIn(dict(name='foo', value='bar'), r.json()['product_meta']) + self.assertNotIn({'name': 'foo', 'value': 'bar'}, r.json()['product_meta']) def test_no_product_or_endpoint_as_parameter(self): r = self.create(name='foo', value='bar') diff --git a/unittests/test_apply_finding_template.py b/unittests/test_apply_finding_template.py index aab724f54a..763200b55b 100644 --- a/unittests/test_apply_finding_template.py +++ b/unittests/test_apply_finding_template.py @@ -91,7 +91,7 @@ def create_get_request(user, path): rf = RequestFactory() get_request = rf.get(path) get_request.user = user - get_request.session = dict() + get_request.session = {} return get_request @@ -100,7 +100,7 @@ def create_post_request(user, path, data): rf = RequestFactory() post_request = rf.post(path, data=data) post_request.user = user - post_request.session = dict() + post_request.session = {} messages = FallbackStorage(post_request) setattr(post_request, '_messages', messages) diff --git a/unittests/test_bulk_risk_acceptance_api.py b/unittests/test_bulk_risk_acceptance_api.py index 9fdf1f90ee..96309fcb4b 100644 --- a/unittests/test_bulk_risk_acceptance_api.py +++ b/unittests/test_bulk_risk_acceptance_api.py @@ -44,24 +44,24 @@ def create_finding(test: Test, reporter: User, cve: str) -> Finding: reporter=reporter, numerical_severity='S1', static_finding=True, dynamic_finding=False) Finding.objects.bulk_create( - map(lambda i: create_finding(cls.test_a, cls.user, f'CVE-1999-{i}'), range(50, 150, 3))) + create_finding(cls.test_a, cls.user, f'CVE-1999-{i}') for i in range(50, 150, 3)) for finding in Finding.objects.filter(test=cls.test_a): Vulnerability_Id.objects.get_or_create(finding=finding, vulnerability_id=finding.cve) Finding.objects.bulk_create( - map(lambda i: create_finding(cls.test_b, cls.user, f'CVE-1999-{i}'), range(51, 150, 3))) + create_finding(cls.test_b, cls.user, f'CVE-1999-{i}') for i in range(51, 150, 3)) for finding in Finding.objects.filter(test=cls.test_b): Vulnerability_Id.objects.get_or_create(finding=finding, vulnerability_id=finding.cve) Finding.objects.bulk_create( - map(lambda i: create_finding(cls.test_c, cls.user, f'CVE-1999-{i}'), range(52, 150, 3))) + create_finding(cls.test_c, cls.user, f'CVE-1999-{i}') for i in range(52, 150, 3)) for finding in Finding.objects.filter(test=cls.test_c): Vulnerability_Id.objects.get_or_create(finding=finding, vulnerability_id=finding.cve) Finding.objects.bulk_create( - map(lambda i: create_finding(cls.test_d, cls.user, f'CVE-2000-{i}'), range(50, 150, 3))) + create_finding(cls.test_d, cls.user, f'CVE-2000-{i}') for i in range(50, 150, 3)) for finding in Finding.objects.filter(test=cls.test_d): Vulnerability_Id.objects.get_or_create(finding=finding, vulnerability_id=finding.cve) Finding.objects.bulk_create( - map(lambda i: create_finding(cls.test_e, cls.user, f'CVE-1999-{i}'), range(50, 150, 3))) + create_finding(cls.test_e, cls.user, f'CVE-1999-{i}') for i in range(50, 150, 3)) for finding in Finding.objects.filter(test=cls.test_e): Vulnerability_Id.objects.get_or_create(finding=finding, vulnerability_id=finding.cve) diff --git a/unittests/test_rest_framework.py b/unittests/test_rest_framework.py index dba925e70b..757e8b35e6 100644 --- a/unittests/test_rest_framework.py +++ b/unittests/test_rest_framework.py @@ -301,10 +301,10 @@ def check_schema(self, schema, obj): def get_endpoint_schema(self, path, method): paths = self.schema["paths"] methods = paths.get(path, None) - assert methods is not None, f"{path} not found in {[path for path in paths.keys()]}" + assert methods is not None, f"{path} not found in {list(paths.keys())}" endpoint = methods.get(method, None) - assert endpoint is not None, f"Method {method} not found in {[method for method in methods.keys()]}" + assert endpoint is not None, f"Method {method} not found in {list(methods.keys())}" return endpoint @@ -1132,7 +1132,7 @@ def test_duplicate(self): assert result.status_code == status.HTTP_200_OK, "Could not check duplicate status" result_json = result.json() # Should return all duplicates for id=3 - assert set(x["id"] for x in result_json) == {2, 4, 5, 6} + assert set(x["id"] for x in result_json) == {2, 4, 5, 6} # noqa: C401 # Reset duplicate result = self.client.post(self.url + "2/duplicate/reset/") diff --git a/unittests/tools/test_api_sonarqube_importer.py b/unittests/tools/test_api_sonarqube_importer.py index ed64677270..48b2053d4e 100644 --- a/unittests/tools/test_api_sonarqube_importer.py +++ b/unittests/tools/test_api_sonarqube_importer.py @@ -62,7 +62,7 @@ def dummy_hotspot_rule_wo_risk_description(self, *args, **kwargs): def empty_list(self, *args, **kwargs): - return list() + return [] class TestSonarqubeImporterNoSQToolConfig(DojoTestCase): diff --git a/unittests/tools/test_api_sonarqube_parser.py b/unittests/tools/test_api_sonarqube_parser.py index 15d936facd..abf18ab289 100644 --- a/unittests/tools/test_api_sonarqube_parser.py +++ b/unittests/tools/test_api_sonarqube_parser.py @@ -31,7 +31,7 @@ def dummy_hotspot_rule(self, *args, **kwargs): def empty_list(self, *args, **kwargs): - return list() + return [] class TestApiSonarQubeParser(DojoTestCase): diff --git a/unittests/tools/test_aqua_parser.py b/unittests/tools/test_aqua_parser.py index f9168258ce..64656f459e 100644 --- a/unittests/tools/test_aqua_parser.py +++ b/unittests/tools/test_aqua_parser.py @@ -79,7 +79,7 @@ def test_aqua_parser_for_aqua_severity(self): with open("unittests/scans/aqua/vulns_with_aqua_severity.json") as testfile: parser = AquaParser() findings = parser.get_findings(testfile, Test()) - sevs = list() + sevs = [] for finding in findings: sevs.append(finding.severity) diff --git a/unittests/tools/test_openvas_parser.py b/unittests/tools/test_openvas_parser.py index f31b6e7727..6f266b87b0 100644 --- a/unittests/tools/test_openvas_parser.py +++ b/unittests/tools/test_openvas_parser.py @@ -80,7 +80,7 @@ def test_openvas_csv_report_usingOpenVAS(self): finding = findings[2] self.assertEqual("Apache HTTP Server Detection Consolidation", finding.title) self.assertEqual("Info", finding.severity) - self.assertEqual(finding.unsaved_vulnerability_ids, list()) + self.assertEqual(finding.unsaved_vulnerability_ids, []) def test_openvas_xml_no_vuln(self): with open("unittests/scans/openvas/no_vuln.xml") as f: diff --git a/unittests/tools/test_vcg_parser.py b/unittests/tools/test_vcg_parser.py index 7e7abf55b3..0051c4ff8e 100644 --- a/unittests/tools/test_vcg_parser.py +++ b/unittests/tools/test_vcg_parser.py @@ -181,7 +181,7 @@ def test_parseissuerow_with_no_row_has_no_finding(self): self.assertIsNone(finding) def test_parseissuerow_with_empty_row_has_no_finding(self): - row = dict() + row = {} finding = self.parser.parse_issue(row, Test()) self.assertIsNone(finding) From 24a52eb270eda5a8f5e148a3ae144ee16eb5f1d0 Mon Sep 17 00:00:00 2001 From: Paul Osinski <42211303+paulOsinski@users.noreply.github.com> Date: Tue, 30 Apr 2024 15:48:02 -0400 Subject: [PATCH 100/138] extend _index.md with link to Knowledge Base (#10002) * extend _index.md with link to Knowledge Base This PR is mainly related to the https://documentation.defectdojo.com/ deployment, in order to consolidate all references to the commercial offering onto this single page. The change is mainly to ensure that DefectDojo Open Source and DefectDojo Inc's Knowledge Base are differentiated and identified in both locations. * Update _index.md with slight language change --- docs/content/en/_index.md | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/docs/content/en/_index.md b/docs/content/en/_index.md index 4510d5554a..ce75fcc5b8 100644 --- a/docs/content/en/_index.md +++ b/docs/content/en/_index.md @@ -17,8 +17,6 @@ cascade: ![image](images/dashboard.png) -## About DefectDojo - ### What is DefectDojo? DefectDojo is a DevSecOps platform. DefectDojo streamlines DevSecOps by serving as an aggregator and single pane of glass for your security tools. DefectDojo has smart features to enhance and tune the results from your security tools including the ability to merge findings, remember false positives, and distill duplicates. DefectDojo also integrates with JIRA, provides metrics / reports, and can also be used for traditional pen test management. @@ -36,11 +34,8 @@ Product:Engagement model, enables traceability among multiple projects 2. [Usage]({{< ref "/usage" >}}) covers how to use DefectDojo to manage vulnerabilities. 3. We support a large amount of [integrations]({{< ref "/integrations" >}}) to help fit DefectDojo in your DevSecOps program. - ### Where to find DefectDojo? -Proprietary editions that include [additional features](https://documentation.defectdojo.com/proprietary_plugins/) and support can be purchased through [defectdojo.com](https://www.defectdojo.com/). - The open-source edition is [available on GitHub](https://github.com/DefectDojo/django-DefectDojo). @@ -48,6 +43,16 @@ A running example is available on [our demo server](https://demo.defectdojo.org) using the credentials `admin` / `defectdojo@demo#appsec`. Note: The demo server is refreshed regularly and provisioned with some sample data. -Follow us on [LinkedIn](https://www.linkedin.com/company/33245534) for updates. -To get in touch with us, please reach out to info@defectdojo.com +### DefectDojo Pro and Enterprise +DefectDojo Inc. hosts a commercial edition of this software, which includes: +- additional features, smart features and UI improvements +- cloud hosting, with regular backups, updates and maintenance +- premium support and implementation guidance + +For more information, please visit [defectdojo.com](https://www.defectdojo.com/). + +DefectDojo Inc. also maintains an updated Knowledge Base at [https://support.defectdojo.com](https://support.defectdojo.com/en/). The Knowledge Base is written to support DefectDojo's Pro and Enterprise releases, but the tutorials and guides may also be applied to the open-source edition. + +Follow DefectDojo Inc. on [LinkedIn](https://www.linkedin.com/company/33245534) for updates. +To get in touch with us, please reach out to info@defectdojo.com From 2bbf8bcc811175b92c0f31d2edf5aa2e724b44bc Mon Sep 17 00:00:00 2001 From: Aleksandr Chebotov <47745270+al-cheb@users.noreply.github.com> Date: Tue, 30 Apr 2024 23:35:20 +0300 Subject: [PATCH 101/138] helm: Add subcomponent labels for celery beat and worker at deployment (#9865) * helm: Add subcomponent labels for celery beat and worker at deployment ``` apiVersion: apps/v1 kind: Deployment metadata: labels: defectdojo.org/component: celery defectdojo.org/subcomponent: worker spec: selector: matchLabels: defectdojo.org/component: celery defectdojo.org/subcomponent: worker template: metadata: labels: defectdojo.org/component: celery defectdojo.org/subcomponent: worker ``` 1, The first label is for deployment itself, it gives label for that particular deployment. 2, The second label is selector: matchLabels which tells the resources(service etc) to match the pod according to label. 3. The third label is podTemplate labels, the template is actually podTemplate. It describe the pod that it is launched. * Update helm lock file Signed-off-by: DefectDojo * bump chart version * Update helm lock file Signed-off-by: DefectDojo * revert changes --------- Signed-off-by: DefectDojo Co-authored-by: Alexander Chebotov Co-authored-by: DefectDojo --- helm/defectdojo/templates/celery-beat-deployment.yaml | 2 ++ helm/defectdojo/templates/celery-worker-deployment.yaml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/helm/defectdojo/templates/celery-beat-deployment.yaml b/helm/defectdojo/templates/celery-beat-deployment.yaml index 605e41b5b9..d91a246592 100644 --- a/helm/defectdojo/templates/celery-beat-deployment.yaml +++ b/helm/defectdojo/templates/celery-beat-deployment.yaml @@ -18,12 +18,14 @@ spec: selector: matchLabels: defectdojo.org/component: celery + defectdojo.org/subcomponent: beat app.kubernetes.io/name: {{ include "defectdojo.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} template: metadata: labels: defectdojo.org/component: celery + defectdojo.org/subcomponent: beat app.kubernetes.io/name: {{ include "defectdojo.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- if .Values.podLabels }} diff --git a/helm/defectdojo/templates/celery-worker-deployment.yaml b/helm/defectdojo/templates/celery-worker-deployment.yaml index b6ca15e687..86d3b7f650 100644 --- a/helm/defectdojo/templates/celery-worker-deployment.yaml +++ b/helm/defectdojo/templates/celery-worker-deployment.yaml @@ -18,12 +18,14 @@ spec: selector: matchLabels: defectdojo.org/component: celery + defectdojo.org/subcomponent: worker app.kubernetes.io/name: {{ include "defectdojo.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} template: metadata: labels: defectdojo.org/component: celery + defectdojo.org/subcomponent: worker app.kubernetes.io/name: {{ include "defectdojo.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- if .Values.podLabels }} From b4605c9ea982209b838adc444eafef65f742da53 Mon Sep 17 00:00:00 2001 From: kiblik Date: Tue, 30 Apr 2024 22:40:11 +0200 Subject: [PATCH 102/138] Ruff: add and fix EXE rules (#9896) --- dojo/forms.py | 0 dojo/models.py | 0 dojo/product/views.py | 0 dojo/tool_config/factory.py | 0 dojo/tools/arachni/parser.py | 0 dojo/tools/burp/parser.py | 0 dojo/tools/burp_dastardly/parser.py | 0 dojo/tools/checkmarx/__init__.py | 0 dojo/tools/checkmarx/parser.py | 0 dojo/tools/crashtest_security/parser.py | 0 dojo/tools/factory.py | 0 dojo/tools/ggshield/parser.py | 0 dojo/tools/gosec/__init__.py | 0 dojo/tools/hcl_appscan/parser.py | 0 dojo/tools/nmap/parser.py | 0 dojo/tools/openvas/parser.py | 0 dojo/tools/php_security_audit_v2/__init__.py | 0 dojo/tools/qualys_webapp/parser.py | 4 ---- dojo/tools/snyk/__init__.py | 0 dojo/tools/snyk/parser.py | 0 dojo/tools/trustwave/__init__.py | 0 dojo/tools/zap/parser.py | 0 dojo/urls.py | 0 dojo/views.py | 0 ruff.toml | 1 + unittests/tools/test_ggshield_parser.py | 0 26 files changed, 1 insertion(+), 4 deletions(-) mode change 100755 => 100644 dojo/forms.py mode change 100755 => 100644 dojo/models.py mode change 100755 => 100644 dojo/product/views.py mode change 100755 => 100644 dojo/tool_config/factory.py mode change 100755 => 100644 dojo/tools/arachni/parser.py mode change 100755 => 100644 dojo/tools/burp/parser.py mode change 100755 => 100644 dojo/tools/burp_dastardly/parser.py mode change 100755 => 100644 dojo/tools/checkmarx/__init__.py mode change 100755 => 100644 dojo/tools/checkmarx/parser.py mode change 100755 => 100644 dojo/tools/crashtest_security/parser.py mode change 100755 => 100644 dojo/tools/factory.py mode change 100755 => 100644 dojo/tools/ggshield/parser.py mode change 100755 => 100644 dojo/tools/gosec/__init__.py mode change 100755 => 100644 dojo/tools/hcl_appscan/parser.py mode change 100755 => 100644 dojo/tools/nmap/parser.py mode change 100755 => 100644 dojo/tools/openvas/parser.py mode change 100755 => 100644 dojo/tools/php_security_audit_v2/__init__.py mode change 100755 => 100644 dojo/tools/snyk/__init__.py mode change 100755 => 100644 dojo/tools/snyk/parser.py mode change 100755 => 100644 dojo/tools/trustwave/__init__.py mode change 100755 => 100644 dojo/tools/zap/parser.py mode change 100755 => 100644 dojo/urls.py mode change 100755 => 100644 dojo/views.py mode change 100755 => 100644 unittests/tools/test_ggshield_parser.py diff --git a/dojo/forms.py b/dojo/forms.py old mode 100755 new mode 100644 diff --git a/dojo/models.py b/dojo/models.py old mode 100755 new mode 100644 diff --git a/dojo/product/views.py b/dojo/product/views.py old mode 100755 new mode 100644 diff --git a/dojo/tool_config/factory.py b/dojo/tool_config/factory.py old mode 100755 new mode 100644 diff --git a/dojo/tools/arachni/parser.py b/dojo/tools/arachni/parser.py old mode 100755 new mode 100644 diff --git a/dojo/tools/burp/parser.py b/dojo/tools/burp/parser.py old mode 100755 new mode 100644 diff --git a/dojo/tools/burp_dastardly/parser.py b/dojo/tools/burp_dastardly/parser.py old mode 100755 new mode 100644 diff --git a/dojo/tools/checkmarx/__init__.py b/dojo/tools/checkmarx/__init__.py old mode 100755 new mode 100644 diff --git a/dojo/tools/checkmarx/parser.py b/dojo/tools/checkmarx/parser.py old mode 100755 new mode 100644 diff --git a/dojo/tools/crashtest_security/parser.py b/dojo/tools/crashtest_security/parser.py old mode 100755 new mode 100644 diff --git a/dojo/tools/factory.py b/dojo/tools/factory.py old mode 100755 new mode 100644 diff --git a/dojo/tools/ggshield/parser.py b/dojo/tools/ggshield/parser.py old mode 100755 new mode 100644 diff --git a/dojo/tools/gosec/__init__.py b/dojo/tools/gosec/__init__.py old mode 100755 new mode 100644 diff --git a/dojo/tools/hcl_appscan/parser.py b/dojo/tools/hcl_appscan/parser.py old mode 100755 new mode 100644 diff --git a/dojo/tools/nmap/parser.py b/dojo/tools/nmap/parser.py old mode 100755 new mode 100644 diff --git a/dojo/tools/openvas/parser.py b/dojo/tools/openvas/parser.py old mode 100755 new mode 100644 diff --git a/dojo/tools/php_security_audit_v2/__init__.py b/dojo/tools/php_security_audit_v2/__init__.py old mode 100755 new mode 100644 diff --git a/dojo/tools/qualys_webapp/parser.py b/dojo/tools/qualys_webapp/parser.py index cac7cb395f..e1e1799c43 100644 --- a/dojo/tools/qualys_webapp/parser.py +++ b/dojo/tools/qualys_webapp/parser.py @@ -1,7 +1,3 @@ -#!/usr/bin/env python -# -# -*- coding:utf-8 -*- - import base64 import re import xml.etree.ElementTree diff --git a/dojo/tools/snyk/__init__.py b/dojo/tools/snyk/__init__.py old mode 100755 new mode 100644 diff --git a/dojo/tools/snyk/parser.py b/dojo/tools/snyk/parser.py old mode 100755 new mode 100644 diff --git a/dojo/tools/trustwave/__init__.py b/dojo/tools/trustwave/__init__.py old mode 100755 new mode 100644 diff --git a/dojo/tools/zap/parser.py b/dojo/tools/zap/parser.py old mode 100755 new mode 100644 diff --git a/dojo/urls.py b/dojo/urls.py old mode 100755 new mode 100644 diff --git a/dojo/views.py b/dojo/views.py old mode 100755 new mode 100644 diff --git a/ruff.toml b/ruff.toml index 30152d6cb9..cfa81b12d6 100644 --- a/ruff.toml +++ b/ruff.toml @@ -38,6 +38,7 @@ select = [ "UP", "YTT", "ASYNC", + "EXE", "TRIO", "C4", "ICN", diff --git a/unittests/tools/test_ggshield_parser.py b/unittests/tools/test_ggshield_parser.py old mode 100755 new mode 100644 From 1c9c74e3ae997fa2f8e75295fc6f415f5ec63917 Mon Sep 17 00:00:00 2001 From: kiblik Date: Tue, 30 Apr 2024 22:41:16 +0200 Subject: [PATCH 103/138] Ruff: add and fix EM rules (#9892) * Ruff: add and fix EM rules Signed-off-by: kiblik <5609770+kiblik@users.noreply.github.com> * Update dojo/tools/api_sonarqube/api_client.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Update dojo/tools/factory.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Clean newline --------- Signed-off-by: kiblik <5609770+kiblik@users.noreply.github.com> Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> --- dojo/api_v2/permissions.py | 42 ++- dojo/api_v2/serializers.py | 291 ++++++++---------- dojo/authorization/authorization.py | 16 +- dojo/endpoint/utils.py | 3 +- dojo/engagement/views.py | 15 +- dojo/finding/helper.py | 3 +- dojo/forms.py | 143 +++++---- dojo/group/utils.py | 3 +- dojo/importers/importer/importer.py | 3 +- dojo/importers/reimporter/reimporter.py | 5 +- dojo/importers/reimporter/utils.py | 9 +- dojo/importers/utils.py | 5 +- dojo/jira_link/helper.py | 21 +- .../commands/import_github_languages.py | 3 +- dojo/models.py | 24 +- dojo/object/views.py | 6 +- dojo/product/views.py | 3 +- dojo/reports/views.py | 9 +- dojo/reports/widgets.py | 9 +- dojo/tool_product/views.py | 6 +- dojo/tools/anchore_enterprise/parser.py | 5 +- dojo/tools/anchorectl_policies/parser.py | 5 +- dojo/tools/api_blackduck/api_client.py | 5 +- dojo/tools/api_blackduck/importer.py | 9 +- dojo/tools/api_bugcrowd/api_client.py | 11 +- dojo/tools/api_bugcrowd/importer.py | 9 +- dojo/tools/api_bugcrowd/parser.py | 3 +- dojo/tools/api_cobalt/api_client.py | 17 +- dojo/tools/api_cobalt/importer.py | 9 +- dojo/tools/api_edgescan/api_client.py | 8 +- dojo/tools/api_edgescan/importer.py | 9 +- dojo/tools/api_sonarqube/api_client.py | 49 +-- dojo/tools/api_sonarqube/importer.py | 9 +- dojo/tools/api_vulners/api_client.py | 5 +- dojo/tools/api_vulners/importer.py | 9 +- dojo/tools/appspider/parser.py | 3 +- dojo/tools/auditjs/parser.py | 8 +- dojo/tools/aws_prowler/parser.py | 3 +- dojo/tools/aws_prowler_v3/parser.py | 3 +- dojo/tools/awssecurityhub/parser.py | 9 +- .../parser.py | 3 +- .../blackduck_component_risk/importer.py | 6 +- dojo/tools/burp_api/parser.py | 5 +- dojo/tools/burp_graphql/parser.py | 6 +- dojo/tools/checkmarx_osa/parser.py | 13 +- dojo/tools/checkov/parser.py | 3 +- dojo/tools/clair/parser.py | 3 +- dojo/tools/coverity_api/parser.py | 12 +- dojo/tools/crashtest_security/parser.py | 3 +- dojo/tools/crunch42/parser.py | 3 +- dojo/tools/cyclonedx/xml_parser.py | 5 +- dojo/tools/dependency_track/parser.py | 15 +- dojo/tools/factory.py | 9 +- dojo/tools/gcloud_artifact_scan/parser.py | 3 +- dojo/tools/generic/parser.py | 8 +- dojo/tools/github_vulnerability/parser.py | 5 +- dojo/tools/gitlab_dep_scan/parser.py | 3 +- dojo/tools/gitleaks/parser.py | 3 +- dojo/tools/govulncheck/parser.py | 3 +- dojo/tools/hcl_appscan/parser.py | 5 +- dojo/tools/huskyci/parser.py | 3 +- dojo/tools/hydra/parser.py | 10 +- dojo/tools/ibm_app/parser.py | 5 +- dojo/tools/immuniweb/parser.py | 5 +- dojo/tools/intsights/parser.py | 5 +- dojo/tools/meterian/parser.py | 3 +- dojo/tools/microfocus_webinspect/parser.py | 5 +- dojo/tools/nancy/parser.py | 3 +- dojo/tools/neuvector/parser.py | 6 +- dojo/tools/neuvector_compliance/parser.py | 6 +- dojo/tools/nikto/parser.py | 3 +- dojo/tools/nmap/parser.py | 3 +- dojo/tools/noseyparker/parser.py | 6 +- dojo/tools/npm_audit/parser.py | 13 +- dojo/tools/npm_audit_7_plus/parser.py | 9 +- dojo/tools/nsp/parser.py | 3 +- dojo/tools/openscap/parser.py | 10 +- dojo/tools/openvas/xml_parser.py | 5 +- dojo/tools/ort/parser.py | 3 +- dojo/tools/ossindex_devaudit/parser.py | 8 +- .../php_symfony_security_check/parser.py | 3 +- dojo/tools/risk_recon/api.py | 16 +- dojo/tools/sarif/parser.py | 3 +- dojo/tools/semgrep/parser.py | 3 +- dojo/tools/snyk/parser.py | 3 +- dojo/tools/snyk_code/parser.py | 3 +- dojo/tools/sslscan/parser.py | 5 +- dojo/tools/sslyze/parser.py | 3 +- dojo/tools/sslyze/parser_json.py | 3 +- dojo/tools/sslyze/parser_xml.py | 5 +- dojo/tools/stackhawk/parser.py | 3 +- .../tools/sysdig_reports/sysdig_csv_parser.py | 6 +- dojo/tools/tenable/parser.py | 5 +- dojo/tools/tenable/xml_format.py | 3 +- dojo/tools/terrascan/parser.py | 3 +- dojo/tools/tfsec/parser.py | 5 +- dojo/tools/threagile/parser.py | 7 +- dojo/tools/trivy/parser.py | 5 +- dojo/tools/trufflehog3/parser.py | 3 +- dojo/tools/twistlock/parser.py | 6 +- dojo/tools/vcg/parser.py | 3 +- dojo/tools/veracode/parser.py | 5 +- dojo/tools/wapiti/parser.py | 5 +- dojo/tools/whitehat_sentinel/parser.py | 5 +- dojo/tools/xanitizer/parser.py | 5 +- dojo/tools/yarn_audit/parser.py | 5 +- dojo/user/views.py | 6 +- dojo/utils.py | 21 +- ruff.toml | 1 + tests/product_test.py | 5 +- 110 files changed, 651 insertions(+), 540 deletions(-) diff --git a/dojo/api_v2/permissions.py b/dojo/api_v2/permissions.py index b9c2ec433b..89267e68cd 100644 --- a/dojo/api_v2/permissions.py +++ b/dojo/api_v2/permissions.py @@ -39,9 +39,8 @@ def check_post_permission(request, post_model, post_pk, post_permission): if request.method == "POST": if request.data.get(post_pk) is None: - raise ParseError( - f"Unable to check for permissions: Attribute '{post_pk}' is required" - ) + msg = f"Unable to check for permissions: Attribute '{post_pk}' is required" + raise ParseError(msg) object = get_object_or_404(post_model, pk=request.data.get(post_pk)) return user_has_permission(request.user, object, post_permission) else: @@ -516,9 +515,8 @@ def has_permission(self, request, view): "product '%s' doesn''t exist" % product_id ) else: - raise serializers.ValidationError( - "Need product_id or product_name to perform import" - ) + msg = "Need product_id or product_name to perform import" + raise serializers.ValidationError(msg) class UserHasProductPermission(permissions.BasePermission): @@ -950,10 +948,12 @@ def raise_no_auto_create_import_validation_error( ): # check for mandatory fields first if not product_name: - raise ValidationError("product_name parameter missing") + msg = "product_name parameter missing" + raise ValidationError(msg) if not engagement_name: - raise ValidationError("engagement_name parameter missing") + msg = "engagement_name parameter missing" + raise ValidationError(msg) if product_type_name and not product_type: raise serializers.ValidationError( @@ -962,29 +962,25 @@ def raise_no_auto_create_import_validation_error( if product_name and not product: if product_type_name: - raise serializers.ValidationError( - f"Product '{product_name}' doesn't exist in Product_Type '{product_type_name}'" - ) + msg = f"Product '{product_name}' doesn't exist in Product_Type '{product_type_name}'" + raise serializers.ValidationError(msg) else: raise serializers.ValidationError( "Product '%s' doesn't exist" % product_name ) if engagement_name and not engagement: - raise serializers.ValidationError( - f"Engagement '{engagement_name}' doesn't exist in Product '{product_name}'" - ) + msg = f"Engagement '{engagement_name}' doesn't exist in Product '{product_name}'" + raise serializers.ValidationError(msg) # these are only set for reimport if test_title: - raise serializers.ValidationError( - f"Test '{test_title}' with scan_type '{scan_type}' doesn't exist in Engagement '{engagement_name}'" - ) + msg = f"Test '{test_title}' with scan_type '{scan_type}' doesn't exist in Engagement '{engagement_name}'" + raise serializers.ValidationError(msg) if scan_type: - raise serializers.ValidationError( - f"Test with scan_type '{scan_type}' doesn't exist in Engagement '{engagement_name}'" - ) + msg = f"Test with scan_type '{scan_type}' doesn't exist in Engagement '{engagement_name}'" + raise serializers.ValidationError(msg) raise ValidationError(error_message) @@ -1015,10 +1011,12 @@ def check_auto_create_permission( - User must have Product_Type_Add_Product permission for the Product_Type, or the user has the Product_Type_Add permission """ if not product_name: - raise ValidationError("product_name parameter missing") + msg = "product_name parameter missing" + raise ValidationError(msg) if not engagement_name: - raise ValidationError("engagement_name parameter missing") + msg = "engagement_name parameter missing" + raise ValidationError(msg) if engagement: # existing engagement, nothing special to check diff --git a/dojo/api_v2/serializers.py b/dojo/api_v2/serializers.py index 47eda0f620..dc949649ee 100644 --- a/dojo/api_v2/serializers.py +++ b/dojo/api_v2/serializers.py @@ -134,7 +134,8 @@ def get_import_meta_data_from_dict(data): if isinstance(test_id, Test): test_id = test_id.id elif isinstance(test_id, str) and not test_id.isdigit(): - raise serializers.ValidationError("test must be an integer") + msg = "test must be an integer" + raise serializers.ValidationError(msg) scan_type = data.get("scan_type", None) @@ -145,7 +146,8 @@ def get_import_meta_data_from_dict(data): if isinstance(engagement_id, Engagement): engagement_id = engagement_id.id elif isinstance(engagement_id, str) and not engagement_id.isdigit(): - raise serializers.ValidationError("engagement must be an integer") + msg = "engagement must be an integer" + raise serializers.ValidationError(msg) engagement_name = data.get("engagement_name", None) @@ -178,7 +180,8 @@ def get_product_id_from_dict(data): if isinstance(product_id, Product): product_id = product_id.id elif isinstance(product_id, str) and not product_id.isdigit(): - raise serializers.ValidationError("product must be an integer") + msg = "product must be an integer" + raise serializers.ValidationError(msg) return product_id @@ -595,17 +598,15 @@ def validate(self, data): if not self.context["request"].user.is_superuser and ( instance_is_superuser or data_is_superuser ): - raise ValidationError( - "Only superusers are allowed to add or edit superusers." - ) + msg = "Only superusers are allowed to add or edit superusers." + raise ValidationError(msg) if ( self.context["request"].method in ["PATCH", "PUT"] and "password" in data ): - raise ValidationError( - "Update of password though API is not allowed" - ) + msg = "Update of password though API is not allowed" + raise ValidationError(msg) else: return super().validate(data) @@ -733,9 +734,8 @@ def validate(self, data): Permissions.Group_Manage_Members, ) ): - raise PermissionDenied( - "You are not permitted to add a user to this group" - ) + msg = "You are not permitted to add a user to this group" + raise PermissionDenied(msg) if ( self.instance is None @@ -746,7 +746,8 @@ def validate(self, data): group=data.get("group"), user=data.get("user") ) if members.count() > 0: - raise ValidationError("Dojo_Group_Member already exists") + msg = "Dojo_Group_Member already exists" + raise ValidationError(msg) if self.instance is not None and not data.get("role").is_owner: owners = ( @@ -757,16 +758,16 @@ def validate(self, data): .count() ) if owners < 1: - raise ValidationError("There must be at least one owner") + msg = "There must be at least one owner" + raise ValidationError(msg) if data.get("role").is_owner and not user_has_permission( self.context["request"].user, data.get("group"), Permissions.Group_Add_Owner, ): - raise PermissionDenied( - "You are not permitted to add a user as Owner to this group" - ) + msg = "You are not permitted to add a user as Owner to this group" + raise PermissionDenied(msg) return data @@ -790,11 +791,11 @@ def validate(self, data): group = data.get("group") if user is None and group is None: - raise ValidationError("Global_Role must have either user or group") + msg = "Global_Role must have either user or group" + raise ValidationError(msg) if user is not None and group is not None: - raise ValidationError( - "Global_Role cannot have both user and group" - ) + msg = "Global_Role cannot have both user and group" + raise ValidationError(msg) return data @@ -885,9 +886,8 @@ def validate(self, data): Permissions.Product_Manage_Members, ) ): - raise PermissionDenied( - "You are not permitted to add a member to this product" - ) + msg = "You are not permitted to add a member to this product" + raise PermissionDenied(msg) if ( self.instance is None @@ -898,16 +898,16 @@ def validate(self, data): product=data.get("product"), user=data.get("user") ) if members.count() > 0: - raise ValidationError("Product_Member already exists") + msg = "Product_Member already exists" + raise ValidationError(msg) if data.get("role").is_owner and not user_has_permission( self.context["request"].user, data.get("product"), Permissions.Product_Member_Add_Owner, ): - raise PermissionDenied( - "You are not permitted to add a member as Owner to this product" - ) + msg = "You are not permitted to add a member as Owner to this product" + raise PermissionDenied(msg) return data @@ -927,9 +927,8 @@ def validate(self, data): Permissions.Product_Group_Add, ) ): - raise PermissionDenied( - "You are not permitted to add a group to this product" - ) + msg = "You are not permitted to add a group to this product" + raise PermissionDenied(msg) if ( self.instance is None @@ -940,16 +939,16 @@ def validate(self, data): product=data.get("product"), group=data.get("group") ) if members.count() > 0: - raise ValidationError("Product_Group already exists") + msg = "Product_Group already exists" + raise ValidationError(msg) if data.get("role").is_owner and not user_has_permission( self.context["request"].user, data.get("product"), Permissions.Product_Group_Add_Owner, ): - raise PermissionDenied( - "You are not permitted to add a group as Owner to this product" - ) + msg = "You are not permitted to add a group as Owner to this product" + raise PermissionDenied(msg) return data @@ -969,9 +968,8 @@ def validate(self, data): Permissions.Product_Type_Manage_Members, ) ): - raise PermissionDenied( - "You are not permitted to add a member to this product type" - ) + msg = "You are not permitted to add a member to this product type" + raise PermissionDenied(msg) if ( self.instance is None @@ -982,7 +980,8 @@ def validate(self, data): product_type=data.get("product_type"), user=data.get("user") ) if members.count() > 0: - raise ValidationError("Product_Type_Member already exists") + msg = "Product_Type_Member already exists" + raise ValidationError(msg) if self.instance is not None and not data.get("role").is_owner: owners = ( @@ -993,16 +992,16 @@ def validate(self, data): .count() ) if owners < 1: - raise ValidationError("There must be at least one owner") + msg = "There must be at least one owner" + raise ValidationError(msg) if data.get("role").is_owner and not user_has_permission( self.context["request"].user, data.get("product_type"), Permissions.Product_Type_Member_Add_Owner, ): - raise PermissionDenied( - "You are not permitted to add a member as Owner to this product type" - ) + msg = "You are not permitted to add a member as Owner to this product type" + raise PermissionDenied(msg) return data @@ -1022,9 +1021,8 @@ def validate(self, data): Permissions.Product_Type_Group_Add, ) ): - raise PermissionDenied( - "You are not permitted to add a group to this product type" - ) + msg = "You are not permitted to add a group to this product type" + raise PermissionDenied(msg) if ( self.instance is None @@ -1035,16 +1033,16 @@ def validate(self, data): product_type=data.get("product_type"), group=data.get("group") ) if members.count() > 0: - raise ValidationError("Product_Type_Group already exists") + msg = "Product_Type_Group already exists" + raise ValidationError(msg) if data.get("role").is_owner and not user_has_permission( self.context["request"].user, data.get("product_type"), Permissions.Product_Type_Group_Add_Owner, ): - raise PermissionDenied( - "You are not permitted to add a group as Owner to this product type" - ) + msg = "You are not permitted to add a group as Owner to this product type" + raise PermissionDenied(msg) return data @@ -1065,9 +1063,8 @@ class Meta: def validate(self, data): if self.context["request"].method == "POST": if data.get("target_start") > data.get("target_end"): - raise serializers.ValidationError( - "Your target start date exceeds your target end date" - ) + msg = "Your target start date exceeds your target end date" + raise serializers.ValidationError(msg) return data def build_relational_field(self, field_name, relation_info): @@ -1136,7 +1133,8 @@ def validate(self, data): name = data.get("name") # Make sure this will not create a duplicate test type if Tool_Type.objects.filter(name=name).count() > 0: - raise serializers.ValidationError('A Tool Type with the name already exists') + msg = 'A Tool Type with the name already exists' + raise serializers.ValidationError(msg) return data @@ -1182,9 +1180,8 @@ def create(self, validated_data): ) except IntegrityError as ie: if "endpoint-finding relation" in str(ie): - raise serializers.ValidationError( - "This endpoint-finding relation already exists" - ) + msg = "This endpoint-finding relation already exists" + raise serializers.ValidationError(msg) else: raise status.mitigated = validated_data.get("mitigated", False) @@ -1200,9 +1197,8 @@ def update(self, instance, validated_data): return super().update(instance, validated_data) except IntegrityError as ie: if "endpoint-finding relation" in str(ie): - raise serializers.ValidationError( - "This endpoint-finding relation already exists" - ) + msg = "This endpoint-finding relation already exists" + raise serializers.ValidationError(msg) else: raise @@ -1219,7 +1215,8 @@ def validate(self, data): if not self.context["request"].method == "PATCH": if "product" not in data: - raise serializers.ValidationError("Product is required") + msg = "Product is required" + raise serializers.ValidationError(msg) protocol = data.get("protocol") userinfo = data.get("userinfo") host = data.get("host") @@ -1237,9 +1234,8 @@ def validate(self, data): query = data.get("query", self.instance.query) fragment = data.get("fragment", self.instance.fragment) if "product" in data and data["product"] != self.instance.product: - raise serializers.ValidationError( - "Change of product is not possible" - ) + msg = "Change of product is not possible" + raise serializers.ValidationError(msg) product = self.instance.product endpoint_ins = Endpoint( @@ -1276,11 +1272,11 @@ def validate(self, data): ) or ( self.context["request"].method in ["POST"] and endpoint.count() > 0 ): - raise serializers.ValidationError( + msg = ( "It appears as though an endpoint with this data already " - "exists for this product.", - code="invalid", + "exists for this product." ) + raise serializers.ValidationError(msg, code="invalid") # use clean data data["protocol"] = endpoint_ins.protocol @@ -1330,9 +1326,8 @@ def validate(self, data): ): pass else: - raise serializers.ValidationError( - "Either engagement or finding or finding_group has to be set." - ) + msg = "Either engagement or finding or finding_group has to be set." + raise serializers.ValidationError(msg) return data @@ -1360,9 +1355,8 @@ def validate(self, data): product = data.get("product", None) if (engagement and product) or (not engagement and not product): - raise serializers.ValidationError( - "Either engagement or product has to be set." - ) + msg = "Either engagement or product has to be set." + raise serializers.ValidationError(msg) return data @@ -1532,22 +1526,19 @@ def validate(self, data): finding_objects = Finding.objects.filter(id__in=findings_ids) authed_findings = get_authorized_findings(Permissions.Finding_Edit).filter(id__in=findings_ids) if len(findings) != len(authed_findings): - raise PermissionDenied( - "You are not permitted to add one or more selected findings to this risk acceptance" - ) + msg = "You are not permitted to add one or more selected findings to this risk acceptance" + raise PermissionDenied(msg) if self.context["request"].method == "POST": engagements = finding_objects.values_list('test__engagement__id', flat=True).distinct().count() if engagements > 1: - raise PermissionDenied( - "You are not permitted to add findings to a distinct engagement" - ) + msg = "You are not permitted to add findings to a distinct engagement" + raise PermissionDenied(msg) elif self.context['request'].method in ['PATCH', 'PUT']: engagement = Engagement.objects.filter(risk_acceptance=self.instance.id).first() findings = finding_objects.exclude(test__engagement__id=engagement.id) if len(findings) > 0: - raise PermissionDenied( - "You are not permitted to add findings to a distinct engagement" - ) + msg = "You are not permitted to add findings to a distinct engagement" + raise PermissionDenied(msg) return data class Meta: @@ -1769,34 +1760,29 @@ def validate(self, data): is_risk_accepted = data.get("risk_accepted", False) if (is_active or is_verified) and is_duplicate: - raise serializers.ValidationError( - "Duplicate findings cannot be" " verified or active" - ) + msg = "Duplicate findings cannot be" " verified or active" + raise serializers.ValidationError(msg) if is_false_p and is_verified: - raise serializers.ValidationError( - "False positive findings cannot " "be verified." - ) + msg = "False positive findings cannot " "be verified." + raise serializers.ValidationError(msg) if is_risk_accepted and not self.instance.risk_accepted: if ( not self.instance.test.engagement.product.enable_simple_risk_acceptance ): - raise serializers.ValidationError( - "Simple risk acceptance is disabled for this product, use the UI to accept this finding." - ) + msg = "Simple risk acceptance is disabled for this product, use the UI to accept this finding." + raise serializers.ValidationError(msg) if is_active and is_risk_accepted: - raise serializers.ValidationError( - "Active findings cannot be risk accepted." - ) + msg = "Active findings cannot be risk accepted." + raise serializers.ValidationError(msg) return data def validate_severity(self, value: str) -> str: if value not in SEVERITIES: - raise serializers.ValidationError( - f"Severity must be one of the following: {SEVERITIES}" - ) + msg = f"Severity must be one of the following: {SEVERITIES}" + raise serializers.ValidationError(msg) return value def build_relational_field(self, field_name, relation_info): @@ -1902,37 +1888,34 @@ def validate(self, data): if (data.get("active") or data.get("verified")) and data.get( "duplicate" ): - raise serializers.ValidationError( - "Duplicate findings cannot be verified or active" - ) + msg = "Duplicate findings cannot be verified or active" + raise serializers.ValidationError(msg) if data.get("false_p") and data.get("verified"): - raise serializers.ValidationError( - "False positive findings cannot be verified." - ) + msg = "False positive findings cannot be verified." + raise serializers.ValidationError(msg) if "risk_accepted" in data and data.get("risk_accepted"): test = data.get("test") # test = Test.objects.get(id=test_id) if not test.engagement.product.enable_simple_risk_acceptance: - raise serializers.ValidationError( - "Simple risk acceptance is disabled for this product, use the UI to accept this finding." - ) + msg = "Simple risk acceptance is disabled for this product, use the UI to accept this finding." + raise serializers.ValidationError(msg) if ( data.get("active") and "risk_accepted" in data and data.get("risk_accepted") ): - raise serializers.ValidationError( - "Active findings cannot be risk accepted." - ) + msg = "Active findings cannot be risk accepted." + raise serializers.ValidationError(msg) return data def validate_severity(self, value: str) -> str: if value not in SEVERITIES: + msg = f"Severity must be one of the following: {SEVERITIES}" raise serializers.ValidationError( - f"Severity must be one of the following: {SEVERITIES}" + msg ) return value @@ -2014,8 +1997,9 @@ class Meta: def validate_severity(self, value: str) -> str: if value not in SEVERITIES: + msg = f"Severity must be one of the following: {SEVERITIES}" raise serializers.ValidationError( - f"Severity must be one of the following: {SEVERITIES}" + msg ) return value @@ -2032,8 +2016,9 @@ class Meta: def validate_severity(self, value: str) -> str: if value not in SEVERITIES: + msg = f"Severity must be one of the following: {SEVERITIES}" raise serializers.ValidationError( - f"Severity must be one of the following: {SEVERITIES}" + msg ) return value @@ -2059,9 +2044,8 @@ def validate(self, data): new_sla_config = data.get('sla_configuration', None) old_sla_config = getattr(self.instance, 'sla_configuration', None) if new_sla_config and old_sla_config and new_sla_config != old_sla_config: - raise serializers.ValidationError( - 'Finding SLA expiration dates are currently being recalculated. The SLA configuration for this product cannot be changed until the calculation is complete.' - ) + msg = 'Finding SLA expiration dates are currently being recalculated. The SLA configuration for this product cannot be changed until the calculation is complete.' + raise serializers.ValidationError(msg) return data def get_findings_count(self, obj) -> int: @@ -2333,13 +2317,11 @@ def validate(self, data): scan_type = data.get("scan_type") file = data.get("file") if not file and requires_file(scan_type): - raise serializers.ValidationError( - f"Uploading a Report File is required for {scan_type}" - ) + msg = f"Uploading a Report File is required for {scan_type}" + raise serializers.ValidationError(msg) if file and is_scan_file_too_large(file): - raise serializers.ValidationError( - f"Report file is too large. Maximum supported size is {settings.SCAN_FILE_MAX_SIZE} MB" - ) + msg = f"Report file is too large. Maximum supported size is {settings.SCAN_FILE_MAX_SIZE} MB" + raise serializers.ValidationError(msg) tool_type = requires_tool_type(scan_type) if tool_type: api_scan_configuration = data.get("api_scan_configuration") @@ -2348,16 +2330,14 @@ def validate(self, data): and tool_type != api_scan_configuration.tool_configuration.tool_type.name ): - raise serializers.ValidationError( - f"API scan configuration must be of tool type {tool_type}" - ) + msg = f"API scan configuration must be of tool type {tool_type}" + raise serializers.ValidationError(msg) return data def validate_scan_date(self, value): if value and value > timezone.localdate(): - raise serializers.ValidationError( - "The scan_date cannot be in the future!" - ) + msg = "The scan_date cannot be in the future!" + raise serializers.ValidationError(msg) return value @@ -2664,7 +2644,8 @@ def save(self, push_to_jira=False): else: # should be captured by validation / permission check already - raise NotFound("test not found") + msg = "test not found" + raise NotFound(msg) if test: data["test"] = test @@ -2690,13 +2671,11 @@ def validate(self, data): scan_type = data.get("scan_type") file = data.get("file") if not file and requires_file(scan_type): - raise serializers.ValidationError( - f"Uploading a Report File is required for {scan_type}" - ) + msg = f"Uploading a Report File is required for {scan_type}" + raise serializers.ValidationError(msg) if file and is_scan_file_too_large(file): - raise serializers.ValidationError( - f"Report file is too large. Maximum supported size is {settings.SCAN_FILE_MAX_SIZE} MB" - ) + msg = f"Report file is too large. Maximum supported size is {settings.SCAN_FILE_MAX_SIZE} MB" + raise serializers.ValidationError(msg) tool_type = requires_tool_type(scan_type) if tool_type: api_scan_configuration = data.get("api_scan_configuration") @@ -2705,16 +2684,14 @@ def validate(self, data): and tool_type != api_scan_configuration.tool_configuration.tool_type.name ): - raise serializers.ValidationError( - f"API scan configuration must be of tool type {tool_type}" - ) + msg = f"API scan configuration must be of tool type {tool_type}" + raise serializers.ValidationError(msg) return data def validate_scan_date(self, value): if value and value > timezone.localdate(): - raise serializers.ValidationError( - "The scan_date cannot be in the future!" - ) + msg = "The scan_date cannot be in the future!" + raise serializers.ValidationError(msg) return value @@ -2735,9 +2712,8 @@ class EndpointMetaImporterSerializer(serializers.Serializer): def validate(self, data): file = data.get("file") if file and is_scan_file_too_large(file): - raise serializers.ValidationError( - f"Report file is too large. Maximum supported size is {settings.SCAN_FILE_MAX_SIZE} MB" - ) + msg = f"Report file is too large. Maximum supported size is {settings.SCAN_FILE_MAX_SIZE} MB" + raise serializers.ValidationError(msg) return data @@ -2810,7 +2786,8 @@ def save(self): except Exception: deserialized = json.loads(data) except Exception: - raise Exception("Invalid format") + msg = "Invalid format" + raise Exception(msg) Languages.objects.filter(product=product).delete() @@ -2839,9 +2816,8 @@ def save(self): def validate(self, data): if is_scan_file_too_large(data["file"]): - raise serializers.ValidationError( - f"File is too large. Maximum supported size is {settings.SCAN_FILE_MAX_SIZE} MB" - ) + msg = f"File is too large. Maximum supported size is {settings.SCAN_FILE_MAX_SIZE} MB" + raise serializers.ValidationError(msg) return data @@ -2973,9 +2949,8 @@ def validate(self, data): if (default_group is None and default_group_role is not None) or ( default_group is not None and default_group_role is None ): - raise ValidationError( - "default_group and default_group_role must either both be set or both be empty." - ) + msg = "default_group and default_group_role must either both be set or both be empty." + raise ValidationError(msg) return data @@ -3076,14 +3051,14 @@ def validate(self, data): user=user, product=product, template=False ).count() if notifications > 0: - raise ValidationError( - "Notification for user and product already exists" - ) + msg = "Notification for user and product already exists" + raise ValidationError(msg) if ( data.get("template") and Notifications.objects.filter(template=True).count() > 0 ): - raise ValidationError("Notification template already exists") + msg = "Notification template already exists" + raise ValidationError(msg) return data @@ -3114,9 +3089,8 @@ def validate(self, data): old_days = getattr(self.instance, field, None) new_days = data.get(field, None) if old_days and new_days and (old_days != new_days): - raise serializers.ValidationError( - 'Finding SLA expiration dates are currently being calculated. The SLA days for this SLA configuration cannot be changed until the calculation is complete.' - ) + msg = 'Finding SLA expiration dates are currently being calculated. The SLA days for this SLA configuration cannot be changed until the calculation is complete.' + raise serializers.ValidationError(msg) return data @@ -3260,6 +3234,7 @@ def create(self, validated_data): return super().create(validated_data) except IntegrityError as e: if 'duplicate key value violates unique constraint "dojo_announcement_pkey"' in str(e): - raise serializers.ValidationError("No more than one Announcement is allowed") + msg = "No more than one Announcement is allowed" + raise serializers.ValidationError(msg) else: raise diff --git a/dojo/authorization/authorization.py b/dojo/authorization/authorization.py index 1cbef9ecd6..8974f2c478 100644 --- a/dojo/authorization/authorization.py +++ b/dojo/authorization/authorization.py @@ -202,9 +202,8 @@ def user_has_permission(user, obj, permission): user, obj.finding.test.engagement.product, permission ) else: - raise NoAuthorizationImplementedError( - f"No authorization implemented for class {type(obj).__name__} and permission {permission}" - ) + msg = f"No authorization implemented for class {type(obj).__name__} and permission {permission}" + raise NoAuthorizationImplementedError(msg) def user_has_global_permission(user, permission): @@ -258,9 +257,8 @@ def user_has_global_permission_or_403(user, permission): def get_roles_for_permission(permission): if not Permissions.has_value(permission): - raise PermissionDoesNotExistError( - f"Permission {permission} does not exist" - ) + msg = f"Permission {permission} does not exist" + raise PermissionDoesNotExistError(msg) roles_for_permissions = set() roles = get_roles_with_permissions() for role in roles: @@ -274,7 +272,8 @@ def role_has_permission(role, permission): if role is None: return False if not Roles.has_value(role): - raise RoleDoesNotExistError(f"Role {role} does not exist") + msg = f"Role {role} does not exist" + raise RoleDoesNotExistError(msg) roles = get_roles_with_permissions() permissions = roles.get(role) if not permissions: @@ -286,7 +285,8 @@ def role_has_global_permission(role, permission): if role is None: return False if not Roles.has_value(role): - raise RoleDoesNotExistError(f"Role {role} does not exist") + msg = f"Role {role} does not exist" + raise RoleDoesNotExistError(msg) roles = get_global_roles_with_permissions() permissions = roles.get(role) if permissions and permission in permissions: diff --git a/dojo/endpoint/utils.py b/dojo/endpoint/utils.py index 4c404a3275..9fd400979d 100644 --- a/dojo/endpoint/utils.py +++ b/dojo/endpoint/utils.py @@ -322,7 +322,8 @@ def endpoint_meta_import(file, product, create_endpoints, create_tags, create_me extra_tags='alert-danger') return HttpResponseRedirect(reverse('import_endpoint_meta', args=(product.id, ))) elif origin == 'API': - raise ValidationError('The column "hostname" must be present to map host to Endpoint.') + msg = 'The column "hostname" must be present to map host to Endpoint.' + raise ValidationError(msg) keys = [key for key in reader.fieldnames if key != 'hostname'] diff --git a/dojo/engagement/views.py b/dojo/engagement/views.py index d4da3198d7..49752edbb9 100644 --- a/dojo/engagement/views.py +++ b/dojo/engagement/views.py @@ -104,7 +104,8 @@ def engagement_calendar(request): def get_filtered_engagements(request, view): if view not in ['all', 'active']: - raise ValidationError(f'View {view} is not allowed') + msg = f'View {view} is not allowed' + raise ValidationError(msg) engagements = get_authorized_engagements(Permissions.Engagement_View).order_by('-target_start') @@ -679,7 +680,8 @@ def get(self, request, eid=None, pid=None): product = get_object_or_404(Product, id=pid) engagement_or_product = product else: - raise Exception('Either Engagement or Product has to be provided') + msg = 'Either Engagement or Product has to be provided' + raise Exception(msg) user_has_permission_or_403(user, engagement_or_product, Permissions.Import_Scan_Result) @@ -728,7 +730,8 @@ def post(self, request, eid=None, pid=None): product = get_object_or_404(Product, id=pid) engagement_or_product = product else: - raise Exception('Either Engagement or Product has to be provided') + msg = 'Either Engagement or Product has to be provided' + raise Exception(msg) user_has_permission_or_403(user, engagement_or_product, Permissions.Import_Scan_Result) @@ -1331,7 +1334,8 @@ def get_list_index(list, index): def get_engagements(request): url = request.META.get('QUERY_STRING') if not url: - raise ValidationError('Please use the export button when exporting engagements') + msg = 'Please use the export button when exporting engagements' + raise ValidationError(msg) else: if url.startswith('url='): url = url[4:] @@ -1339,7 +1343,8 @@ def get_engagements(request): path_items = list(filter(None, re.split(r'/|\?', url))) if not path_items or path_items[0] != 'engagement': - raise ValidationError('URL is not an engagement view') + msg = 'URL is not an engagement view' + raise ValidationError(msg) view = query = None if get_list_index(path_items, 1) in ['active', 'all']: diff --git a/dojo/finding/helper.py b/dojo/finding/helper.py index debb209b3f..48a6c25786 100644 --- a/dojo/finding/helper.py +++ b/dojo/finding/helper.py @@ -146,7 +146,8 @@ def can_edit_mitigated_data(user): def create_finding_group(finds, finding_group_name): logger.debug('creating finding_group_create') if not finds or len(finds) == 0: - raise ValueError('cannot create empty Finding Group') + msg = 'cannot create empty Finding Group' + raise ValueError(msg) finding_group_name_dummy = 'bulk group ' + strftime("%a, %d %b %Y %X", timezone.now().timetuple()) diff --git a/dojo/forms.py b/dojo/forms.py index 8bce183a95..2a09eeafe7 100644 --- a/dojo/forms.py +++ b/dojo/forms.py @@ -515,12 +515,14 @@ def clean(self): scan_type = cleaned_data.get("scan_type") file = cleaned_data.get("file") if requires_file(scan_type) and not file: - raise forms.ValidationError(f'Uploading a Report File is required for {scan_type}') + msg = f'Uploading a Report File is required for {scan_type}' + raise forms.ValidationError(msg) tool_type = requires_tool_type(scan_type) if tool_type: api_scan_configuration = cleaned_data.get('api_scan_configuration') if api_scan_configuration and tool_type != api_scan_configuration.tool_configuration.tool_type.name: - raise forms.ValidationError(f'API scan configuration must be of tool type {tool_type}') + msg = f'API scan configuration must be of tool type {tool_type}' + raise forms.ValidationError(msg) endpoints_to_add_list, errors = validate_endpoints_to_add(cleaned_data['endpoints_to_add']) if errors: @@ -534,7 +536,8 @@ def clean(self): def clean_scan_date(self): date = self.cleaned_data.get('scan_date', None) if date and date.date() > datetime.today().date(): - raise forms.ValidationError("The date cannot be in the future!") + msg = "The date cannot be in the future!" + raise forms.ValidationError(msg) return date def get_scan_type(self): @@ -614,12 +617,14 @@ def clean(self): cleaned_data = super().clean() file = cleaned_data.get("file") if requires_file(self.scan_type) and not file: - raise forms.ValidationError("Uploading a report file is required for re-uploading findings.") + msg = "Uploading a report file is required for re-uploading findings." + raise forms.ValidationError(msg) tool_type = requires_tool_type(self.scan_type) if tool_type: api_scan_configuration = cleaned_data.get('api_scan_configuration') if api_scan_configuration and tool_type != api_scan_configuration.tool_configuration.tool_type.name: - raise forms.ValidationError(f'API scan configuration must be of tool type {tool_type}') + msg = f'API scan configuration must be of tool type {tool_type}' + raise forms.ValidationError(msg) return cleaned_data @@ -627,7 +632,8 @@ def clean(self): def clean_scan_date(self): date = self.cleaned_data.get('scan_date', None) if date and date.date() > timezone.localtime(timezone.now()).date(): - raise forms.ValidationError("The date cannot be in the future!") + msg = "The date cannot be in the future!" + raise forms.ValidationError(msg) return date @@ -1038,14 +1044,14 @@ def __init__(self, *args, **kwargs): def clean(self): cleaned_data = super().clean() if ((cleaned_data['active'] or cleaned_data['verified']) and cleaned_data['duplicate']): - raise forms.ValidationError('Duplicate findings cannot be' - ' verified or active') + msg = 'Duplicate findings cannot be verified or active' + raise forms.ValidationError(msg) if cleaned_data['false_p'] and cleaned_data['verified']: - raise forms.ValidationError('False positive findings cannot ' - 'be verified.') + msg = 'False positive findings cannot be verified.' + raise forms.ValidationError(msg) if cleaned_data['active'] and 'risk_accepted' in cleaned_data and cleaned_data['risk_accepted']: - raise forms.ValidationError('Active findings cannot ' - 'be risk accepted.') + msg = 'Active findings cannot be risk accepted.' + raise forms.ValidationError(msg) endpoints_to_add_list, errors = validate_endpoints_to_add(cleaned_data['endpoints_to_add']) if errors: @@ -1119,11 +1125,11 @@ def __init__(self, *args, **kwargs): def clean(self): cleaned_data = super().clean() if ((cleaned_data['active'] or cleaned_data['verified']) and cleaned_data['duplicate']): - raise forms.ValidationError('Duplicate findings cannot be' - ' verified or active') + msg = 'Duplicate findings cannot be verified or active' + raise forms.ValidationError(msg) if cleaned_data['false_p'] and cleaned_data['verified']: - raise forms.ValidationError('False positive findings cannot ' - 'be verified.') + msg = 'False positive findings cannot be verified.' + raise forms.ValidationError(msg) endpoints_to_add_list, errors = validate_endpoints_to_add(cleaned_data['endpoints_to_add']) if errors: @@ -1298,14 +1304,14 @@ def clean(self): cleaned_data = super().clean() if (cleaned_data['active'] or cleaned_data['verified']) and cleaned_data['duplicate']: - raise forms.ValidationError('Duplicate findings cannot be' - ' verified or active') + msg = 'Duplicate findings cannot be verified or active' + raise forms.ValidationError(msg) if cleaned_data['false_p'] and cleaned_data['verified']: - raise forms.ValidationError('False positive findings cannot ' - 'be verified.') + msg = 'False positive findings cannot be verified.' + raise forms.ValidationError(msg) if cleaned_data['active'] and 'risk_accepted' in cleaned_data and cleaned_data['risk_accepted']: - raise forms.ValidationError('Active findings cannot ' - 'be risk accepted.') + msg = 'Active findings cannot be risk accepted.' + raise forms.ValidationError(msg) endpoints_to_add_list, errors = validate_endpoints_to_add(cleaned_data['endpoints_to_add']) if errors: @@ -1345,9 +1351,11 @@ def clean(self): cleaned_data = super().clean() if 'title' in cleaned_data: if len(cleaned_data['title']) <= 0: - raise forms.ValidationError("The title is required.") + msg = "The title is required." + raise forms.ValidationError(msg) else: - raise forms.ValidationError("The title is required.") + msg = "The title is required." + raise forms.ValidationError(msg) return cleaned_data @@ -1381,9 +1389,11 @@ def clean(self): if 'title' in cleaned_data: if len(cleaned_data['title']) <= 0: - raise forms.ValidationError("The title is required.") + msg = "The title is required." + raise forms.ValidationError(msg) else: - raise forms.ValidationError("The title is required.") + msg = "The title is required." + raise forms.ValidationError(msg) return cleaned_data @@ -1461,11 +1471,11 @@ def clean(self): cleaned_data = super().clean() if (cleaned_data['active'] or cleaned_data['verified']) and cleaned_data['duplicate']: - raise forms.ValidationError('Duplicate findings cannot be' - ' verified or active') + msg = 'Duplicate findings cannot be verified or active' + raise forms.ValidationError(msg) if cleaned_data['false_p'] and cleaned_data['verified']: - raise forms.ValidationError('False positive findings cannot ' - 'be verified.') + msg = 'False positive findings cannot be verified.' + raise forms.ValidationError(msg) return cleaned_data class Meta: @@ -1513,9 +1523,8 @@ def clean(self): product=self.product ) if endpoint.count() > 1 or (endpoint.count() == 1 and endpoint.first().pk != self.endpoint_instance.pk): - raise forms.ValidationError( - 'It appears as though an endpoint with this data already exists for this product.', - code='invalid') + msg = 'It appears as though an endpoint with this data already exists for this product.' + raise forms.ValidationError(msg, code='invalid') return cleaned_data @@ -1572,8 +1581,8 @@ def clean(self): else: self.product = Product.objects.get(id=int(product)) else: - raise forms.ValidationError('Please enter a valid URL or IP address.', - code='invalid') + msg = 'Please enter a valid URL or IP address.' + raise forms.ValidationError(msg, code='invalid') endpoints_to_add_list, errors = validate_endpoints_to_add(endpoint) if errors: @@ -1765,7 +1774,8 @@ def clean(self): if cleaned_data.get("allow_all_reviewers", False): cleaned_data["reviewers"] = [user.id for user in self.reviewer_queryset] if len(cleaned_data.get("reviewers", [])) == 0: - raise ValidationError("Please select at least one user from the reviewers list") + msg = "Please select at least one user from the reviewers list" + raise ValidationError(msg) return cleaned_data class Meta: @@ -2056,11 +2066,14 @@ def clean(self): confirm_password = self.cleaned_data.get('confirm_password') if not self.user.check_password(current_password): - raise forms.ValidationError('Current password is incorrect.') + msg = 'Current password is incorrect.' + raise forms.ValidationError(msg) if new_password == current_password: - raise forms.ValidationError('New password must be different from current password.') + msg = 'New password must be different from current password.' + raise forms.ValidationError(msg) if new_password != confirm_password: - raise forms.ValidationError('Passwords do not match.') + msg = 'Passwords do not match.' + raise forms.ValidationError(msg) return cleaned_data @@ -2428,7 +2441,8 @@ def clean(self): name = form_data.get("name") # Make sure this will not create a duplicate test type if Tool_Type.objects.filter(name=name).count() > 0: - raise forms.ValidationError('A Tool Type with the name already exists') + msg = 'A Tool Type with the name already exists' + raise forms.ValidationError(msg) return form_data @@ -2480,9 +2494,8 @@ def clean(self): url_validator = URLValidator(schemes=['ssh', 'http', 'https']) url_validator(form_data["url"]) except forms.ValidationError: - raise forms.ValidationError( - 'It does not appear as though this endpoint is a valid URL/SSH or IP address.', - code='invalid') + msg = 'It does not appear as though this endpoint is a valid URL/SSH or IP address.' + raise forms.ValidationError(msg, code='invalid') return form_data @@ -2554,9 +2567,8 @@ def clean(self): url_validator = URLValidator(schemes=['ssh', 'http', 'https']) url_validator(form_data["url"]) except forms.ValidationError: - raise forms.ValidationError( - 'It does not appear as though this endpoint is a valid URL/SSH or IP address.', - code='invalid') + msg = 'It does not appear as though this endpoint is a valid URL/SSH or IP address.' + raise forms.ValidationError(msg, code='invalid') return form_data @@ -2829,9 +2841,11 @@ def clean(self): return cleaned_data if self.target == 'engagement': - raise ValidationError('JIRA Project needs a JIRA Instance, JIRA Project Key, and Epic issue type name, or choose to inherit settings from product') + msg = 'JIRA Project needs a JIRA Instance, JIRA Project Key, and Epic issue type name, or choose to inherit settings from product' + raise ValidationError(msg) else: - raise ValidationError('JIRA Project needs a JIRA Instance, JIRA Project Key, and Epic issue type name, leave empty to have no JIRA integration setup') + msg = 'JIRA Project needs a JIRA Instance, JIRA Project Key, and Epic issue type name, leave empty to have no JIRA integration setup' + raise ValidationError(msg) class GITHUBFindingForm(forms.Form): @@ -2855,7 +2869,8 @@ def __init__(self, *args, **kwargs): self.finding_form = kwargs.pop('finding_form', None) if self.instance is None and self.jira_project is None: - raise ValueError('either and finding instance or jira_project is needed') + msg = 'either and finding instance or jira_project is needed' + raise ValueError(msg) super().__init__(*args, **kwargs) self.fields['push_to_jira'] = forms.BooleanField() @@ -3066,7 +3081,8 @@ def __init__(self, *args, **kwargs): self.question = kwargs.get('question') if not self.question: - raise ValueError('Need a question to render') + msg = 'Need a question to render' + raise ValueError(msg) del kwargs['question'] super().__init__(*args, **kwargs) @@ -3097,13 +3113,15 @@ def __init__(self, *args, **kwargs): def save(self): if not self.is_valid(): - raise forms.ValidationError('form is not valid') + msg = 'form is not valid' + raise forms.ValidationError(msg) answer = self.cleaned_data.get('answer') if not answer: if self.fields['answer'].required: - raise forms.ValidationError('Required') + msg = 'Required' + raise forms.ValidationError(msg) return text_answer, created = TextAnswer.objects.get_or_create( @@ -3173,13 +3191,15 @@ def clean_answer(self): def save(self): if not self.is_valid(): - raise forms.ValidationError('Form is not valid') + msg = 'Form is not valid' + raise forms.ValidationError(msg) real_answer = self.cleaned_data.get('answer') if not real_answer: if self.fields['answer'].required: - raise forms.ValidationError('Required') + msg = 'Required' + raise forms.ValidationError(msg) return choices = Choice.objects.filter(id__in=real_answer) @@ -3242,11 +3262,14 @@ def clean_expiration(self): if expiration: today = datetime.today().date() if expiration < today: - raise forms.ValidationError("The expiration cannot be in the past") + msg = "The expiration cannot be in the past" + raise forms.ValidationError(msg) elif expiration.day == today.day: - raise forms.ValidationError("The expiration cannot be today") + msg = "The expiration cannot be today" + raise forms.ValidationError(msg) else: - raise forms.ValidationError("An expiration for the survey must be supplied") + msg = "An expiration for the survey must be supplied" + raise forms.ValidationError(msg) return expiration @@ -3462,7 +3485,8 @@ def set_permission(self, codename): elif self.group: self.group.auth_group.permissions.add(self.permissions[codename]) else: - raise Exception('Neither user or group are set') + msg = 'Neither user or group are set' + raise Exception(msg) else: # Checkbox is unset if self.user: @@ -3470,4 +3494,5 @@ def set_permission(self, codename): elif self.group: self.group.auth_group.permissions.remove(self.permissions[codename]) else: - raise Exception('Neither user or group are set') + msg = 'Neither user or group are set' + raise Exception(msg) diff --git a/dojo/group/utils.py b/dojo/group/utils.py index be7f5ea1d6..bf46fc7150 100644 --- a/dojo/group/utils.py +++ b/dojo/group/utils.py @@ -8,7 +8,8 @@ def get_auth_group_name(group, attempt=0): if attempt > 999: - raise Exception(f'Cannot find name for authorization group for Dojo_Group {group.name}, aborted after 999 attempts.') + msg = f'Cannot find name for authorization group for Dojo_Group {group.name}, aborted after 999 attempts.' + raise Exception(msg) if attempt == 0: auth_group_name = group.name else: diff --git a/dojo/importers/importer/importer.py b/dojo/importers/importer/importer.py index d89a41f0cd..c2d55d5f30 100644 --- a/dojo/importers/importer/importer.py +++ b/dojo/importers/importer/importer.py @@ -275,7 +275,8 @@ def import_scan(self, scan, scan_type, engagement, lead, environment, active=Non now = timezone.now() if api_scan_configuration and api_scan_configuration.product != engagement.product: - raise ValidationError('API Scan Configuration has to be from same product as the Engagement') + msg = 'API Scan Configuration has to be from same product as the Engagement' + raise ValidationError(msg) # check if the parser that handle the scan_type manage tests # if yes, we parse the data first diff --git a/dojo/importers/reimporter/reimporter.py b/dojo/importers/reimporter/reimporter.py index dac0c8e8e4..8061123aaf 100644 --- a/dojo/importers/reimporter/reimporter.py +++ b/dojo/importers/reimporter/reimporter.py @@ -582,9 +582,8 @@ def reimport_scan( if api_scan_configuration: if api_scan_configuration.product != test.engagement.product: - raise ValidationError( - "API Scan Configuration has to be from same product as the Test" - ) + msg = "API Scan Configuration has to be from same product as the Test" + raise ValidationError(msg) if test.api_scan_configuration != api_scan_configuration: test.api_scan_configuration = api_scan_configuration test.save() diff --git a/dojo/importers/reimporter/utils.py b/dojo/importers/reimporter/utils.py index 5347fbf67f..8f332150aa 100644 --- a/dojo/importers/reimporter/utils.py +++ b/dojo/importers/reimporter/utils.py @@ -209,7 +209,8 @@ def get_or_create_product(product_name=None, product_type_name=None, auto_create # not found .... create it if not auto_create_context: - raise ValueError('auto_create_context not True, unable to create non-existing product') + msg = 'auto_create_context not True, unable to create non-existing product' + raise ValueError(msg) else: product_type, created = Product_Type.objects.get_or_create(name=product_type_name) if created: @@ -240,12 +241,14 @@ def get_or_create_engagement(engagement_id=None, engagement_name=None, product_n # not found .... create it if not auto_create_context: - raise ValueError('auto_create_context not True, unable to create non-existing engagement') + msg = 'auto_create_context not True, unable to create non-existing engagement' + raise ValueError(msg) else: product = get_or_create_product(product_name, product_type_name, auto_create_context) if not product: - raise ValueError('no product, unable to create engagement') + msg = 'no product, unable to create engagement' + raise ValueError(msg) target_start = timezone.now().date() if (target_end is None) or (target_start > target_end): diff --git a/dojo/importers/utils.py b/dojo/importers/utils.py index 5788b5fcf4..7f5fb5fcc7 100644 --- a/dojo/importers/utils.py +++ b/dojo/importers/utils.py @@ -155,8 +155,9 @@ def add_endpoints_to_unsaved_finding(finding, test, endpoints, **kwargs): fragment=endpoint.fragment, product=test.engagement.product) except (MultipleObjectsReturned): - raise Exception("Endpoints in your database are broken. Please access {} and migrate them to new format or " - "remove them.".format(reverse('endpoint_migrate'))) + msg = "Endpoints in your database are broken. Please access {} and migrate them to new format or " \ + "remove them.".format(reverse('endpoint_migrate')) + raise Exception(msg) _eps, _created = Endpoint_Status.objects.get_or_create( finding=finding, diff --git a/dojo/jira_link/helper.py b/dojo/jira_link/helper.py index eb2b1c3adf..4862501356 100644 --- a/dojo/jira_link/helper.py +++ b/dojo/jira_link/helper.py @@ -604,7 +604,8 @@ def jira_environment(obj): def push_to_jira(obj, *args, **kwargs): if obj is None: - raise ValueError('Cannot push None to JIRA') + msg = 'Cannot push None to JIRA' + raise ValueError(msg) if isinstance(obj, Finding): finding = obj @@ -1082,12 +1083,14 @@ def get_issuetype_fields( try: project = meta['projects'][0] except Exception: - raise JIRAError("Project misconfigured or no permissions in Jira ?") + msg = "Project misconfigured or no permissions in Jira ?" + raise JIRAError(msg) try: issuetype_fields = project['issuetypes'][0]['fields'].keys() except Exception: - raise JIRAError("Misconfigured default issue type ?") + msg = "Misconfigured default issue type ?" + raise JIRAError(msg) else: try: @@ -1103,7 +1106,8 @@ def get_issuetype_fields( break if not issuetype_id: - raise JIRAError("Issue type ID can not be matched. Misconfigured default issue type ?") + msg = "Issue type ID can not be matched. Misconfigured default issue type ?" + raise JIRAError(msg) try: issuetype_fields = jira.project_issue_fields(project_key, issuetype_id) @@ -1114,7 +1118,8 @@ def get_issuetype_fields( try: issuetype_fields = [f.fieldId for f in issuetype_fields] except Exception: - raise JIRAError("Misconfigured default issue type ?") + msg = "Misconfigured default issue type ?" + raise JIRAError(msg) except JIRAError as e: e.text = f"Failed retrieving field metadata from Jira version: {jira._version}, project: {project_key}, issue type: {issuetype_name}. {e.text}" @@ -1468,7 +1473,8 @@ def process_jira_project_form(request, instance=None, target=None, product=None, logger.debug('inheriting but no existing JIRA Project for engagement, so nothing to do') else: error = True - raise ValueError('Not allowed to remove existing JIRA Config for an engagement') + msg = 'Not allowed to remove existing JIRA Config for an engagement' + raise ValueError(msg) elif jform.is_valid(): try: jira_project = jform.save(commit=False) @@ -1481,7 +1487,8 @@ def process_jira_project_form(request, instance=None, target=None, product=None, obj = product if not jira_project.product_id and not jira_project.engagement_id: - raise ValueError('encountered JIRA_Project without product_id and without engagement_id') + msg = 'encountered JIRA_Project without product_id and without engagement_id' + raise ValueError(msg) # only check jira project if form is sufficiently populated if jira_project.jira_instance and jira_project.project_key: diff --git a/dojo/management/commands/import_github_languages.py b/dojo/management/commands/import_github_languages.py index bed838e9f6..8dbaf866eb 100644 --- a/dojo/management/commands/import_github_languages.py +++ b/dojo/management/commands/import_github_languages.py @@ -21,7 +21,8 @@ def handle(self, *args, **options): try: deserialized = json.loads(requests.get('https://raw.githubusercontent.com/ozh/github-colors/master/colors.json').text) except: - raise Exception("Invalid format") + msg = "Invalid format" + raise Exception(msg) new_language_types = 0 diff --git a/dojo/models.py b/dojo/models.py index 6d18e724a4..d7bac77823 100644 --- a/dojo/models.py +++ b/dojo/models.py @@ -860,9 +860,11 @@ def clean(self): ids_count += 1 if ids_count == 0: - raise ValidationError('Metadata entries need either a product, an endpoint or a finding') + msg = 'Metadata entries need either a product, an endpoint or a finding' + raise ValidationError(msg) if ids_count > 1: - raise ValidationError('Metadata entries may not have more than one relation, either a product, an endpoint either or a finding') + msg = 'Metadata entries may not have more than one relation, either a product, an endpoint either or a finding' + raise ValidationError(msg) def __str__(self): return f"{self.name}: {self.value}" @@ -893,7 +895,8 @@ def clean(self): for sla_day in sla_days: if sla_day < 1: - raise ValidationError('SLA Days must be at least 1') + msg = 'SLA Days must be at least 1' + raise ValidationError(msg) def save(self, *args, **kwargs): # get the initial sla config before saving (if this is an existing sla config) @@ -947,7 +950,8 @@ def delete(self, *args, **kwargs): if self.id != 1: super().delete(*args, **kwargs) else: - raise ValidationError("Unable to delete default SLA Configuration") + msg = "Unable to delete default SLA Configuration" + raise ValidationError(msg) def get_summary(self): return f'{self.name} - Critical: {self.critical}, High: {self.high}, Medium: {self.medium}, Low: {self.low}' @@ -1723,10 +1727,12 @@ def __str__(self): if clean_url[:len(dummy_scheme) + 3] == (dummy_scheme + '://'): clean_url = clean_url[len(dummy_scheme) + 3:] else: - raise ValueError('hyperlink lib did not create URL as was expected') + msg = 'hyperlink lib did not create URL as was expected' + raise ValueError(msg) return clean_url else: - raise ValueError('Missing host') + msg = 'Missing host' + raise ValueError(msg) except: url = '' if self.protocol: @@ -1913,7 +1919,8 @@ def from_uri(uri): from urllib.parse import urlparse url = hyperlink.parse(url="//" + urlparse(uri).netloc) except hyperlink.URLParseError as e: - raise ValidationError(f'Invalid URL format: {e}') + msg = f'Invalid URL format: {e}' + raise ValidationError(msg) query_parts = [] # inspired by https://github.com/python-hyper/hyperlink/blob/b8c9152cd826bbe8e6cc125648f3738235019705/src/hyperlink/_url.py#L1768 for k, v in url.query: @@ -3900,7 +3907,8 @@ class JIRA_Project(models.Model): def clean(self): if not self.jira_instance: - raise ValidationError('Cannot save JIRA Project Configuration without JIRA Instance') + msg = 'Cannot save JIRA Project Configuration without JIRA Instance' + raise ValidationError(msg) def __str__(self): return ('%s: ' + self.project_key + '(%s)') % (str(self.id), str(self.jira_instance.url) if self.jira_instance else 'None') diff --git a/dojo/object/views.py b/dojo/object/views.py index ec2b1f7b45..20be866c1a 100644 --- a/dojo/object/views.py +++ b/dojo/object/views.py @@ -58,7 +58,8 @@ def edit_object(request, pid, ttid): object = Objects_Product.objects.get(pk=ttid) product = get_object_or_404(Product, id=pid) if object.product != product: - raise BadRequest(f'Product {pid} does not fit to product of Object {object.product.id}') + msg = f'Product {pid} does not fit to product of Object {object.product.id}' + raise BadRequest(msg) if request.method == 'POST': tform = ObjectSettingsForm(request.POST, instance=object) @@ -87,7 +88,8 @@ def delete_object(request, pid, ttid): object = Objects_Product.objects.get(pk=ttid) product = get_object_or_404(Product, id=pid) if object.product != product: - raise BadRequest(f'Product {pid} does not fit to product of Object {object.product.id}') + msg = f'Product {pid} does not fit to product of Object {object.product.id}' + raise BadRequest(msg) if request.method == 'POST': tform = ObjectSettingsForm(request.POST, instance=object) diff --git a/dojo/product/views.py b/dojo/product/views.py index 55362b5f18..85b6bf2768 100644 --- a/dojo/product/views.py +++ b/dojo/product/views.py @@ -293,7 +293,8 @@ def identify_view(request): # although any XSS should be catch by django autoescape, we see people sometimes using '|safe'... if view in ['Endpoint', 'Finding']: return view - raise ValueError('invalid view, view must be "Endpoint" or "Finding"') + msg = 'invalid view, view must be "Endpoint" or "Finding"' + raise ValueError(msg) else: if get_data.get('finding__severity', None): return 'Endpoint' diff --git a/dojo/reports/views.py b/dojo/reports/views.py index b6782a317b..8f071ec0f7 100644 --- a/dojo/reports/views.py +++ b/dojo/reports/views.py @@ -362,9 +362,11 @@ def generate_report(request, obj, host_view=False): pass else: if obj is None: - raise Exception('No object is given to generate report for') + msg = 'No object is given to generate report for' + raise Exception(msg) else: - raise Exception(f'Report cannot be generated for object of type {type(obj).__name__}') + msg = f'Report cannot be generated for object of type {type(obj).__name__}' + raise Exception(msg) report_format = request.GET.get('report_type', 'AsciiDoc') include_finding_notes = int(request.GET.get('include_finding_notes', 0)) @@ -684,7 +686,8 @@ def get_list_index(list, index): def get_findings(request): url = request.META.get('QUERY_STRING') if not url: - raise Http404('Please use the report button when viewing findings') + msg = 'Please use the report button when viewing findings' + raise Http404(msg) else: if url.startswith('url='): url = url[4:] diff --git a/dojo/reports/widgets.py b/dojo/reports/widgets.py index 46ad101616..6d0ca15656 100644 --- a/dojo/reports/widgets.py +++ b/dojo/reports/widgets.py @@ -30,7 +30,8 @@ def clean_json(self): try: json.loads(jdata) except: - raise forms.ValidationError("Invalid data in json") + msg = "Invalid data in json" + raise forms.ValidationError(msg) return jdata @@ -255,7 +256,8 @@ def __init__(self, *args, **kwargs): if 'findings' in kwargs: self.findings = kwargs.get('findings') else: - raise Exception("Need to instantiate with finding queryset.") + msg = "Need to instantiate with finding queryset." + raise Exception(msg) if 'finding_notes' in kwargs: self.finding_notes = kwargs.get('finding_notes') @@ -330,7 +332,8 @@ def __init__(self, *args, **kwargs): if 'endpoints' in kwargs: self.endpoints = kwargs.get('endpoints') else: - raise Exception("Need to instantiate with endpoint queryset.") + msg = "Need to instantiate with endpoint queryset." + raise Exception(msg) if 'finding_notes' in kwargs: self.finding_notes = kwargs.get('finding_notes') diff --git a/dojo/tool_product/views.py b/dojo/tool_product/views.py index fd3c475750..b4ae55a2ad 100644 --- a/dojo/tool_product/views.py +++ b/dojo/tool_product/views.py @@ -61,7 +61,8 @@ def edit_tool_product(request, pid, ttid): product = get_object_or_404(Product, id=pid) tool_product = Tool_Product_Settings.objects.get(pk=ttid) if tool_product.product != product: - raise BadRequest(f'Product {pid} does not fit to product of Tool_Product {tool_product.product.id}') + msg = f'Product {pid} does not fit to product of Tool_Product {tool_product.product.id}' + raise BadRequest(msg) if request.method == 'POST': tform = ToolProductSettingsForm(request.POST, instance=tool_product) @@ -88,7 +89,8 @@ def delete_tool_product(request, pid, ttid): tool_product = Tool_Product_Settings.objects.get(pk=ttid) product = get_object_or_404(Product, id=pid) if tool_product.product != product: - raise BadRequest(f'Product {pid} does not fit to product of Tool_Product {tool_product.product.id}') + msg = f'Product {pid} does not fit to product of Tool_Product {tool_product.product.id}' + raise BadRequest(msg) if request.method == 'POST': DeleteToolProductSettingsForm(request.POST, instance=tool_product) diff --git a/dojo/tools/anchore_enterprise/parser.py b/dojo/tools/anchore_enterprise/parser.py index 0ba332d696..03e7cc1ee8 100644 --- a/dojo/tools/anchore_enterprise/parser.py +++ b/dojo/tools/anchore_enterprise/parser.py @@ -83,9 +83,8 @@ def get_findings(self, filename, test): ] items.append(find) except (KeyError, IndexError) as err: - raise ValueError( - f"Invalid format: {err} key not found" - ) + msg = f"Invalid format: {err} key not found" + raise ValueError(msg) except AttributeError as err: # import empty policies without error (e.g. policies or images # objects are not a dictionary) diff --git a/dojo/tools/anchorectl_policies/parser.py b/dojo/tools/anchorectl_policies/parser.py index e02d169be2..1e31b08e68 100644 --- a/dojo/tools/anchorectl_policies/parser.py +++ b/dojo/tools/anchorectl_policies/parser.py @@ -66,9 +66,8 @@ def get_findings(self, filename, test): find.unsaved_vulnerability_ids = [vulnerability_id] items.append(find) except (KeyError, IndexError) as err: - raise ValueError( - f"Invalid format: {err} key not found" - ) + msg = f"Invalid format: {err} key not found" + raise ValueError(msg) except AttributeError as err: # import empty policies without error (e.g. policies or images # objects are not a dictionary) diff --git a/dojo/tools/api_blackduck/api_client.py b/dojo/tools/api_blackduck/api_client.py index a2895dc5be..6d5342d580 100644 --- a/dojo/tools/api_blackduck/api_client.py +++ b/dojo/tools/api_blackduck/api_client.py @@ -16,9 +16,8 @@ def __init__(self, tool_config): timeout=120, ) else: - raise ValueError( - f"Authentication type {tool_config.authentication_type} not supported" - ) + msg = f"Authentication type {tool_config.authentication_type} not supported" + raise ValueError(msg) # TODO # def test_connection(self): diff --git a/dojo/tools/api_blackduck/importer.py b/dojo/tools/api_blackduck/importer.py index af0917a0e5..f84f3e6166 100644 --- a/dojo/tools/api_blackduck/importer.py +++ b/dojo/tools/api_blackduck/importer.py @@ -23,10 +23,11 @@ def prepare_client(self, test): config = test.api_scan_configuration # Double check of config if config.product != product: - raise ValidationError( + msg = ( f'API Scan Configuration for "{self.config_id}" and Product do not match. ' f'Product: "{product.name}" ({product.id}), config.product: "{config.product.name}" ({config.product.id})' ) + raise ValidationError(msg) else: configs = Product_API_Scan_Configuration.objects.filter( product=product, @@ -35,17 +36,19 @@ def prepare_client(self, test): if configs.count() == 1: config = configs.first() elif configs.count() > 1: - raise ValidationError( + msg = ( "More than one Product API Scan Configuration has been configured, but none of them has been " "chosen. Please specify at Test which one should be used. " f'Product: "{product.name}" ({product.id})' ) + raise ValidationError(msg) else: - raise ValidationError( + msg = ( "There are no API Scan Configurations for this Product. Please add at least one API Scan " f'Configuration for "{self.config_id}" to this Product. ' f'Product: "{product.name}" ({product.id})' ) + raise ValidationError(msg) tool_config = config.tool_configuration return BlackduckAPI(tool_config), config diff --git a/dojo/tools/api_bugcrowd/api_client.py b/dojo/tools/api_bugcrowd/api_client.py index ad72f9174e..933378724d 100644 --- a/dojo/tools/api_bugcrowd/api_client.py +++ b/dojo/tools/api_bugcrowd/api_client.py @@ -23,9 +23,8 @@ def __init__(self, tool_config): ) self.session.headers.update(self.default_headers) else: - raise Exception( - f"bugcrowd Authentication type {tool_config.authentication_type} not supported" - ) + msg = f"bugcrowd Authentication type {tool_config.authentication_type} not supported" + raise Exception(msg) def get_findings(self, program, target): """ @@ -113,15 +112,17 @@ def test_connection(self): f'You also have targets "{target_names}" that can be used in Service key 2' ) else: - raise Exception( + msg = ( "Bugcrowd API test not successful, no targets were defined in Bugcrowd which is used for " f"filtering, check your configuration, HTTP response was: {response_targets.text}" ) + raise Exception(msg) else: - raise Exception( + msg = ( "Bugcrowd API test not successful, could not retrieve the programs or submissions, check your " f"configuration, HTTP response for programs was: {response_programs.text}, HTTP response for submissions was: {response_subs.text}" ) + raise Exception(msg) def test_product_connection(self, api_scan_configuration): submissions = [] diff --git a/dojo/tools/api_bugcrowd/importer.py b/dojo/tools/api_bugcrowd/importer.py index 56b7ca1a22..f49ffb1bee 100644 --- a/dojo/tools/api_bugcrowd/importer.py +++ b/dojo/tools/api_bugcrowd/importer.py @@ -37,10 +37,11 @@ def prepare_client(self, test): config = test.api_scan_configuration # Double check of config if config.product != product: - raise ValidationError( + msg = ( "API Scan Configuration for Bugcrowd API and Product do not match. " f'Product: "{product.name}" ({product.id}), config.product: "{config.product.name}" ({config.product.id})' ) + raise ValidationError(msg) else: configs = Product_API_Scan_Configuration.objects.filter( product=product, @@ -49,17 +50,19 @@ def prepare_client(self, test): if configs.count() == 1: config = configs.first() elif configs.count() > 1: - raise ValidationError( + msg = ( "More than one Product API Scan Configuration has been configured, but none of them has been " "chosen. Please specify at Test which one should be used. " f'Product: "{product.name}" ({product.id})' ) + raise ValidationError(msg) else: - raise ValidationError( + msg = ( "There are no API Scan Configurations for this Product. " "Please add at least one API Scan Configuration for bugcrowd to this Product. " f'Product: "{product.name}" ({product.id})' ) + raise ValidationError(msg) tool_config = config.tool_configuration return BugcrowdAPI(tool_config), config diff --git a/dojo/tools/api_bugcrowd/parser.py b/dojo/tools/api_bugcrowd/parser.py index df119ed576..173357f182 100644 --- a/dojo/tools/api_bugcrowd/parser.py +++ b/dojo/tools/api_bugcrowd/parser.py @@ -198,11 +198,12 @@ def include_finding(self, entry): if entry["attributes"]["state"] in allowed_states: return True else: - raise ValueError( + msg = ( "{} not in allowed bugcrowd submission states".format( entry["attributes"]["state"] ) ) + raise ValueError(msg) def convert_log_timestamp(self, timestamp): """Convert a log entry's timestamp to a DefectDojo date""" diff --git a/dojo/tools/api_cobalt/api_client.py b/dojo/tools/api_cobalt/api_client.py index e18ed6f01f..36f37d734d 100644 --- a/dojo/tools/api_cobalt/api_client.py +++ b/dojo/tools/api_cobalt/api_client.py @@ -14,9 +14,8 @@ def __init__(self, tool_config): self.api_token = tool_config.api_key self.org_token = tool_config.extras else: - raise Exception( - f"Cobalt.io Authentication type {tool_config.authentication_type} not supported" - ) + msg = f"Cobalt.io Authentication type {tool_config.authentication_type} not supported" + raise Exception(msg) def get_asset(self, asset_id): """ @@ -30,7 +29,8 @@ def get_asset(self, asset_id): if asset["resource"]["id"] == asset_id: return asset - raise Exception(f"Asset {asset_id} not found in organisation") + msg = f"Asset {asset_id} not found in organisation" + raise Exception(msg) def get_assets(self): """Returns all org assets""" @@ -42,11 +42,12 @@ def get_assets(self): if response.ok: return response.json().get("data") else: - raise Exception( + msg = ( "Unable to get assets due to {} - {}".format( response.status_code, response.content.decode("utf-8") ) ) + raise Exception(msg) def get_findings(self, asset_id): """ @@ -62,11 +63,12 @@ def get_findings(self, asset_id): if response.ok: return response.json() else: - raise Exception( + msg = ( "Unable to get asset findings due to {} - {}".format( response.status_code, response.content.decode("utf-8") ) ) + raise Exception(msg) def test_connection(self): # Request orgs for the org name @@ -90,12 +92,13 @@ def test_connection(self): org_name = org["resource"]["name"] return f'You have access to the "{org_name}" organization' else: - raise Exception( + msg = ( "Connection failed (error: {} - {})".format( response_assets.status_code, response_assets.content.decode("utf-8"), ) ) + raise Exception(msg) def test_product_connection(self, api_scan_configuration): asset = self.get_asset(api_scan_configuration.service_key_1) diff --git a/dojo/tools/api_cobalt/importer.py b/dojo/tools/api_cobalt/importer.py index 9f3a291f4a..d1296bd4ef 100644 --- a/dojo/tools/api_cobalt/importer.py +++ b/dojo/tools/api_cobalt/importer.py @@ -22,10 +22,11 @@ def prepare_client(self, test): config = test.api_scan_configuration # Double check of config if config.product != product: - raise ValidationError( + msg = ( "API Scan Configuration for Cobalt.io and Product do not match. " f'Product: "{product.name}" ({product.id}), config.product: "{config.product.name}" ({config.product.id})' ) + raise ValidationError(msg) else: configs = Product_API_Scan_Configuration.objects.filter( product=product, @@ -34,17 +35,19 @@ def prepare_client(self, test): if configs.count() == 1: config = configs.first() elif configs.count() > 1: - raise ValidationError( + msg = ( "More than one Product API Scan Configuration has been configured, but none of them has been " "chosen. Please specify at Test which one should be used. " f'Product: "{product.name}" ({product.id})' ) + raise ValidationError(msg) else: - raise ValidationError( + msg = ( "There are no API Scan Configurations for this Product. Please add at least one API Scan " "Configuration for Cobalt.io to this Product. " f'Product: "{product.name}" ({product.id})' ) + raise ValidationError(msg) tool_config = config.tool_configuration return CobaltAPI(tool_config), config diff --git a/dojo/tools/api_edgescan/api_client.py b/dojo/tools/api_edgescan/api_client.py index a49c7686eb..89510721b9 100644 --- a/dojo/tools/api_edgescan/api_client.py +++ b/dojo/tools/api_edgescan/api_client.py @@ -16,9 +16,8 @@ def __init__(self, tool_config): self.url = tool_config.url or self.DEFAULT_URL self.options = self.get_extra_options(tool_config) else: - raise Exception( - f"Edgescan Authentication type {tool_config.authentication_type} not supported" - ) + msg = f"Edgescan Authentication type {tool_config.authentication_type} not supported" + raise Exception(msg) @staticmethod def get_extra_options(tool_config): @@ -26,7 +25,8 @@ def get_extra_options(tool_config): try: return json.loads(tool_config.extras) except (JSONDecodeError, TypeError): - raise ValueError("JSON not provided in Extras field.") + msg = "JSON not provided in Extras field." + raise ValueError(msg) def get_findings(self, asset_ids): if asset_ids: diff --git a/dojo/tools/api_edgescan/importer.py b/dojo/tools/api_edgescan/importer.py index 5857b188ab..a5e7c3301d 100644 --- a/dojo/tools/api_edgescan/importer.py +++ b/dojo/tools/api_edgescan/importer.py @@ -18,10 +18,11 @@ def prepare_client(self, test): if test.api_scan_configuration: config = test.api_scan_configuration if config.product != product: - raise ValidationError( + msg = ( "API Scan Configuration for Edgescan and Product do not match. " f'Product: "{product.name}" ({product.id}), config.product: "{config.product.name}" ({config.product.id})' ) + raise ValidationError(msg) else: configs = Product_API_Scan_Configuration.objects.filter( product=product @@ -29,17 +30,19 @@ def prepare_client(self, test): if configs.count() == 1: config = configs.first() elif configs.count() > 1: - raise ValidationError( + msg = ( "More than one Product API Scan Configuration has been configured, but none of them has been " "chosen.\nPlease specify at Test which one should be used. " f'Product: "{product.name}" ({product.id})' ) + raise ValidationError(msg) else: - raise ValidationError( + msg = ( "There are no API Scan Configurations for this Product.\n" "Please add at least one API Scan Configuration for Edgescan to this Product. " f'Product: "{product.name}" ({product.id})' ) + raise ValidationError(msg) tool_config = config.tool_configuration return EdgescanAPI(tool_config), config diff --git a/dojo/tools/api_sonarqube/api_client.py b/dojo/tools/api_sonarqube/api_client.py index 67f08eee22..1e26ebad9d 100644 --- a/dojo/tools/api_sonarqube/api_client.py +++ b/dojo/tools/api_sonarqube/api_client.py @@ -38,9 +38,8 @@ def __init__(self, tool_config): entry in supported_issue_types for entry in split_issue_types ) if not all_clean: - raise Exception( - f"Deteced unsupported issue type! Supported types are {', '.join(supported_issue_types)}" - ) + msg = f"Detected unsupported issue type! Supported types are {', '.join(supported_issue_types)}" + raise Exception(msg) self.session = requests.Session() self.default_headers = {"User-Agent": "DefectDojo"} @@ -53,9 +52,8 @@ def __init__(self, tool_config): elif tool_config.authentication_type == "API": self.session.auth = (tool_config.api_key, "") else: - raise Exception( - f"SonarQube Authentication type {tool_config.authentication_type} not supported" - ) + msg = f"SonarQube Authentication type {tool_config.authentication_type} not supported" + raise Exception(msg) def find_project(self, project_name, organization=None, branch=None): """ @@ -80,15 +78,16 @@ def find_project(self, project_name, organization=None, branch=None): ) if not response.ok: - raise Exception( + msg = ( f"Unable to find the project {project_name} " f'due to {response.status_code} - {response.content.decode("utf-8")}' ) + raise Exception(msg) for component in response.json().get("components", []): if component["name"] == project_name: return component - raise Exception( + msg = ( f""" 'Expected Project "{project_name}", but it returned ' '{[x.get('name') for x in response.json().get('components')]}. \n' @@ -96,6 +95,7 @@ def find_project(self, project_name, organization=None, branch=None): 'Alternatively it can also be specified the Project Key at Product configuration. """ ) + raise Exception(msg) def get_project(self, project_key, organization=None, branch=None): """ @@ -123,10 +123,11 @@ def get_project(self, project_key, organization=None, branch=None): ) if not response.ok: - raise Exception( + msg = ( f"Unable to find the project {project_key} " f'due to {response.status_code} - {response.content.decode("utf-8")}' ) + raise Exception(msg) return response.json().get("component") @@ -176,10 +177,11 @@ def find_issues( ) if not response.ok: - raise Exception( + msg = ( f"Unable to find the issues for component {component_key} " f'due to {response.status_code} - {response.content.decode("utf-8")}' ) + raise Exception(msg) issues_page = response.json().get("issues") if not issues_page: @@ -217,10 +219,11 @@ def find_hotspots(self, project_key, organization=None, branch=None): ) if not response.ok: - raise Exception( + msg = ( f"Unable to find the hotspots for project {project_key} " f"due to {response.status_code} - {response.content}" ) + raise Exception(msg) hotspots_page = response.json().get("hotspots") if not hotspots_page: @@ -251,21 +254,23 @@ def get_issue(self, issue_key): ) if not response.ok: - raise Exception( + msg = ( f"Unable to get issue {issue_key} " f'due to {response.status_code} - {response.content.decode("utf-8")}' ) + raise Exception(msg) issues = response.json().get("issues", []) for issue in issues: if issue["key"] == issue_key: return issue - raise Exception( + msg = ( f"Expected Issue \"{issue_key}\", but it returned" f"{[x.get('key') for x in response.json().get('issues')]}. " "Full response: " f"{response.json()}" ) + raise Exception(msg) def get_rule(self, rule_id, organization=None): """ @@ -288,10 +293,11 @@ def get_rule(self, rule_id, organization=None): headers=self.default_headers, ) if not response.ok: - raise Exception( + msg = ( f"Unable to get the rule {rule_id} " f'due to {response.status_code} - {response.content.decode("utf-8")}' ) + raise Exception(msg) rule = response.json()["rule"] self.rules_cache.update({rule_id: rule}) @@ -311,10 +317,11 @@ def get_hotspot_rule(self, rule_id): headers=self.default_headers, ) if not response.ok: - raise Exception( + msg = ( f"Unable to get the hotspot rule {rule_id} " f"due to {response.status_code} - {response.content}" ) + raise Exception(msg) rule = response.json()["rule"] self.rules_cache.update({rule_id: rule}) @@ -354,10 +361,11 @@ def transition_issue(self, issue_key, transition): ) if not response.ok: - raise Exception( + msg = ( f"Unable to transition {transition} the issue {issue_key} " f'due to {response.status_code} - {response.content.decode("utf-8")}' ) + raise Exception(msg) def add_comment(self, issue_key, text): """ @@ -373,10 +381,11 @@ def add_comment(self, issue_key, text): headers=self.default_headers, ) if not response.ok: - raise Exception( + msg = ( f"Unable to add a comment into issue {issue_key} " f'due to {response.status_code} - {response.content.decode("utf-8")}' ) + raise Exception(msg) def test_connection(self): """ @@ -394,20 +403,22 @@ def test_connection(self): ) if not response.ok: - raise Exception( + msg = ( f"Unable to connect and search in SonarQube " f'due to {response.status_code} - {response.content.decode("utf-8")}' ) + raise Exception(msg) try: num_projects = response.json()["paging"]["total"] except RequestsJSONDecodeError: - raise Exception( + msg = ( f""" Test request was successful (there was no HTTP-4xx or HTTP-5xx) but response doesn't contain expected JSON response. SonarQube responded with HTTP-{response.status_code} ({response.reason}). This is full response: {response.text} """ ) + raise Exception(msg) return f"You have access to {num_projects} projects" def test_product_connection(self, api_scan_configuration): diff --git a/dojo/tools/api_sonarqube/importer.py b/dojo/tools/api_sonarqube/importer.py index 6d4d1577f5..b0ebe9e3db 100644 --- a/dojo/tools/api_sonarqube/importer.py +++ b/dojo/tools/api_sonarqube/importer.py @@ -61,10 +61,11 @@ def prepare_client(test): ) # https://github.com/DefectDojo/django-DefectDojo/pull/4676 case no. 7 and 8 # Double check of config if config.product != product: - raise ValidationError( + msg = ( "Product API Scan Configuration and Product do not match. " f'Product: "{product.name}" ({product.id}), config.product: "{config.product.name}" ({config.product.id})' ) + raise ValidationError(msg) else: sqqs = product.product_api_scan_configuration_set.filter( product=product, @@ -77,19 +78,21 @@ def prepare_client(test): elif ( sqqs.count() > 1 ): # https://github.com/DefectDojo/django-DefectDojo/pull/4676 case no. 6 - raise ValidationError( + msg = ( "More than one Product API Scan Configuration has been configured, but none of them has been " "chosen. Please specify which one should be used. " f'Product: "{product.name}" ({product.id})' ) + raise ValidationError(msg) else: # We are not handling cases no. 1-3 anymore - # https://github.com/DefectDojo/django-DefectDojo/pull/4676 - raise ValidationError( + msg = ( "There are no API Scan Configurations for this Product.\n" "Please add at least one API Scan Configuration for SonarQube to this Product. " f'Product: "{product.name}" ({product.id})' ) + raise ValidationError(msg) return SonarQubeAPI(tool_config=config.tool_configuration), config diff --git a/dojo/tools/api_vulners/api_client.py b/dojo/tools/api_vulners/api_client.py index 9441fada34..0213e55e61 100644 --- a/dojo/tools/api_vulners/api_client.py +++ b/dojo/tools/api_vulners/api_client.py @@ -15,9 +15,8 @@ def __init__(self, tool_config): if tool_config.url: self.vulners_api_url = tool_config.url else: - raise Exception( - f"Vulners.com Authentication type {tool_config.authentication_type} not supported" - ) + msg = f"Vulners.com Authentication type {tool_config.authentication_type} not supported" + raise Exception(msg) def get_client(self): return vulners.VulnersApi( diff --git a/dojo/tools/api_vulners/importer.py b/dojo/tools/api_vulners/importer.py index 0017122f97..a0b543699c 100644 --- a/dojo/tools/api_vulners/importer.py +++ b/dojo/tools/api_vulners/importer.py @@ -27,10 +27,11 @@ def prepare_client(self, test): config = test.api_scan_configuration # Double check of config if config.product != product: - raise ValidationError( + msg = ( "API Scan Configuration for Vulners API and Product do not match. " f'Product: "{product.name}" ({product.id}), config.product: "{config.product.name}" ({config.product.id})' ) + raise ValidationError(msg) else: configs = Product_API_Scan_Configuration.objects.filter( product=product, tool_configuration__tool_type__name="Vulners" @@ -38,17 +39,19 @@ def prepare_client(self, test): if configs.count() == 1: config = configs.first() elif configs.count() > 1: - raise ValidationError( + msg = ( "More than one Product API Scan Configuration has been configured, but none of them has been " "chosen. Please specify at Test which one should be used. " f'Product: "{product.name}" ({product.id})' ) + raise ValidationError(msg) else: - raise ValidationError( + msg = ( "There are no API Scan Configurations for this Product. Please add at least one API Scan " "Configuration for Vulners to this Product. " f'Product: "{product.name}" ({product.id})' ) + raise ValidationError(msg) tool_config = config.tool_configuration return VulnersAPI(tool_config), config diff --git a/dojo/tools/appspider/parser.py b/dojo/tools/appspider/parser.py index 8cb0753f0c..bf9ed6eb41 100644 --- a/dojo/tools/appspider/parser.py +++ b/dojo/tools/appspider/parser.py @@ -24,10 +24,11 @@ def get_findings(self, filename, test): root = vscan.getroot() if "VulnSummary" not in str(root.tag): - raise ValueError( + msg = ( "Please ensure that you are uploading AppSpider's VulnerabilitiesSummary.xml file." "At this time it is the only file that is consumable by DefectDojo." ) + raise ValueError(msg) dupes = {} diff --git a/dojo/tools/auditjs/parser.py b/dojo/tools/auditjs/parser.py index 9cd6f8399d..73c3ca8ce0 100644 --- a/dojo/tools/auditjs/parser.py +++ b/dojo/tools/auditjs/parser.py @@ -36,9 +36,8 @@ def get_findings(self, filename, test): try: data = json.load(filename) except JSONDecodeError: - raise ValueError( - "Invalid JSON format. Are you sure you used --json option ?" - ) + msg = "Invalid JSON format. Are you sure you used --json option ?" + raise ValueError(msg) dupes = {} for dependency in data: @@ -84,10 +83,11 @@ def get_findings(self, filename, test): if cwe_find: cwe = int(cwe_find[0][4:]) else: - raise ValueError( + msg = ( "Missing mandatory attributes (id, title, description). Please check your report or ask " "community." ) + raise ValueError(msg) if "cvssScore" in vulnerability: cvss_score = vulnerability["cvssScore"] if "cvssVector" in vulnerability: diff --git a/dojo/tools/aws_prowler/parser.py b/dojo/tools/aws_prowler/parser.py index 9b92261c60..4a1ed7af91 100644 --- a/dojo/tools/aws_prowler/parser.py +++ b/dojo/tools/aws_prowler/parser.py @@ -26,7 +26,8 @@ def get_findings(self, file, test): elif file.name.lower().endswith(".json"): return self.process_json(file, test) else: - raise ValueError("Unknown file format") + msg = "Unknown file format" + raise ValueError(msg) def process_csv(self, file, test): content = file.read() diff --git a/dojo/tools/aws_prowler_v3/parser.py b/dojo/tools/aws_prowler_v3/parser.py index 2154141c1f..60f7a5dc7e 100644 --- a/dojo/tools/aws_prowler_v3/parser.py +++ b/dojo/tools/aws_prowler_v3/parser.py @@ -23,7 +23,8 @@ def get_findings(self, file, test): if file.name.lower().endswith('.json'): return self.process_json(file, test) else: - raise ValueError('Unknown file format') + msg = 'Unknown file format' + raise ValueError(msg) def process_json(self, file, test): dupes = {} diff --git a/dojo/tools/awssecurityhub/parser.py b/dojo/tools/awssecurityhub/parser.py index d7110c6daf..6cda17bb23 100644 --- a/dojo/tools/awssecurityhub/parser.py +++ b/dojo/tools/awssecurityhub/parser.py @@ -18,14 +18,16 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, filehandle, test): tree = json.load(filehandle) if not isinstance(tree, dict): - raise TypeError("Incorrect Security Hub report format") + msg = "Incorrect Security Hub report format" + raise TypeError(msg) return self.get_items(tree, test) def get_items(self, tree: dict, test): items = {} findings = tree.get("Findings", tree.get("findings", None)) if not isinstance(findings, list): - raise TypeError("Incorrect Security Hub report format") + msg = "Incorrect Security Hub report format" + raise TypeError(msg) for node in findings: aws_scanner_type = node.get("ProductFields", {}).get("aws/securityhub/ProductName", "") if aws_scanner_type == "Inspector": @@ -36,6 +38,7 @@ def get_items(self, tree: dict, test): item = Compliance().get_item(node, test) key = node["Id"] if not isinstance(key, str): - raise TypeError("Incorrect Security Hub report format") + msg = "Incorrect Security Hub report format" + raise TypeError(msg) items[key] = item return list(items.values()) diff --git a/dojo/tools/azure_security_center_recommendations/parser.py b/dojo/tools/azure_security_center_recommendations/parser.py index e2e9faf5eb..19dc794dab 100644 --- a/dojo/tools/azure_security_center_recommendations/parser.py +++ b/dojo/tools/azure_security_center_recommendations/parser.py @@ -22,7 +22,8 @@ def get_findings(self, file, test): if file.name.lower().endswith(".csv"): return self.process_csv(file, test) else: - raise ValueError("Unknown file format") + msg = "Unknown file format" + raise ValueError(msg) def process_csv(self, file, test): content = file.read() diff --git a/dojo/tools/blackduck_component_risk/importer.py b/dojo/tools/blackduck_component_risk/importer.py index 87f4160188..db10d823b7 100644 --- a/dojo/tools/blackduck_component_risk/importer.py +++ b/dojo/tools/blackduck_component_risk/importer.py @@ -30,7 +30,8 @@ def parse_findings(self, report: Path) -> (dict, dict, dict): if zipfile.is_zipfile(str(report)): return self._process_zipfile(report) else: - raise ValueError(f"File {report} not a zip!") + msg = f"File {report} not a zip!" + raise ValueError(msg) def _process_zipfile(self, report: Path) -> (dict, dict, dict): """ @@ -64,7 +65,8 @@ def _process_zipfile(self, report: Path) -> (dict, dict, dict): # Raise exception to error-out if the zip is missing either of # these files. if not (c_file and s_file): - raise Exception("Zip file missing needed files!") + msg = "Zip file missing needed files!" + raise Exception(msg) except Exception: logger.exception("Could not process zip file") diff --git a/dojo/tools/burp_api/parser.py b/dojo/tools/burp_api/parser.py index 97d8d40ef7..6063a41b59 100644 --- a/dojo/tools/burp_api/parser.py +++ b/dojo/tools/burp_api/parser.py @@ -117,9 +117,8 @@ def get_clean_base64(self, value): elif segment["type"] == "HighlightSegment": output += "\n\n------------------------------------------------------------------\n\n" else: - raise ValueError( - f"unknown segment type in Burp data {segment['type']}" - ) + msg = f"unknown segment type in Burp data {segment['type']}" + raise ValueError(msg) return output diff --git a/dojo/tools/burp_graphql/parser.py b/dojo/tools/burp_graphql/parser.py index 4f2cce8a24..4fc968c02b 100644 --- a/dojo/tools/burp_graphql/parser.py +++ b/dojo/tools/burp_graphql/parser.py @@ -23,7 +23,8 @@ def get_findings(self, filename, test): data = json.load(filename) if "Issues" not in data: - raise ValueError("No Issues found") + msg = "No Issues found" + raise ValueError(msg) return self.create_findings(data.get("Issues"), test) @@ -64,7 +65,8 @@ def parse_findings(self, scan_data): if not issue.get("issue_type") or not issue["issue_type"].get( "name" ): - raise ValueError("Issue does not have a name") + msg = "Issue does not have a name" + raise ValueError(msg) issue_name = issue["issue_type"]["name"] diff --git a/dojo/tools/checkmarx_osa/parser.py b/dojo/tools/checkmarx_osa/parser.py index c61ce2f868..ac3d14e033 100644 --- a/dojo/tools/checkmarx_osa/parser.py +++ b/dojo/tools/checkmarx_osa/parser.py @@ -27,7 +27,8 @@ def get_findings(self, filehandle, test): "Found %i elements", len(tree), ) - raise ValueError("Invalid format: bad structure") + msg = "Invalid format: bad structure" + raise ValueError(msg) libraries_dict = self.get_libraries(tree) vulnerabilities = self.get_vunlerabilities(tree) items = [] @@ -38,13 +39,11 @@ def get_findings(self, filehandle, test): library = libraries_dict[item["libraryId"]] self.check_mandatory(library, mandatory_library_fields) if "name" not in item["state"]: - raise ValueError( - "Invalid format: missing mandatory field state.name" - ) + msg = "Invalid format: missing mandatory field state.name" + raise ValueError(msg) if "name" not in item["severity"]: - raise ValueError( - "Invalid format: missing mandatory field severity.name" - ) + msg = "Invalid format: missing mandatory field severity.name" + raise ValueError(msg) # Possible status as per checkmarx 9.2: TO_VERIFY, NOT_EXPLOITABLE, # CONFIRMED, URGENT, PROPOSED_NOT_EXPLOITABLE diff --git a/dojo/tools/checkov/parser.py b/dojo/tools/checkov/parser.py index ad4878d389..5628e53576 100644 --- a/dojo/tools/checkov/parser.py +++ b/dojo/tools/checkov/parser.py @@ -41,7 +41,8 @@ def parse_json(self, json_output): except BaseException: deserialized = json.loads(data) except BaseException: - raise ValueError("Invalid format") + msg = "Invalid format" + raise ValueError(msg) return ( [deserialized] if not isinstance( diff --git a/dojo/tools/clair/parser.py b/dojo/tools/clair/parser.py index 592c7afae4..a87e46d5bb 100644 --- a/dojo/tools/clair/parser.py +++ b/dojo/tools/clair/parser.py @@ -37,5 +37,6 @@ def parse_json(self, json_output): self.scanner = "clairklar" subtree = tree.get("Vulnerabilities") except BaseException: - raise ValueError("Invalid format") + msg = "Invalid format" + raise ValueError(msg) return subtree diff --git a/dojo/tools/coverity_api/parser.py b/dojo/tools/coverity_api/parser.py index 8acba51e37..c3b15f573f 100644 --- a/dojo/tools/coverity_api/parser.py +++ b/dojo/tools/coverity_api/parser.py @@ -20,10 +20,8 @@ def get_findings(self, file, test): tree = json.load(file) if "viewContentsV1" not in tree: - raise ValueError( - "Report file is not a well-formed Coverity REST view report", - file.name, - ) + msg = "Report file is not a well-formed Coverity REST view report" + raise ValueError(msg, file.name) items = [] for issue in tree["viewContentsV1"]["rows"]: @@ -101,7 +99,8 @@ def convert_displayImpact(self, val): return "Medium" if "High" == val: return "High" - raise ValueError(f"Unknown value for Coverity displayImpact {val}") + msg = f"Unknown value for Coverity displayImpact {val}" + raise ValueError(msg) def convert_severity(self, val): if val is None: @@ -118,4 +117,5 @@ def convert_severity(self, val): return "Info" if "Various" == val: return "Info" - raise ValueError(f"Unknown value for Coverity severity {val}") + msg = f"Unknown value for Coverity severity {val}" + raise ValueError(msg) diff --git a/dojo/tools/crashtest_security/parser.py b/dojo/tools/crashtest_security/parser.py index b33273a2f9..8770013b79 100644 --- a/dojo/tools/crashtest_security/parser.py +++ b/dojo/tools/crashtest_security/parser.py @@ -247,4 +247,5 @@ def get_findings(self, filename, test): elif filename.name.lower().endswith(".json"): return CrashtestSecurityJsonParser().get_findings(filename, test) else: - raise ValueError("Unknown File Format") + msg = "Unknown File Format" + raise ValueError(msg) diff --git a/dojo/tools/crunch42/parser.py b/dojo/tools/crunch42/parser.py index fade8ddb42..8478132824 100644 --- a/dojo/tools/crunch42/parser.py +++ b/dojo/tools/crunch42/parser.py @@ -21,7 +21,8 @@ def parse_json(self, json_output): except Exception: tree = json.loads(data) except Exception: - raise ValueError("Invalid format") + msg = "Invalid format" + raise ValueError(msg) return tree diff --git a/dojo/tools/cyclonedx/xml_parser.py b/dojo/tools/cyclonedx/xml_parser.py index 81daf1b3cb..e0be085c0f 100644 --- a/dojo/tools/cyclonedx/xml_parser.py +++ b/dojo/tools/cyclonedx/xml_parser.py @@ -13,9 +13,8 @@ def _get_findings_xml(self, file, test): root = nscan.getroot() namespace = self.get_namespace(root) if not namespace.startswith("{http://cyclonedx.org/schema/bom/"): - raise ValueError( - f"This doesn't seem to be a valid CycloneDX BOM XML file. Namespace={namespace}" - ) + msg = f"This doesn't seem to be a valid CycloneDX BOM XML file. Namespace={namespace}" + raise ValueError(msg) ns = { "b": namespace.replace("{", "").replace( "}", "" diff --git a/dojo/tools/dependency_track/parser.py b/dojo/tools/dependency_track/parser.py index 4540297e98..e7a39ea4bd 100644 --- a/dojo/tools/dependency_track/parser.py +++ b/dojo/tools/dependency_track/parser.py @@ -113,17 +113,22 @@ def _convert_dependency_track_finding_to_dojo_finding(self, dependency_track_fin """ # Validation of required fields if 'vulnerability' not in dependency_track_finding: - raise ValueError("Missing 'vulnerability' node from finding!") + msg = "Missing 'vulnerability' node from finding!" + raise ValueError(msg) if 'vulnId' not in dependency_track_finding['vulnerability']: - raise ValueError("Missing 'vulnId' node from vulnerability!") + msg = "Missing 'vulnId' node from vulnerability!" + raise ValueError(msg) vuln_id = dependency_track_finding['vulnerability']['vulnId'] if 'source' not in dependency_track_finding['vulnerability']: - raise ValueError("Missing 'source' node from vulnerability!") + msg = "Missing 'source' node from vulnerability!" + raise ValueError(msg) source = dependency_track_finding['vulnerability']['source'] if 'component' not in dependency_track_finding: - raise ValueError("Missing 'component' node from finding!") + msg = "Missing 'component' node from finding!" + raise ValueError(msg) if 'name' not in dependency_track_finding['component']: - raise ValueError("Missing 'name' node from component!") + msg = "Missing 'name' node from component!" + raise ValueError(msg) component_name = dependency_track_finding['component']['name'] # Build the title of the Dojo finding diff --git a/dojo/tools/factory.py b/dojo/tools/factory.py index 84cfaafa90..891fd830dd 100644 --- a/dojo/tools/factory.py +++ b/dojo/tools/factory.py @@ -25,21 +25,24 @@ def register_parser(scan_type, parser): logger.debug(f"register scan_type:{scan_type} with parser:{parser}") # check double registration or registration with an existing key if scan_type in PARSERS: - raise ValueError(f"Try to register an existing parser '{scan_type}'") + msg = f"Try to register an existing parser '{scan_type}'" + raise ValueError(msg) PARSERS[scan_type] = parser def get_parser(scan_type): """Return a parser by the scan type""" if scan_type not in PARSERS: - raise ValueError(f"Parser '{scan_type}' does not exists") + msg = f"Parser '{scan_type}' does not exist" + raise ValueError(msg) rg = re.compile(settings.PARSER_EXCLUDE) if not rg.match(scan_type) or settings.PARSER_EXCLUDE.strip() == "": # update DB dynamicaly test_type, _ = Test_Type.objects.get_or_create(name=scan_type) if test_type.active: return PARSERS[scan_type] - raise ValueError(f"Parser {scan_type} is not active") + msg = f"Parser {scan_type} is not active" + raise ValueError(msg) def get_scan_types_sorted(): diff --git a/dojo/tools/gcloud_artifact_scan/parser.py b/dojo/tools/gcloud_artifact_scan/parser.py index 833d0b21e4..54bd27d5a1 100644 --- a/dojo/tools/gcloud_artifact_scan/parser.py +++ b/dojo/tools/gcloud_artifact_scan/parser.py @@ -20,7 +20,8 @@ def parse_json(self, json_output): except Exception: tree = json.loads(data) except Exception: - raise ValueError("Invalid format") + msg = "Invalid format" + raise ValueError(msg) return tree def get_findings(self, json_output, test): diff --git a/dojo/tools/generic/parser.py b/dojo/tools/generic/parser.py index d93feccc2b..1e5858bbd7 100644 --- a/dojo/tools/generic/parser.py +++ b/dojo/tools/generic/parser.py @@ -72,7 +72,8 @@ def _get_test_json(self, data): required = {"title", "severity", "description"} missing = sorted(required.difference(item)) if missing: - raise ValueError(f"Required fields are missing: {missing}") + msg = f"Required fields are missing: {missing}" + raise ValueError(msg) # check for allowed keys allowed = { @@ -121,9 +122,8 @@ def _get_test_json(self, data): }.union(required) not_allowed = sorted(set(item).difference(allowed)) if not_allowed: - raise ValueError( - f"Not allowed fields are present: {not_allowed}" - ) + msg = f"Not allowed fields are present: {not_allowed}" + raise ValueError(msg) finding = Finding(**item) diff --git a/dojo/tools/github_vulnerability/parser.py b/dojo/tools/github_vulnerability/parser.py index 6a83b832cf..4ca7830971 100644 --- a/dojo/tools/github_vulnerability/parser.py +++ b/dojo/tools/github_vulnerability/parser.py @@ -20,9 +20,8 @@ def get_findings(self, filename, test): if "data" in data: vulnerabilityAlerts = self._search_vulnerability_alerts(data["data"]) if not vulnerabilityAlerts: - raise ValueError( - "Invalid report, no 'vulnerabilityAlerts' node found" - ) + msg = "Invalid report, no 'vulnerabilityAlerts' node found" + raise ValueError(msg) repository_url = None if "repository" in data["data"]: if "nameWithOwner" in data["data"]["repository"]: diff --git a/dojo/tools/gitlab_dep_scan/parser.py b/dojo/tools/gitlab_dep_scan/parser.py index 3928d82d1d..2ec561500c 100644 --- a/dojo/tools/gitlab_dep_scan/parser.py +++ b/dojo/tools/gitlab_dep_scan/parser.py @@ -29,7 +29,8 @@ def parse_json(self, json_output): except Exception: tree = json.loads(data) except Exception: - raise ValueError("Invalid format") + msg = "Invalid format" + raise ValueError(msg) return tree diff --git a/dojo/tools/gitleaks/parser.py b/dojo/tools/gitleaks/parser.py index f7ab81873f..40ec9b9a81 100644 --- a/dojo/tools/gitleaks/parser.py +++ b/dojo/tools/gitleaks/parser.py @@ -35,7 +35,8 @@ def get_findings(self, filename, test): elif issue.get("Description"): self.get_finding_current(issue, test, dupes) else: - raise ValueError("Format is not recognized for Gitleaks") + msg = "Format is not recognized for Gitleaks" + raise ValueError(msg) return list(dupes.values()) diff --git a/dojo/tools/govulncheck/parser.py b/dojo/tools/govulncheck/parser.py index 31b8ec0c75..2deb7d70e8 100644 --- a/dojo/tools/govulncheck/parser.py +++ b/dojo/tools/govulncheck/parser.py @@ -73,7 +73,8 @@ def get_findings(self, scan_file, test): try: data = json.load(scan_file) except Exception: - raise ValueError("Invalid JSON format") + msg = "Invalid JSON format" + raise ValueError(msg) else: if isinstance(data, dict): if data["Vulns"]: diff --git a/dojo/tools/hcl_appscan/parser.py b/dojo/tools/hcl_appscan/parser.py index 0ac4adddd8..99862e17aa 100644 --- a/dojo/tools/hcl_appscan/parser.py +++ b/dojo/tools/hcl_appscan/parser.py @@ -27,9 +27,8 @@ def get_findings(self, file, test): tree = ET.parse(file) root = tree.getroot() if "xml-report" not in root.tag: - raise NamespaceErr( - "This doesn't seem to be a valid HCLAppScan xml file." - ) + msg = "This doesn't seem to be a valid HCLAppScan xml file." + raise NamespaceErr(msg) report = root.find("issue-group") if report is not None: for finding in report: diff --git a/dojo/tools/huskyci/parser.py b/dojo/tools/huskyci/parser.py index be0caeeb3a..472ffbbf6f 100644 --- a/dojo/tools/huskyci/parser.py +++ b/dojo/tools/huskyci/parser.py @@ -34,7 +34,8 @@ def parse_json(self, json_output): except Exception: tree = json.loads(data) except Exception: - raise ValueError("Invalid format") + msg = "Invalid format" + raise ValueError(msg) return tree diff --git a/dojo/tools/hydra/parser.py b/dojo/tools/hydra/parser.py index 3abb2b1c1b..a91adc88d3 100644 --- a/dojo/tools/hydra/parser.py +++ b/dojo/tools/hydra/parser.py @@ -72,9 +72,8 @@ def __extract_finding( or (username is None) or (password is None) ): - raise ValueError( - "Vital information is missing for this finding! Skipping this finding!" - ) + msg = "Vital information is missing for this finding! Skipping this finding!" + raise ValueError(msg) finding = Finding( test=test, @@ -103,8 +102,7 @@ def __parse_json(json_output): report = json.load(json_output) if "generator" not in report or "results" not in report: - raise ValueError( - "Unexpected JSON format provided. That doesn't look like a Hydra scan!" - ) + msg = "Unexpected JSON format provided. That doesn't look like a Hydra scan!" + raise ValueError(msg) return report diff --git a/dojo/tools/ibm_app/parser.py b/dojo/tools/ibm_app/parser.py index 3ef856063d..72700fd72c 100644 --- a/dojo/tools/ibm_app/parser.py +++ b/dojo/tools/ibm_app/parser.py @@ -24,9 +24,8 @@ def get_findings(self, file, test): # validate XML file if "xml-report" not in root.tag: - raise ValueError( - "This does not look like a valid expected Ibm AppScan DAST XML file." - ) + msg = "This does not look like a valid expected Ibm AppScan DAST XML file." + raise ValueError(msg) # self.hosts = self.fetch_host_details() issue_types = self.fetch_issue_types(root) diff --git a/dojo/tools/immuniweb/parser.py b/dojo/tools/immuniweb/parser.py index fdd90c9c8b..5076259f7f 100644 --- a/dojo/tools/immuniweb/parser.py +++ b/dojo/tools/immuniweb/parser.py @@ -22,9 +22,8 @@ def get_findings(self, file, test): root = ImmuniScanTree.getroot() # validate XML file if "Vulnerabilities" not in root.tag: - raise ValueError( - "This does not look like a valid expected Immuniweb XML file." - ) + msg = "This does not look like a valid expected Immuniweb XML file." + raise ValueError(msg) dupes = {} diff --git a/dojo/tools/intsights/parser.py b/dojo/tools/intsights/parser.py index 2ad4d7ae92..4c029ce0aa 100644 --- a/dojo/tools/intsights/parser.py +++ b/dojo/tools/intsights/parser.py @@ -51,9 +51,8 @@ def get_findings(self, file, test): elif file.name.lower().endswith(".csv"): alerts = IntSightsCSVParser()._parse_csv(file) else: - raise ValueError( - "Filename extension not recognized. Use .json or .csv" - ) + msg = "Filename extension not recognized. Use .json or .csv" + raise ValueError(msg) for alert in alerts: dupe_key = alert["alert_id"] alert = Finding( diff --git a/dojo/tools/meterian/parser.py b/dojo/tools/meterian/parser.py index 1fee4cbc86..f959713a64 100644 --- a/dojo/tools/meterian/parser.py +++ b/dojo/tools/meterian/parser.py @@ -35,7 +35,8 @@ def get_security_reports(self, report_json): if "reports" in report_json["reports"]["security"]: return report_json["reports"]["security"]["reports"] - raise ValueError("Malformed report: the security reports are missing.") + msg = "Malformed report: the security reports are missing." + raise ValueError(msg) def do_get_findings(self, single_security_report, scan_date, test): findings = [] diff --git a/dojo/tools/microfocus_webinspect/parser.py b/dojo/tools/microfocus_webinspect/parser.py index 228a861c7c..9764a2e8db 100644 --- a/dojo/tools/microfocus_webinspect/parser.py +++ b/dojo/tools/microfocus_webinspect/parser.py @@ -24,9 +24,8 @@ def get_findings(self, file, test): # get root of tree. root = tree.getroot() if "Sessions" not in root.tag: - raise ValueError( - "This doesn't seem to be a valid Webinspect xml file." - ) + msg = "This doesn't seem to be a valid Webinspect xml file." + raise ValueError(msg) dupes = {} for session in root: diff --git a/dojo/tools/nancy/parser.py b/dojo/tools/nancy/parser.py index 5b79c6c1e5..7fae9821fa 100644 --- a/dojo/tools/nancy/parser.py +++ b/dojo/tools/nancy/parser.py @@ -27,7 +27,8 @@ def get_findings(self, scan_file, test): if "vulnerable" in data: findings = self.get_items(data["vulnerable"], test) else: - raise ValueError("Invalid format, unable to parse json.") + msg = "Invalid format, unable to parse json." + raise ValueError(msg) return findings diff --git a/dojo/tools/neuvector/parser.py b/dojo/tools/neuvector/parser.py index e09429387e..f2f20ebd53 100644 --- a/dojo/tools/neuvector/parser.py +++ b/dojo/tools/neuvector/parser.py @@ -26,7 +26,8 @@ def parse_json(self, json_output): except Exception: tree = json.loads(data) except Exception: - raise ValueError("Invalid format") + msg = "Invalid format" + raise ValueError(msg) return tree @@ -144,4 +145,5 @@ def get_findings(self, filename, test): if filename.name.lower().endswith(".json"): return NeuVectorJsonParser().parse(filename, test) else: - raise ValueError("Unknown File Format") + msg = "Unknown File Format" + raise ValueError(msg) diff --git a/dojo/tools/neuvector_compliance/parser.py b/dojo/tools/neuvector_compliance/parser.py index 32f02d1be1..cf4367143a 100644 --- a/dojo/tools/neuvector_compliance/parser.py +++ b/dojo/tools/neuvector_compliance/parser.py @@ -23,7 +23,8 @@ def parse_json(json_output): except Exception: tree = json.loads(data) except Exception: - raise ValueError("Invalid format") + msg = "Invalid format" + raise ValueError(msg) return tree @@ -150,4 +151,5 @@ def get_findings(self, filename, test): if filename.name.lower().endswith(".json"): return parse(filename, test) else: - raise ValueError("Unknown File Format") + msg = "Unknown File Format" + raise ValueError(msg) diff --git a/dojo/tools/nikto/parser.py b/dojo/tools/nikto/parser.py index 414a0a882d..6e0f49dbb9 100644 --- a/dojo/tools/nikto/parser.py +++ b/dojo/tools/nikto/parser.py @@ -30,4 +30,5 @@ def get_findings(self, filename, test): elif filename.name.lower().endswith(".json"): return NiktoJSONParser().process_json(filename, test) else: - raise ValueError("Unknown File Format") + msg = "Unknown File Format" + raise ValueError(msg) diff --git a/dojo/tools/nmap/parser.py b/dojo/tools/nmap/parser.py index 5aceea62cd..b7630f217a 100644 --- a/dojo/tools/nmap/parser.py +++ b/dojo/tools/nmap/parser.py @@ -20,7 +20,8 @@ def get_findings(self, file, test): root = tree.getroot() dupes = {} if "nmaprun" not in root.tag: - raise ValueError("This doesn't seem to be a valid Nmap xml file.") + msg = "This doesn't seem to be a valid Nmap xml file." + raise ValueError(msg) report_date = None try: diff --git a/dojo/tools/noseyparker/parser.py b/dojo/tools/noseyparker/parser.py index c475b93d10..467855173b 100644 --- a/dojo/tools/noseyparker/parser.py +++ b/dojo/tools/noseyparker/parser.py @@ -45,7 +45,8 @@ def get_findings(self, file, test): rule_name = line['rule_name'] secret = line['match_content'] except Exception: - raise ValueError("Invalid Nosey Parker data, make sure to use Nosey Parker v0.16.0") + msg = "Invalid Nosey Parker data, make sure to use Nosey Parker v0.16.0" + raise ValueError(msg) # Set Finding details for match in line['matches']: @@ -96,6 +97,7 @@ def get_findings(self, file, test): ) dupes[key] = finding else: - raise ValueError("JSON lines format not recognized (.jsonl file extension). Make sure to use Nosey Parker v0.16.0") + msg = "JSON lines format not recognized (.jsonl file extension). Make sure to use Nosey Parker v0.16.0" + raise ValueError(msg) return list(dupes.values()) diff --git a/dojo/tools/npm_audit/parser.py b/dojo/tools/npm_audit/parser.py index b78e6f5e38..fc07e28100 100644 --- a/dojo/tools/npm_audit/parser.py +++ b/dojo/tools/npm_audit/parser.py @@ -32,20 +32,19 @@ def parse_json(self, json_output): except Exception: tree = json.loads(data) except Exception: - raise ValueError("Invalid format, unable to parse json.") + msg = "Invalid format, unable to parse json." + raise ValueError(msg) if tree.get("auditReportVersion"): - raise ValueError( - "npm7 with auditReportVersion 2 or higher not yet supported as it lacks the most important fields in the reports" - ) + msg = "npm7 with auditReportVersion 2 or higher not yet supported as it lacks the most important fields in the reports" + raise ValueError(msg) if tree.get("error"): error = tree.get("error") code = error["code"] summary = error["summary"] - raise ValueError( - "npm audit report contains errors: %s, %s", code, summary - ) + msg = "npm audit report contains errors: %s, %s" + raise ValueError(msg, code, summary) subtree = tree.get("advisories") diff --git a/dojo/tools/npm_audit_7_plus/parser.py b/dojo/tools/npm_audit_7_plus/parser.py index 42abc86330..b7afa60aed 100644 --- a/dojo/tools/npm_audit_7_plus/parser.py +++ b/dojo/tools/npm_audit_7_plus/parser.py @@ -51,25 +51,28 @@ def parse_json(self, json_output): except Exception: tree = json.loads(data) except Exception: - raise ValueError("Invalid format, unable to parse json.") + msg = "Invalid format, unable to parse json." + raise ValueError(msg) # output from npm audit fix --dry-run --json if tree.get("audit"): if not tree.get("audit").get("auditReportVersion"): - raise ValueError( + msg = ( "This parser only supports output from npm audit version" " 7 and above." ) + raise ValueError(msg) subtree = tree.get("audit").get("vulnerabilities") # output from npm audit --dry-run --json # or # output from npm audit --json else: if not tree.get("auditReportVersion"): - raise ValueError( + msg = ( "This parser only supports output from npm audit version" " 7 and above." ) + raise ValueError(msg) subtree = tree.get("vulnerabilities") return subtree diff --git a/dojo/tools/nsp/parser.py b/dojo/tools/nsp/parser.py index 35c0fca976..0b4da91c4e 100644 --- a/dojo/tools/nsp/parser.py +++ b/dojo/tools/nsp/parser.py @@ -28,7 +28,8 @@ def parse_json(self, json_output): except Exception: tree = json.loads(data) except Exception: - raise ValueError("Invalid format") + msg = "Invalid format" + raise ValueError(msg) return tree diff --git a/dojo/tools/openscap/parser.py b/dojo/tools/openscap/parser.py index 884ac1f571..91411b2bba 100644 --- a/dojo/tools/openscap/parser.py +++ b/dojo/tools/openscap/parser.py @@ -26,13 +26,11 @@ def get_findings(self, file, test): # check if xml file hash correct root or not. if "Benchmark" not in root.tag: - raise ValueError( - "This doesn't seem to be a valid Openscap vulnerability scan xml file." - ) + msg = "This doesn't seem to be a valid Openscap vulnerability scan xml file." + raise ValueError(msg) if "http://checklists.nist.gov/xccdf/" not in namespace: - raise ValueError( - "This doesn't seem to be a valid Openscap vulnerability scan xml file." - ) + msg = "This doesn't seem to be a valid Openscap vulnerability scan xml file." + raise ValueError(msg) # read rules rules = {} diff --git a/dojo/tools/openvas/xml_parser.py b/dojo/tools/openvas/xml_parser.py index 5937b3c11b..4466727095 100644 --- a/dojo/tools/openvas/xml_parser.py +++ b/dojo/tools/openvas/xml_parser.py @@ -9,9 +9,8 @@ def get_findings(self, filename, test): tree = ET.parse(filename) root = tree.getroot() if "report" not in root.tag: - raise NamespaceErr( - "This doesn't seem to be a valid Greenbone OpenVAS XML file." - ) + msg = "This doesn't seem to be a valid Greenbone OpenVAS XML file." + raise NamespaceErr(msg) report = root.find("report") results = report.find("results") for result in results: diff --git a/dojo/tools/ort/parser.py b/dojo/tools/ort/parser.py index 306d78374f..b2c33b0c45 100644 --- a/dojo/tools/ort/parser.py +++ b/dojo/tools/ort/parser.py @@ -35,7 +35,8 @@ def parse_json(self, json_output): except Exception: tree = json.loads(data) except Exception: - raise ValueError("Invalid format") + msg = "Invalid format" + raise ValueError(msg) return tree diff --git a/dojo/tools/ossindex_devaudit/parser.py b/dojo/tools/ossindex_devaudit/parser.py index 883d25eb1c..e9abb97770 100644 --- a/dojo/tools/ossindex_devaudit/parser.py +++ b/dojo/tools/ossindex_devaudit/parser.py @@ -33,7 +33,8 @@ def parse_json(self, json_file): try: tree = json.load(json_file) except JSONDecodeError: - raise ValueError("Invalid format") + msg = "Invalid format" + raise ValueError(msg) return tree @@ -67,9 +68,8 @@ def get_item( try: cwe = int(cwe_data.split("-")[1]) except ValueError: - raise ValueError( - "Attempting to convert the CWE value to an integer failed" - ) + msg = "Attempting to convert the CWE value to an integer failed" + raise ValueError(msg) finding = Finding( title=dependency_source diff --git a/dojo/tools/php_symfony_security_check/parser.py b/dojo/tools/php_symfony_security_check/parser.py index 3691e60639..a124a4d419 100644 --- a/dojo/tools/php_symfony_security_check/parser.py +++ b/dojo/tools/php_symfony_security_check/parser.py @@ -27,7 +27,8 @@ def parse_json(self, json_file): except Exception: tree = json.loads(data) except Exception: - raise Exception("Invalid format") + msg = "Invalid format" + raise Exception(msg) return tree diff --git a/dojo/tools/risk_recon/api.py b/dojo/tools/risk_recon/api.py index 8b1a07dfbf..07048e763b 100644 --- a/dojo/tools/risk_recon/api.py +++ b/dojo/tools/risk_recon/api.py @@ -10,17 +10,19 @@ def __init__(self, api_key, endpoint, data): self.toe_map = {} if not self.key: - raise Exception( + msg = ( "Please supply a Risk Recon API key. \n" "This can be generated in the system admin panel. \n" "See https://documentation.defectdojo.com/integrations/import/#risk-recon-api-importer \n" ) + raise Exception(msg) if not self.url: - raise Exception( + msg = ( "Please supply a Risk Recon API url. \n" "A general url is https://api.riskrecon.com/v1/ \n" "See https://documentation.defectdojo.com/integrations/import/#risk-recon-api-importer \n" ) + raise Exception(msg) if self.url.endswith("/"): self.url = endpoint[:-1] self.session = requests.Session() @@ -50,9 +52,8 @@ def map_toes(self): filters = comps.get(name, None) self.toe_map[toe_id] = filters if filters else self.data else: - raise Exception( - f"Unable to query Target of Evaluations due to {response.status_code} - {response.content}" - ) + msg = f"Unable to query Target of Evaluations due to {response.status_code} - {response.content}" + raise Exception(msg) def filter_finding(self, finding): filters = self.toe_map[finding["toe_id"]] @@ -82,6 +83,5 @@ def get_findings(self): if not self.filter_finding(finding): self.findings.append(finding) else: - raise Exception( - f"Unable to collect findings from toe: {toe} due to {response.status_code} - {response.content}" - ) + msg = f"Unable to collect findings from toe: {toe} due to {response.status_code} - {response.content}" + raise Exception(msg) diff --git a/dojo/tools/sarif/parser.py b/dojo/tools/sarif/parser.py index e6afa42d2d..1f42f6d2a7 100644 --- a/dojo/tools/sarif/parser.py +++ b/dojo/tools/sarif/parser.py @@ -180,7 +180,8 @@ def get_title(result, rule): title = rule["id"] if title is None: - raise ValueError("No information found to create a title") + msg = "No information found to create a title" + raise ValueError(msg) return textwrap.shorten(title, 150) diff --git a/dojo/tools/semgrep/parser.py b/dojo/tools/semgrep/parser.py index 762b471638..97e711bf23 100644 --- a/dojo/tools/semgrep/parser.py +++ b/dojo/tools/semgrep/parser.py @@ -139,7 +139,8 @@ def convert_severity(self, val): elif "INFO" == val.upper(): return "Info" else: - raise ValueError(f"Unknown value for severity: {val}") + msg = f"Unknown value for severity: {val}" + raise ValueError(msg) def get_description(self, item): description = "" diff --git a/dojo/tools/snyk/parser.py b/dojo/tools/snyk/parser.py index 94974ca794..04120e80ee 100644 --- a/dojo/tools/snyk/parser.py +++ b/dojo/tools/snyk/parser.py @@ -36,7 +36,8 @@ def parse_json(self, json_output): except Exception: tree = json.loads(data) except Exception: - raise ValueError("Invalid format") + msg = "Invalid format" + raise ValueError(msg) return tree diff --git a/dojo/tools/snyk_code/parser.py b/dojo/tools/snyk_code/parser.py index 4ef37a5081..fa9172774c 100644 --- a/dojo/tools/snyk_code/parser.py +++ b/dojo/tools/snyk_code/parser.py @@ -36,7 +36,8 @@ def parse_json(self, json_output): except Exception: tree = json.loads(data) except Exception: - raise ValueError("Invalid format") + msg = "Invalid format" + raise ValueError(msg) return tree diff --git a/dojo/tools/sslscan/parser.py b/dojo/tools/sslscan/parser.py index ed6ab585a9..421e197442 100644 --- a/dojo/tools/sslscan/parser.py +++ b/dojo/tools/sslscan/parser.py @@ -23,9 +23,8 @@ def get_findings(self, file, test): # get root of tree. root = tree.getroot() if "document" not in root.tag: - raise NamespaceErr( - "This doesn't seem to be a valid sslscan xml file." - ) + msg = "This doesn't seem to be a valid sslscan xml file." + raise NamespaceErr(msg) dupes = {} for ssltest in root: for target in ssltest: diff --git a/dojo/tools/sslyze/parser.py b/dojo/tools/sslyze/parser.py index ba742d43a2..a80965f294 100644 --- a/dojo/tools/sslyze/parser.py +++ b/dojo/tools/sslyze/parser.py @@ -25,4 +25,5 @@ def get_findings(self, filename, test): elif filename.name.lower().endswith(".json"): return SSLyzeJSONParser().get_findings(filename, test) else: - raise ValueError("Unknown File Format") + msg = "Unknown File Format" + raise ValueError(msg) diff --git a/dojo/tools/sslyze/parser_json.py b/dojo/tools/sslyze/parser_json.py index 3409576b6f..48dc625c04 100644 --- a/dojo/tools/sslyze/parser_json.py +++ b/dojo/tools/sslyze/parser_json.py @@ -86,7 +86,8 @@ def parse_json(self, json_output): except Exception: tree = json.loads(data) except Exception: - raise Exception("Invalid format") + msg = "Invalid format" + raise Exception(msg) return tree diff --git a/dojo/tools/sslyze/parser_xml.py b/dojo/tools/sslyze/parser_xml.py index 7c59bce50b..07c2adcaad 100644 --- a/dojo/tools/sslyze/parser_xml.py +++ b/dojo/tools/sslyze/parser_xml.py @@ -55,9 +55,8 @@ def get_findings(self, file, test): # get root of tree. root = tree.getroot() if "document" not in root.tag: - raise NamespaceErr( - "This doesn't seem to be a valid sslyze xml file." - ) + msg = "This doesn't seem to be a valid sslyze xml file." + raise NamespaceErr(msg) results = root.find("results") dupes = {} diff --git a/dojo/tools/stackhawk/parser.py b/dojo/tools/stackhawk/parser.py index 64480334f7..9030dcd9a3 100644 --- a/dojo/tools/stackhawk/parser.py +++ b/dojo/tools/stackhawk/parser.py @@ -123,12 +123,13 @@ def __parse_json(json_output): # Specifically, that the attributes accessed when parsing the finding will always exist. # See our documentation for more details on this data: # https://docs.stackhawk.com/workflow-integrations/webhook.html#scan-completed - raise ValueError( + msg = ( " Unexpected JSON format provided. " "Need help? " "Check out the StackHawk Docs at " "https://docs.stackhawk.com/workflow-integrations/defect-dojo.html" ) + raise ValueError(msg) return report["scanCompleted"] diff --git a/dojo/tools/sysdig_reports/sysdig_csv_parser.py b/dojo/tools/sysdig_reports/sysdig_csv_parser.py index 21d5e946fa..8962531d2d 100644 --- a/dojo/tools/sysdig_reports/sysdig_csv_parser.py +++ b/dojo/tools/sysdig_reports/sysdig_csv_parser.py @@ -26,11 +26,13 @@ def parse(self, filename) -> SysdigData: for row in reader: # Compare headers to values. if len(row) != len(reader.fieldnames): - raise ValueError(f"Number of fields in row ({len(row)}) does not match number of headers ({len(reader.fieldnames)})") + msg = f"Number of fields in row ({len(row)}) does not match number of headers ({len(reader.fieldnames)})" + raise ValueError(msg) # Check for a CVE value to being with if not row[reader.fieldnames[0]].startswith("CVE"): - raise ValueError(f"Expected 'CVE' at the start but got: {row[reader.fieldnames[0]]}") + msg = f"Expected 'CVE' at the start but got: {row[reader.fieldnames[0]]}" + raise ValueError(msg) csvarray.append(row) diff --git a/dojo/tools/tenable/parser.py b/dojo/tools/tenable/parser.py index 88ebd63d90..b24b072a68 100644 --- a/dojo/tools/tenable/parser.py +++ b/dojo/tools/tenable/parser.py @@ -22,6 +22,5 @@ def get_findings(self, filename, test): elif filename.name.lower().endswith(".csv"): return TenableCSVParser().get_findings(filename, test) else: - raise ValueError( - "Filename extension not recognized. Use .xml, .nessus or .csv" - ) + msg = "Filename extension not recognized. Use .xml, .nessus or .csv" + raise ValueError(msg) diff --git a/dojo/tools/tenable/xml_format.py b/dojo/tools/tenable/xml_format.py index 12d1089be4..d0c231b67d 100644 --- a/dojo/tools/tenable/xml_format.py +++ b/dojo/tools/tenable/xml_format.py @@ -61,11 +61,12 @@ def get_findings(self, filename: str, test: Test) -> list: root = nscan.getroot() if "NessusClientData_v2" not in root.tag: - raise ValueError( + msg = ( "This version of Nessus report is not supported. " "Please make sure the export is " "formatted using the NessusClientData_v2 schema." ) + raise ValueError(msg) dupes = {} for report in root.iter("Report"): diff --git a/dojo/tools/terrascan/parser.py b/dojo/tools/terrascan/parser.py index 2810ffcaaa..1c08f310e6 100644 --- a/dojo/tools/terrascan/parser.py +++ b/dojo/tools/terrascan/parser.py @@ -28,7 +28,8 @@ def get_findings(self, filename, test): data = json.load(filename) dupes = {} if "results" not in data and "violations" not in data.get("results"): - raise ValueError("missing mandatory attribute 'results'") + msg = "missing mandatory attribute 'results'" + raise ValueError(msg) if data.get("results").get("violations") is None: return [] for item in data.get("results").get("violations"): diff --git a/dojo/tools/tfsec/parser.py b/dojo/tools/tfsec/parser.py index 7fc671121a..017fe74820 100644 --- a/dojo/tools/tfsec/parser.py +++ b/dojo/tools/tfsec/parser.py @@ -32,9 +32,8 @@ def get_findings(self, filename, test): data = json.load(filename) dupes = {} if "results" not in data: - raise ValueError( - "Incorrect TFSec scan, missing attribute 'results'" - ) + msg = "Incorrect TFSec scan, missing attribute 'results'" + raise ValueError(msg) if data.get("results") is None: return [] for item in data.get("results"): diff --git a/dojo/tools/threagile/parser.py b/dojo/tools/threagile/parser.py index 61a2487420..418fabcf31 100644 --- a/dojo/tools/threagile/parser.py +++ b/dojo/tools/threagile/parser.py @@ -73,15 +73,16 @@ def get_findings(self, file, test): def get_items(self, tree, test): if not isinstance(tree, list): - raise TypeError("Invalid ThreAgile risks file") + msg = "Invalid ThreAgile risks file" + raise TypeError(msg) if not tree: return [] findings = [] for item in tree: for field in self.REQUIRED_FIELDS: if field not in item.keys(): - raise ValueError( - f"Invalid ThreAgile risks file, missing field {field}") + msg = f"Invalid ThreAgile risks file, missing field {field}" + raise ValueError(msg) severity = item.get("severity", "info").capitalize() severity = severity if severity != "Elevated" else "High" finding = Finding( diff --git a/dojo/tools/trivy/parser.py b/dojo/tools/trivy/parser.py index 66c720938a..400f71c36d 100644 --- a/dojo/tools/trivy/parser.py +++ b/dojo/tools/trivy/parser.py @@ -145,9 +145,8 @@ def get_findings(self, scan_file, test): ) return findings else: - raise ValueError( - "Schema of Trivy json report is not supported" - ) + msg = "Schema of Trivy json report is not supported" + raise ValueError(msg) def get_result_items(self, test, results, service_name=None, artifact_name=""): items = [] diff --git a/dojo/tools/trufflehog3/parser.py b/dojo/tools/trufflehog3/parser.py index 9b22661840..11cbe68072 100644 --- a/dojo/tools/trufflehog3/parser.py +++ b/dojo/tools/trufflehog3/parser.py @@ -25,7 +25,8 @@ def get_findings(self, filename, test): elif json_data.get("rule"): self.get_finding_current(json_data, test, dupes) else: - raise ValueError("Format is not recognized for Trufflehog3") + msg = "Format is not recognized for Trufflehog3" + raise ValueError(msg) return list(dupes.values()) diff --git a/dojo/tools/twistlock/parser.py b/dojo/tools/twistlock/parser.py index 7009c61c62..d561555042 100644 --- a/dojo/tools/twistlock/parser.py +++ b/dojo/tools/twistlock/parser.py @@ -108,7 +108,8 @@ def parse_json(self, json_output): except Exception: tree = json.loads(data) except Exception: - raise ValueError("Invalid format") + msg = "Invalid format" + raise ValueError(msg) return tree @@ -220,4 +221,5 @@ def get_findings(self, filename, test): elif filename.name.lower().endswith(".csv"): return TwistlockCSVParser().parse(filename, test) else: - raise ValueError("Unknown File Format") + msg = "Unknown File Format" + raise ValueError(msg) diff --git a/dojo/tools/vcg/parser.py b/dojo/tools/vcg/parser.py index 86b1f75cc0..9c2bc3a540 100644 --- a/dojo/tools/vcg/parser.py +++ b/dojo/tools/vcg/parser.py @@ -222,4 +222,5 @@ def get_findings(self, filename, test): elif filename.name.lower().endswith(".csv"): return list(VCGCsvParser().parse(content, test).values()) else: - raise ValueError("Unknown File Format") + msg = "Unknown File Format" + raise ValueError(msg) diff --git a/dojo/tools/veracode/parser.py b/dojo/tools/veracode/parser.py index d24c99f351..ec3f5ba00d 100644 --- a/dojo/tools/veracode/parser.py +++ b/dojo/tools/veracode/parser.py @@ -20,6 +20,5 @@ def get_findings(self, filename, test): elif filename.name.lower().endswith(".json"): return VeracodeJSONParser().get_findings(filename, test) else: - raise ValueError( - "Filename extension not recognized. Use .xml or .json" - ) + msg = "Filename extension not recognized. Use .xml or .json" + raise ValueError(msg) diff --git a/dojo/tools/wapiti/parser.py b/dojo/tools/wapiti/parser.py index 64937b9889..d4c9b9dccc 100644 --- a/dojo/tools/wapiti/parser.py +++ b/dojo/tools/wapiti/parser.py @@ -31,9 +31,8 @@ def get_findings(self, file, test): root = tree.getroot() # check if it is if "report" not in root.tag: - raise ValueError( - "This doesn't seem to be a valid Wapiti XML file." - ) + msg = "This doesn't seem to be a valid Wapiti XML file." + raise ValueError(msg) severity_mapping = { "4": "Critical", diff --git a/dojo/tools/whitehat_sentinel/parser.py b/dojo/tools/whitehat_sentinel/parser.py index ca4cb8acb8..0952f188d9 100644 --- a/dojo/tools/whitehat_sentinel/parser.py +++ b/dojo/tools/whitehat_sentinel/parser.py @@ -36,9 +36,8 @@ def get_findings(self, file, test): "collection" not in findings_collection.keys() or not findings_collection["collection"] ): - raise ValueError( - "collection key not present or there were not findings present." - ) + msg = "collection key not present or there were not findings present." + raise ValueError(msg) # Convert a WhiteHat Vuln with Attack Vectors to a list of DefectDojo # findings diff --git a/dojo/tools/xanitizer/parser.py b/dojo/tools/xanitizer/parser.py index 211448e944..bed38e19f4 100644 --- a/dojo/tools/xanitizer/parser.py +++ b/dojo/tools/xanitizer/parser.py @@ -35,9 +35,8 @@ def parse_xml(self, filename): root = tree.getroot() if "XanitizerFindingsList" not in root.tag: - raise ValueError( - f"'{filename}' is not a valid Xanitizer findings list report XML file." - ) + msg = f"'{filename}' is not a valid Xanitizer findings list report XML file." + raise ValueError(msg) return root diff --git a/dojo/tools/yarn_audit/parser.py b/dojo/tools/yarn_audit/parser.py index 6eaaecb7e4..97da05a71b 100644 --- a/dojo/tools/yarn_audit/parser.py +++ b/dojo/tools/yarn_audit/parser.py @@ -39,9 +39,8 @@ def get_items_yarn(self, tree, test): items[unique_key] = item elif element.get("type") == "error": error = element.get("data") - raise ValueError( - "yarn audit report contains errors: %s", error - ) + msg = "yarn audit report contains errors: %s" + raise ValueError(msg, error) return list(items.values()) def get_items_auditci(self, tree, test): # https://github.com/DefectDojo/django-DefectDojo/issues/6495 diff --git a/dojo/user/views.py b/dojo/user/views.py index 7e3d41938b..94f07668ba 100644 --- a/dojo/user/views.py +++ b/dojo/user/views.py @@ -617,7 +617,8 @@ def clean(self): connection.open() connection.close() except Exception: - raise ValidationError("SMTP server is not configured correctly...") + msg = "SMTP server is not configured correctly..." + raise ValidationError(msg) class DojoPasswordResetForm(PasswordResetForm): @@ -643,7 +644,8 @@ def clean(self): connection.close() except Exception as e: logger.error(f"SMTP Server Connection Failure: {str(e)}") - raise ValidationError("SMTP server is not configured correctly...") + msg = "SMTP server is not configured correctly..." + raise ValidationError(msg) class DojoPasswordResetView(PasswordResetView): diff --git a/dojo/utils.py b/dojo/utils.py index 73d98fcecc..22d737a974 100644 --- a/dojo/utils.py +++ b/dojo/utils.py @@ -136,7 +136,8 @@ def match_finding_to_existing_findings(finding, product=None, engagement=None, t custom_filter = {'test': test} else: - raise ValueError('No product, engagement or test provided as argument.') + msg = 'No product, engagement or test provided as argument.' + raise ValueError(msg) deduplication_algorithm = finding.test.deduplication_algorithm @@ -486,13 +487,17 @@ def set_duplicate(new_finding, existing_finding): deduplicationLogger.debug(f"existing_finding.status(): {existing_finding.id} {existing_finding.status()}") if existing_finding.duplicate: deduplicationLogger.debug('existing finding: %s:%s:duplicate=%s;duplicate_finding=%s', existing_finding.id, existing_finding.title, existing_finding.duplicate, existing_finding.duplicate_finding.id if existing_finding.duplicate_finding else 'None') - raise Exception("Existing finding is a duplicate") + msg = "Existing finding is a duplicate" + raise Exception(msg) if existing_finding.id == new_finding.id: - raise Exception("Can not add duplicate to itself") + msg = "Can not add duplicate to itself" + raise Exception(msg) if is_duplicate_reopen(new_finding, existing_finding): - raise Exception("Found a regression. Ignore this so that a new duplicate chain can be made") + msg = "Found a regression. Ignore this so that a new duplicate chain can be made" + raise Exception(msg) if new_finding.duplicate and finding_mitigated(existing_finding): - raise Exception("Skip this finding as we do not want to attach a new duplicate to a mitigated finding") + msg = "Skip this finding as we do not want to attach a new duplicate to a mitigated finding" + raise Exception(msg) deduplicationLogger.debug('Setting new finding ' + str(new_finding.id) + ' as a duplicate of existing finding ' + str(existing_finding.id)) new_finding.duplicate = True @@ -1786,7 +1791,8 @@ def redirect(request, redirect_to): """Only allow redirects to allowed_hosts to prevent open redirects""" if is_safe_url(redirect_to): return HttpResponseRedirect(redirect_to) - raise ValueError('invalid redirect, host and scheme not in allowed_hosts') + msg = 'invalid redirect, host and scheme not in allowed_hosts' + raise ValueError(msg) def file_size_mb(file_obj): @@ -2150,7 +2156,8 @@ def mass_model_updater(model_type, models, function, fields, page_size=1000, ord # get maximum, which is the first due to descending order last_id = models.first().id + 1 else: - raise ValueError('order must be ''asc'' or ''desc''') + msg = 'order must be ''asc'' or ''desc''' + raise ValueError(msg) # use filter to make count fast on mysql total_count = models.filter(id__gt=0).count() logger.debug('%s found %d models for mass update:', log_prefix, total_count) diff --git a/ruff.toml b/ruff.toml index cfa81b12d6..484b0b505b 100644 --- a/ruff.toml +++ b/ruff.toml @@ -41,6 +41,7 @@ select = [ "EXE", "TRIO", "C4", + "EM", "ICN", "LOG", "SLOT", diff --git a/tests/product_test.py b/tests/product_test.py index efe868dde9..1c858c5231 100644 --- a/tests/product_test.py +++ b/tests/product_test.py @@ -26,9 +26,8 @@ def __exit__(self, *_): return True else: time.sleep(0.2) - raise Exception( - f'Timeout waiting for {self.timeout}s' - ) + msg = f'Timeout waiting for {self.timeout}s' + raise Exception(msg) class ProductTest(BaseTestCase): From ea1e4f662c0bb7d8e536b269dcd8cbe5d59c25a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Apr 2024 15:46:59 -0500 Subject: [PATCH 104/138] Bump boto3 from 1.34.93 to 1.34.94 (#10067) Bumps [boto3](https://github.com/boto/boto3) from 1.34.93 to 1.34.94. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.34.93...1.34.94) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index f4f03b816f..48b63397ff 100644 --- a/requirements.txt +++ b/requirements.txt @@ -75,7 +75,7 @@ django-ratelimit==4.1.0 argon2-cffi==23.1.0 blackduck==1.1.3 pycurl==7.45.3 # Required for Celery Broker AWS (SQS) support -boto3==1.34.93 # Required for Celery Broker AWS (SQS) support +boto3==1.34.94 # Required for Celery Broker AWS (SQS) support netaddr==1.2.1 vulners==2.1.5 fontawesomefree==6.5.1 From 134d403c2e3ae85cc3c7eab73da2e5099562b652 Mon Sep 17 00:00:00 2001 From: kiblik Date: Tue, 30 Apr 2024 22:49:47 +0200 Subject: [PATCH 105/138] Ruff: add isort (#9754) * Add isort * Fix isort --- dojo/admin.py | 16 +- dojo/announcement/signals.py | 5 +- dojo/announcement/urls.py | 1 + dojo/announcement/views.py | 12 +- dojo/api_v2/exception_handler.py | 6 +- dojo/api_v2/mixins.py | 10 +- dojo/api_v2/permissions.py | 26 +- dojo/api_v2/prefetch/mixins.py | 3 +- dojo/api_v2/prefetch/prefetcher.py | 6 +- dojo/api_v2/serializers.py | 172 ++++++----- dojo/api_v2/views.py | 266 +++++++++--------- dojo/apps.py | 2 +- dojo/authorization/authorization.py | 27 +- .../authorization/authorization_decorators.py | 4 +- dojo/banner/urls.py | 1 + dojo/banner/views.py | 10 +- dojo/benchmark/urls.py | 1 + dojo/benchmark/views.py | 24 +- dojo/celery.py | 3 +- dojo/components/urls.py | 1 + dojo/components/views.py | 13 +- dojo/cred/queries.py | 4 +- dojo/cred/urls.py | 1 + dojo/cred/views.py | 16 +- dojo/decorators.py | 15 +- dojo/development_environment/views.py | 16 +- dojo/endpoint/queries.py | 11 +- dojo/endpoint/utils.py | 16 +- dojo/endpoint/views.py | 42 +-- dojo/engagement/queries.py | 4 +- dojo/engagement/services.py | 3 +- dojo/engagement/views.py | 136 +++++---- dojo/filters.py | 105 +++++-- dojo/finding/helper.py | 30 +- dojo/finding/queries.py | 12 +- dojo/finding/views.py | 158 +++++------ dojo/finding_group/queries.py | 4 +- dojo/finding_group/views.py | 18 +- dojo/forms.py | 122 +++++--- dojo/github.py | 5 +- dojo/github_issue_link/urls.py | 1 + dojo/github_issue_link/views.py | 11 +- dojo/group/queries.py | 3 +- dojo/group/utils.py | 5 +- dojo/group/views.py | 52 ++-- dojo/home/views.py | 13 +- dojo/importers/importer/importer.py | 25 +- dojo/importers/reimporter/reimporter.py | 15 +- dojo/importers/reimporter/utils.py | 11 +- dojo/importers/utils.py | 25 +- dojo/jira_link/helper.py | 43 ++- dojo/jira_link/queries.py | 4 +- dojo/jira_link/urls.py | 1 + dojo/jira_link/views.py | 25 +- dojo/management/commands/clear_alerts.py | 1 + dojo/management/commands/dedupe.py | 11 +- dojo/management/commands/dupecheck.py | 2 +- .../management/commands/endpoint_migration.py | 7 +- dojo/management/commands/fix_0120.py | 7 +- .../commands/fix_broken_endpoint_status.py | 7 +- .../commands/fix_loop_duplicates.py | 7 +- .../commands/import_github_languages.py | 3 +- dojo/management/commands/import_surveys.py | 7 +- .../commands/initialize_permissions.py | 6 +- .../commands/initialize_test_types.py | 3 +- .../management/commands/jira_async_updates.py | 2 +- .../commands/jira_refactor_data_migration.py | 6 +- .../commands/jira_status_reconciliation.py | 7 +- .../commands/migrate_authorization_v2.py | 2 +- .../commands/migrate_staff_users.py | 4 +- dojo/management/commands/migrate_surveys.py | 5 +- .../commands/migrate_textquestions.py | 2 +- dojo/management/commands/print_settings.py | 5 +- .../commands/push_to_jira_update.py | 2 +- .../commands/rename_mend_findings.py | 1 + .../risk_acceptance_handle_expiration.py | 3 +- dojo/management/commands/sla_notifications.py | 1 + dojo/management/commands/system_settings.py | 1 + .../commands/test_celery_decorator.py | 5 +- .../commands/validatededupeconfig.py | 1 + dojo/metrics/views.py | 42 +-- dojo/middleware.py | 10 +- dojo/models.py | 50 ++-- dojo/note_type/views.py | 12 +- dojo/notes/urls.py | 1 + dojo/notes/views.py | 11 +- dojo/notifications/helper.py | 9 +- dojo/notifications/urls.py | 1 + dojo/notifications/views.py | 9 +- dojo/object/urls.py | 1 + dojo/object/views.py | 14 +- dojo/okta.py | 6 +- dojo/pipeline.py | 9 +- dojo/product/helpers.py | 4 +- dojo/product/queries.py | 25 +- dojo/product/signals.py | 8 +- dojo/product/urls.py | 2 +- dojo/product/views.py | 138 ++++++--- dojo/product_type/queries.py | 13 +- dojo/product_type/urls.py | 2 +- dojo/product_type/views.py | 41 ++- dojo/regulations/urls.py | 1 + dojo/regulations/views.py | 12 +- dojo/remote_user.py | 10 +- dojo/reports/views.py | 47 ++-- dojo/reports/widgets.py | 2 +- dojo/risk_acceptance/api.py | 7 +- dojo/risk_acceptance/helper.py | 14 +- dojo/risk_acceptance/queries.py | 4 +- dojo/search/views.py | 31 +- dojo/settings/settings.dist.py | 16 +- dojo/settings/settings.py | 2 +- dojo/sla_config/helpers.py | 3 +- dojo/sla_config/urls.py | 1 + dojo/sla_config/views.py | 2 +- dojo/survey/urls.py | 6 +- dojo/survey/views.py | 60 ++-- dojo/system_settings/urls.py | 1 + dojo/system_settings/views.py | 9 +- dojo/tasks.py | 16 +- dojo/templatetags/announcement_banner_tags.py | 2 +- dojo/templatetags/as_json.py | 2 + dojo/templatetags/authorization_tags.py | 7 +- dojo/templatetags/display_tags.py | 31 +- dojo/templatetags/event_tags.py | 4 +- dojo/templatetags/get_attribute.py | 1 + dojo/templatetags/get_banner.py | 3 +- dojo/templatetags/get_endpoint_status.py | 4 +- dojo/templatetags/get_note_status.py | 1 + .../templatetags/get_notetype_availability.py | 1 + dojo/templatetags/navigation_tags.py | 3 +- dojo/templatetags/survey_tags.py | 1 + dojo/test/queries.py | 4 +- dojo/test/signals.py | 6 +- dojo/test/views.py | 98 +++++-- dojo/test_type/views.py | 11 +- dojo/tool_config/factory.py | 3 +- dojo/tool_config/urls.py | 1 + dojo/tool_config/views.py | 10 +- dojo/tool_product/queries.py | 4 +- dojo/tool_product/urls.py | 1 + dojo/tool_product/views.py | 7 +- dojo/tool_type/urls.py | 1 + dojo/tool_type/views.py | 6 +- dojo/tools/acunetix/parse_acunetix360_json.py | 4 +- dojo/tools/acunetix/parse_acunetix_xml.py | 5 +- dojo/tools/anchore_grype/parser.py | 1 + dojo/tools/api_blackduck/importer.py | 1 + dojo/tools/api_bugcrowd/api_client.py | 3 +- dojo/tools/api_bugcrowd/importer.py | 3 + dojo/tools/api_bugcrowd/parser.py | 10 +- dojo/tools/api_cobalt/importer.py | 3 + dojo/tools/api_cobalt/parser.py | 3 +- dojo/tools/api_edgescan/api_client.py | 3 +- dojo/tools/api_edgescan/importer.py | 2 + dojo/tools/api_edgescan/parser.py | 2 + dojo/tools/api_sonarqube/importer.py | 5 +- dojo/tools/api_sonarqube/parser.py | 1 - dojo/tools/api_sonarqube/updater.py | 1 + .../api_sonarqube/updater_from_source.py | 3 +- dojo/tools/api_vulners/importer.py | 3 + dojo/tools/api_vulners/parser.py | 2 + dojo/tools/asff/parser.py | 2 + dojo/tools/auditjs/parser.py | 8 +- dojo/tools/aws_scout2/parser.py | 3 +- dojo/tools/awssecurityhub/compliance.py | 1 + dojo/tools/awssecurityhub/guardduty.py | 3 +- dojo/tools/awssecurityhub/inspector.py | 3 +- dojo/tools/awssecurityhub/parser.py | 5 +- .../parser.py | 5 +- dojo/tools/bandit/parser.py | 1 + dojo/tools/bearer_cli/parser.py | 1 + dojo/tools/blackduck/parser.py | 1 + .../tools/blackduck_binary_analysis/parser.py | 4 +- .../blackduck_component_risk/importer.py | 2 +- dojo/tools/blackduck_component_risk/parser.py | 3 +- dojo/tools/bugcrowd/parser.py | 1 + dojo/tools/burp/parser.py | 2 + dojo/tools/burp_api/parser.py | 2 +- dojo/tools/burp_dastardly/parser.py | 2 + dojo/tools/burp_graphql/parser.py | 4 +- dojo/tools/cargo_audit/parser.py | 3 +- dojo/tools/checkmarx_one/parser.py | 2 + dojo/tools/checkmarx_osa/parser.py | 3 +- dojo/tools/chefinspect/parser.py | 1 + dojo/tools/clair/clair_parser.py | 2 + dojo/tools/clair/clairklar_parser.py | 2 + dojo/tools/clair/parser.py | 1 + dojo/tools/codechecker/parser.py | 3 +- dojo/tools/contrast/parser.py | 2 +- dojo/tools/cred_scan/parser.py | 2 + dojo/tools/crunch42/parser.py | 1 + dojo/tools/cyclonedx/helpers.py | 4 +- dojo/tools/cyclonedx/json_parser.py | 3 + dojo/tools/cyclonedx/xml_parser.py | 5 +- dojo/tools/dawnscanner/parser.py | 1 + dojo/tools/dependency_check/parser.py | 4 +- dojo/tools/detect_secrets/parser.py | 4 +- dojo/tools/dockerbench/parser.py | 2 +- dojo/tools/dockle/parser.py | 3 +- dojo/tools/dsop/parser.py | 1 + dojo/tools/factory.py | 10 +- dojo/tools/fortify/fpr_parser.py | 2 + dojo/tools/fortify/parser.py | 2 +- dojo/tools/fortify/xml_parser.py | 1 + dojo/tools/gcloud_artifact_scan/parser.py | 1 + dojo/tools/generic/parser.py | 1 + dojo/tools/ggshield/parser.py | 6 +- dojo/tools/github_vulnerability/parser.py | 3 +- dojo/tools/gitlab_container_scan/parser.py | 1 + dojo/tools/gitlab_dast/parser.py | 5 +- .../gitlab_secret_detection_report/parser.py | 1 + dojo/tools/govulncheck/parser.py | 4 +- dojo/tools/hcl_appscan/parser.py | 4 +- dojo/tools/horusec/parser.py | 1 + dojo/tools/humble/parser.py | 3 +- dojo/tools/hydra/parser.py | 5 +- dojo/tools/intsights/parser.py | 1 + .../jfrog_xray_api_summary_artifact/parser.py | 4 +- dojo/tools/kics/parser.py | 3 +- dojo/tools/kubeaudit/parser.py | 1 + dojo/tools/kubehunter/parser.py | 1 + dojo/tools/kubescape/parser.py | 1 + dojo/tools/meterian/parser.py | 2 +- dojo/tools/mobsfscan/parser.py | 3 +- dojo/tools/ms_defender/parser.py | 3 +- dojo/tools/nancy/parser.py | 1 + dojo/tools/netsparker/parser.py | 7 +- dojo/tools/neuvector_compliance/parser.py | 1 - dojo/tools/nexpose/parser.py | 9 +- dojo/tools/nikto/json_parser.py | 1 + dojo/tools/nikto/xml_parser.py | 7 +- dojo/tools/nmap/parser.py | 1 + dojo/tools/noseyparker/parser.py | 2 +- dojo/tools/npm_audit_7_plus/parser.py | 1 + dojo/tools/nuclei/parser.py | 5 +- dojo/tools/openscap/parser.py | 4 +- dojo/tools/openvas/csv_parser.py | 4 +- dojo/tools/openvas/xml_parser.py | 2 + dojo/tools/osv_scanner/parser.py | 1 + dojo/tools/pmd/parser.py | 3 +- dojo/tools/popeye/parser.py | 1 + dojo/tools/pwn_sast/parser.py | 2 +- dojo/tools/qualys/csv_parser.py | 1 + dojo/tools/qualys/parser.py | 3 +- dojo/tools/qualys_webapp/parser.py | 1 + dojo/tools/redhatsatellite/parser.py | 1 + dojo/tools/risk_recon/parser.py | 1 + dojo/tools/rusty_hog/parser.py | 3 +- dojo/tools/sarif/parser.py | 3 +- dojo/tools/snyk/parser.py | 1 + dojo/tools/snyk_code/parser.py | 1 + dojo/tools/solar_appscreener/parser.py | 1 + dojo/tools/sonarqube/parser.py | 13 +- .../tools/sonarqube/sonarqube_restapi_json.py | 3 +- dojo/tools/sonarqube/sonarqube_restapi_zip.py | 3 +- dojo/tools/sonarqube/soprasteria_helper.py | 3 + dojo/tools/sonarqube/soprasteria_html.py | 2 + dojo/tools/sonarqube/soprasteria_json.py | 5 +- dojo/tools/sonatype/parser.py | 1 + dojo/tools/spotbugs/parser.py | 2 + dojo/tools/ssh_audit/parser.py | 1 + dojo/tools/stackhawk/parser.py | 3 +- dojo/tools/sysdig_reports/parser.py | 9 +- .../tools/sysdig_reports/sysdig_csv_parser.py | 1 + dojo/tools/terrascan/parser.py | 3 +- dojo/tools/tfsec/parser.py | 3 +- dojo/tools/tool_issue_updater.py | 7 +- dojo/tools/trivy_operator/parser.py | 5 +- dojo/tools/trustwave_fusion_api/parser.py | 6 +- dojo/tools/veracode/json_parser.py | 3 +- dojo/tools/veracode/xml_parser.py | 4 +- dojo/tools/veracode_sca/parser.py | 5 +- dojo/tools/wapiti/parser.py | 3 +- dojo/tools/wazuh/parser.py | 3 +- dojo/tools/wfuzz/parser.py | 5 +- dojo/tools/whitehat_sentinel/parser.py | 5 +- dojo/tools/wiz/parser.py | 1 + dojo/urls.py | 129 ++++++--- dojo/user/queries.py | 11 +- dojo/user/urls.py | 4 +- dojo/user/validators.py | 3 +- dojo/user/views.py | 46 +-- dojo/utils.py | 78 +++-- dojo/views.py | 27 +- dojo/widgets.py | 2 +- dojo/wsgi.py | 4 +- manage.py | 1 - ruff.toml | 1 + tests/Import_scanner_test.py | 9 +- tests/announcement_banner_test.py | 6 +- tests/base_test_class.py | 9 +- tests/check_various_pages.py | 3 +- tests/close_old_findings_dedupe_test.py | 6 +- tests/close_old_findings_test.py | 6 +- tests/dedupe_test.py | 6 +- tests/endpoint_test.py | 7 +- tests/engagement_test.py | 7 +- tests/environment_test.py | 5 +- tests/false_positive_history_test.py | 9 +- tests/file_test.py | 5 +- tests/finding_test.py | 18 +- tests/group_test.py | 9 +- tests/ibm_appscan_test.py | 8 +- tests/note_type_test.py | 3 +- tests/notes_test.py | 3 +- tests/notifications_test.py | 8 +- tests/product_group_test.py | 11 +- tests/product_member_test.py | 9 +- tests/product_test.py | 9 +- tests/product_type_group_test.py | 9 +- tests/product_type_member_test.py | 7 +- tests/product_type_test.py | 3 +- tests/regulations_test.py | 5 +- tests/report_builder_test.py | 14 +- tests/search_test.py | 3 +- tests/sla_configuration_test.py | 3 +- tests/test_test.py | 7 +- tests/tool_config.py | 7 +- tests/user_test.py | 4 +- tests/zap.py | 7 +- unittests/authorization/test_authorization.py | 43 ++- .../test_authorization_decorators.py | 9 +- .../authorization/test_authorization_tags.py | 17 +- unittests/dojo_test_case.py | 22 +- unittests/test_adminsite.py | 5 +- unittests/test_api_sonarqube_updater.py | 3 +- unittests/test_apiv2_endpoint.py | 2 +- unittests/test_apiv2_limit_reqresp.py | 4 +- unittests/test_apiv2_metadata.py | 2 +- unittests/test_apiv2_methods_and_endpoints.py | 40 +-- unittests/test_apiv2_notifications.py | 2 +- unittests/test_apiv2_scan_import_options.py | 7 +- unittests/test_apiv2_user.py | 2 +- unittests/test_apply_finding_template.py | 21 +- unittests/test_bulk_risk_acceptance_api.py | 15 +- unittests/test_cleanup_alerts.py | 10 +- unittests/test_copy_model.py | 3 +- unittests/test_dashboard.py | 5 +- unittests/test_deduplication_logic.py | 15 +- unittests/test_duplication_loops.py | 8 +- unittests/test_endpoint_meta_import.py | 10 +- unittests/test_endpoint_model.py | 11 +- unittests/test_factory.py | 3 +- .../test_false_positive_history_logic.py | 11 +- unittests/test_finding_helper.py | 13 +- unittests/test_finding_model.py | 7 +- unittests/test_flush_auditlog.py | 16 +- unittests/test_import_reimport.py | 16 +- unittests/test_importers_closeold.py | 6 +- unittests/test_importers_importer.py | 16 +- unittests/test_jira_config_engagement.py | 14 +- unittests/test_jira_config_engagement_epic.py | 8 +- unittests/test_jira_config_product.py | 15 +- unittests/test_jira_import_and_pushing_api.py | 14 +- unittests/test_jira_template.py | 8 +- unittests/test_jira_webhook.py | 10 +- unittests/test_metrics_queries.py | 3 +- unittests/test_migrations.py | 2 +- unittests/test_notifications.py | 9 +- unittests/test_parsers.py | 3 +- unittests/test_remote_user.py | 4 +- unittests/test_rest_framework.py | 162 ++++++++--- unittests/test_risk_acceptance.py | 22 +- unittests/test_sample_data.py | 1 + unittests/test_search_parser.py | 3 +- unittests/test_system_settings.py | 3 +- unittests/test_tags.py | 8 +- unittests/test_tool_config.py | 7 +- unittests/test_user_queries.py | 6 +- unittests/test_user_validators.py | 3 +- unittests/test_utils.py | 32 ++- unittests/test_utils_deduplication_reopen.py | 9 +- unittests/tools/test_acunetix_parser.py | 6 +- unittests/tools/test_anchore_engine_parser.py | 5 +- .../tools/test_anchore_enterprise_parser.py | 7 +- unittests/tools/test_anchore_grype_parser.py | 4 +- .../tools/test_anchorectl_policies_parser.py | 5 +- .../tools/test_anchorectl_vulns_parser.py | 5 +- unittests/tools/test_api_blackduck_parser.py | 2 +- unittests/tools/test_api_bugcrowd_importer.py | 7 +- unittests/tools/test_api_bugcrowd_parser.py | 3 +- unittests/tools/test_api_cobalt_importer.py | 6 +- unittests/tools/test_api_cobalt_parser.py | 6 +- unittests/tools/test_api_edgescan_importer.py | 5 +- unittests/tools/test_api_edgescan_parser.py | 2 +- .../tools/test_api_sonarqube_importer.py | 4 +- unittests/tools/test_api_sonarqube_parser.py | 11 +- unittests/tools/test_api_vulners_parser.py | 5 +- unittests/tools/test_appspider_parser.py | 6 +- unittests/tools/test_aqua_parser.py | 8 +- unittests/tools/test_arachni_parser.py | 6 +- unittests/tools/test_asff_parser.py | 6 +- unittests/tools/test_auditjs_parser.py | 5 +- unittests/tools/test_aws_prowler_parser.py | 6 +- unittests/tools/test_aws_prowler_v3_parser.py | 5 +- unittests/tools/test_aws_scout2_parser.py | 8 +- unittests/tools/test_awssecurityhub_parser.py | 5 +- ..._security_center_recommendations_parser.py | 6 +- unittests/tools/test_bandit_parser.py | 4 +- unittests/tools/test_bearer_cli_parser.py | 3 +- .../test_blackduck_binary_analysis_parser.py | 8 +- .../test_blackduck_component_risk_parser.py | 8 +- unittests/tools/test_blackduck_parser.py | 8 +- unittests/tools/test_brakeman_parser.py | 5 +- unittests/tools/test_bugcrowd_parser.py | 8 +- unittests/tools/test_bundler_audit_parser.py | 6 +- unittests/tools/test_burp_api_parser.py | 6 +- unittests/tools/test_burp_dastardly_parser.py | 3 +- .../tools/test_burp_enterprise_parser.py | 3 +- unittests/tools/test_burp_graphql_parser.py | 3 +- unittests/tools/test_burp_parser.py | 3 +- unittests/tools/test_cargo_audit_parser.py | 5 +- unittests/tools/test_checkmarx_one_parser.py | 1 + unittests/tools/test_checkmarx_osa_parser.py | 7 +- unittests/tools/test_checkov_parser.py | 5 +- unittests/tools/test_chefinspect_parser.py | 5 +- unittests/tools/test_clair_parser.py | 3 +- unittests/tools/test_cloudsploit_parser.py | 3 +- unittests/tools/test_cobalt_parser.py | 5 +- unittests/tools/test_codechecker_parser.py | 5 +- unittests/tools/test_contrast_parser.py | 6 +- unittests/tools/test_coverity_api_parser.py | 3 +- .../tools/test_crashtest_security_parser.py | 5 +- unittests/tools/test_cred_scan_parser.py | 8 +- unittests/tools/test_crunch42_parser.py | 3 +- unittests/tools/test_cyclonedx_parser.py | 5 +- unittests/tools/test_dawnscanner_parser.py | 3 +- .../tools/test_dependency_check_parser.py | 3 +- .../tools/test_dependency_track_parser.py | 5 +- unittests/tools/test_detect_secrets_parser.py | 7 +- unittests/tools/test_dockerbench_parser.py | 5 +- unittests/tools/test_dockle_parser.py | 5 +- unittests/tools/test_drheader_parser.py | 5 +- unittests/tools/test_dsop_parser.py | 4 +- unittests/tools/test_eslint_parser.py | 5 +- unittests/tools/test_fortify_parser.py | 1 + .../tools/test_gcloud_artifact_scan_parser.py | 5 +- unittests/tools/test_generic_parser.py | 6 +- unittests/tools/test_ggshield_parser.py | 5 +- .../tools/test_github_vulnerability_parser.py | 3 +- .../tools/test_gitlab_api_fuzzing_parser.py | 5 +- .../test_gitlab_container_scan_parser.py | 6 +- unittests/tools/test_gitlab_dast_parser.py | 5 +- .../tools/test_gitlab_dep_scan_parser.py | 5 +- unittests/tools/test_gitlab_sast_parser.py | 5 +- ...t_gitlab_secret_detection_report_parser.py | 6 +- unittests/tools/test_gitleaks_parser.py | 5 +- unittests/tools/test_gosec_parser.py | 5 +- unittests/tools/test_govulncheck_parser.py | 4 +- unittests/tools/test_h1_parser.py | 5 +- unittests/tools/test_hadolint_parser.py | 3 +- .../tools/test_harbor_vulnerability_parser.py | 3 +- unittests/tools/test_hcl_appscan_parser.py | 3 +- unittests/tools/test_horusec_parser.py | 3 +- unittests/tools/test_humble_parser.py | 2 +- unittests/tools/test_huskyci_parser.py | 5 +- unittests/tools/test_hydra_parser.py | 4 +- unittests/tools/test_ibm_app_parser.py | 3 +- unittests/tools/test_immuniweb_parser.py | 5 +- unittests/tools/test_intsights_parser.py | 3 +- ..._jfrog_xray_api_summary_artifact_parser.py | 6 +- ...jfrog_xray_on_demand_binary_scan_parser.py | 10 +- .../tools/test_jfrog_xray_unified_parser.py | 4 +- unittests/tools/test_jfrogxray_parser.py | 3 +- unittests/tools/test_kics_parser.py | 5 +- unittests/tools/test_kiuwan_parser.py | 5 +- unittests/tools/test_kubeaudit_parser.py | 5 +- unittests/tools/test_kubebench_parser.py | 5 +- unittests/tools/test_kubehunter_parser.py | 3 +- unittests/tools/test_kubescape_parser.py | 5 +- unittests/tools/test_mend_parser.py | 5 +- unittests/tools/test_meterian_parser.py | 3 +- .../test_microfocus_webinspect_parser.py | 5 +- unittests/tools/test_mobsf_parser.py | 5 +- unittests/tools/test_mobsfscan_parser.py | 5 +- .../tools/test_mozilla_observatory_parser.py | 3 +- unittests/tools/test_ms_defender_parser.py | 5 +- unittests/tools/test_nancy_parser.py | 6 +- unittests/tools/test_netsparker_parser.py | 3 +- .../tools/test_neuvector_compliance_parser.py | 4 +- unittests/tools/test_neuvector_parser.py | 4 +- unittests/tools/test_nexpose_parser.py | 6 +- unittests/tools/test_nikto_parser.py | 5 +- unittests/tools/test_nmap_parser.py | 3 +- unittests/tools/test_noseyparker_parser.py | 3 +- .../tools/test_npm_audit_7_plus_parser.py | 6 +- unittests/tools/test_npm_audit_parser.py | 6 +- unittests/tools/test_nsp_parser.py | 5 +- unittests/tools/test_nuclei_parser.py | 9 +- unittests/tools/test_openscap_parser.py | 5 +- unittests/tools/test_openvas_parser.py | 5 +- unittests/tools/test_ort_parser.py | 5 +- .../tools/test_ossindex_devaudit_parser.py | 5 +- unittests/tools/test_osv_scanner_parser.py | 6 +- unittests/tools/test_outpost24_parser.py | 5 +- .../test_php_security_audit_v2_parser.py | 5 +- .../test_php_symfony_security_check_parser.py | 5 +- unittests/tools/test_pip_audit_parser.py | 4 +- unittests/tools/test_pmd_parser.py | 5 +- unittests/tools/test_popeye_parser.py | 5 +- unittests/tools/test_pwn_sast_parser.py | 5 +- .../test_qualys_infrascan_webgui_parser.py | 6 +- unittests/tools/test_qualys_parser.py | 4 +- unittests/tools/test_qualys_webapp_parser.py | 5 +- .../tools/test_redhatsatellite_parser.py | 5 +- unittests/tools/test_retirejs_parser.py | 3 +- unittests/tools/test_risk_recon_parser.py | 3 +- unittests/tools/test_rubocop_parser.py | 4 +- unittests/tools/test_rusty_hog_parser.py | 5 +- unittests/tools/test_scantist_parser.py | 5 +- unittests/tools/test_scout_suite_parser.py | 3 +- unittests/tools/test_semgrep_parser.py | 5 +- unittests/tools/test_skf_parser.py | 5 +- unittests/tools/test_snyk_code_parser.py | 3 +- unittests/tools/test_snyk_parser.py | 3 +- .../tools/test_solar_appscreener_parser.py | 5 +- unittests/tools/test_sonarqube_parser.py | 6 +- unittests/tools/test_sonatype_parser.py | 3 +- unittests/tools/test_spotbugs_parser.py | 5 +- unittests/tools/test_ssh_audit_parser.py | 5 +- unittests/tools/test_ssl_labs_parser.py | 5 +- unittests/tools/test_sslscan_parser.py | 5 +- unittests/tools/test_sslyze_parser.py | 5 +- unittests/tools/test_stackhawk_parser.py | 2 +- unittests/tools/test_sysdig_reports_parser.py | 3 +- unittests/tools/test_tenable_parser.py | 6 +- unittests/tools/test_terrascan_parser.py | 5 +- unittests/tools/test_testssl_parser.py | 5 +- unittests/tools/test_tfsec_parser.py | 5 +- unittests/tools/test_trivy_operator_parser.py | 5 +- unittests/tools/test_trivy_parser.py | 5 +- unittests/tools/test_trufflehog3_parser.py | 8 +- unittests/tools/test_trufflehog_parser.py | 5 +- .../tools/test_trustwave_fusion_api_parser.py | 5 +- unittests/tools/test_trustwave_parser.py | 5 +- unittests/tools/test_twistlock_parser.py | 4 +- unittests/tools/test_vcg_parser.py | 9 +- unittests/tools/test_veracode_parser.py | 6 +- unittests/tools/test_veracode_sca_parser.py | 7 +- unittests/tools/test_wapiti_parser.py | 5 +- unittests/tools/test_wazuh_parser.py | 5 +- unittests/tools/test_wfuzz_parser.py | 5 +- unittests/tools/test_whispers_parser.py | 3 +- .../tools/test_whitehat_sentinel_parser.py | 4 +- unittests/tools/test_wiz_parser.py | 3 +- unittests/tools/test_wpscan_parser.py | 4 +- unittests/tools/test_xanitizer_parser.py | 5 +- unittests/tools/test_yarn_audit_parser.py | 5 +- unittests/tools/test_zap_parser.py | 5 +- wsgi.py | 1 + 551 files changed, 3089 insertions(+), 1916 deletions(-) diff --git a/dojo/admin.py b/dojo/admin.py index 04ecfcf5c2..68353f24ab 100644 --- a/dojo/admin.py +++ b/dojo/admin.py @@ -1,8 +1,18 @@ from auditlog.models import LogEntry from django.contrib import admin -from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin -from dojo.models import Question, TextQuestion, ChoiceQuestion, Choice, \ - Answer, TextAnswer, ChoiceAnswer, Engagement_Survey, Answered_Survey +from polymorphic.admin import PolymorphicChildModelAdmin, PolymorphicParentModelAdmin + +from dojo.models import ( + Answer, + Answered_Survey, + Choice, + ChoiceAnswer, + ChoiceQuestion, + Engagement_Survey, + Question, + TextAnswer, + TextQuestion, +) admin.site.unregister(LogEntry) diff --git a/dojo/announcement/signals.py b/dojo/announcement/signals.py index 5b89d71d78..580da64a84 100644 --- a/dojo/announcement/signals.py +++ b/dojo/announcement/signals.py @@ -1,7 +1,8 @@ -from dojo.models import Announcement, UserAnnouncement, Dojo_User +from django.conf import settings from django.db.models.signals import post_save from django.dispatch import receiver -from django.conf import settings + +from dojo.models import Announcement, Dojo_User, UserAnnouncement @receiver(post_save, sender=Dojo_User) diff --git a/dojo/announcement/urls.py b/dojo/announcement/urls.py index c62d26f13d..9dc9118765 100644 --- a/dojo/announcement/urls.py +++ b/dojo/announcement/urls.py @@ -1,4 +1,5 @@ from django.urls import re_path + from dojo.announcement import views urlpatterns = [ diff --git a/dojo/announcement/views.py b/dojo/announcement/views.py index 44fc065849..5c01ffaaf4 100644 --- a/dojo/announcement/views.py +++ b/dojo/announcement/views.py @@ -1,18 +1,18 @@ import logging -from django.shortcuts import render from django.contrib import messages +from django.http import HttpResponseRedirect +from django.shortcuts import render from django.urls import reverse -from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext -from django.http import HttpResponseRedirect -from dojo.utils import add_breadcrumb +from django.utils.translation import gettext_lazy as _ -from dojo.forms import AnnouncementCreateForm, AnnouncementRemoveForm -from dojo.models import Announcement, UserAnnouncement from dojo.authorization.authorization_decorators import ( user_is_configuration_authorized, ) +from dojo.forms import AnnouncementCreateForm, AnnouncementRemoveForm +from dojo.models import Announcement, UserAnnouncement +from dojo.utils import add_breadcrumb logger = logging.getLogger(__name__) diff --git a/dojo/api_v2/exception_handler.py b/dojo/api_v2/exception_handler.py index 922ba85888..b4d8143366 100644 --- a/dojo/api_v2/exception_handler.py +++ b/dojo/api_v2/exception_handler.py @@ -1,4 +1,5 @@ -from dojo.models import System_Settings +import logging + from django.core.exceptions import ValidationError from django.db.models.deletion import RestrictedError from rest_framework.response import Response @@ -8,7 +9,8 @@ HTTP_500_INTERNAL_SERVER_ERROR, ) from rest_framework.views import exception_handler -import logging + +from dojo.models import System_Settings logger = logging.getLogger(__name__) diff --git a/dojo/api_v2/mixins.py b/dojo/api_v2/mixins.py index 4e2791aec5..749f7ab8b5 100644 --- a/dojo/api_v2/mixins.py +++ b/dojo/api_v2/mixins.py @@ -1,12 +1,14 @@ -from django.db import DEFAULT_DB_ALIAS +import itertools + from django.contrib.admin.utils import NestedObjects +from django.db import DEFAULT_DB_ALIAS from drf_spectacular.utils import extend_schema -from rest_framework.decorators import action from rest_framework import status from rest_framework.authtoken.models import Token +from rest_framework.decorators import action + from dojo.api_v2 import serializers -from dojo.models import Question, Answer -import itertools +from dojo.models import Answer, Question class DeletePreviewModelMixin: diff --git a/dojo/api_v2/permissions.py b/dojo/api_v2/permissions.py index 89267e68cd..dc02801386 100644 --- a/dojo/api_v2/permissions.py +++ b/dojo/api_v2/permissions.py @@ -1,39 +1,41 @@ import re + +from django.shortcuts import get_object_or_404 +from rest_framework import permissions, serializers from rest_framework.exceptions import ( ParseError, PermissionDenied, ValidationError, ) + from dojo.api_v2.serializers import ( get_import_meta_data_from_dict, get_product_id_from_dict, ) +from dojo.authorization.authorization import ( + user_has_configuration_permission, + user_has_global_permission, + user_has_permission, +) +from dojo.authorization.roles_permissions import Permissions from dojo.importers.reimporter.utils import ( get_target_engagement_if_exists, get_target_product_by_id_if_exists, get_target_product_if_exists, - get_target_test_if_exists, get_target_product_type_if_exists, + get_target_test_if_exists, ) from dojo.models import ( + Cred_Mapping, + Dojo_Group, Endpoint, Engagement, Finding, Finding_Group, - Product_Type, Product, + Product_Type, Test, - Dojo_Group, - Cred_Mapping, ) -from django.shortcuts import get_object_or_404 -from rest_framework import permissions, serializers -from dojo.authorization.authorization import ( - user_has_global_permission, - user_has_permission, - user_has_configuration_permission, -) -from dojo.authorization.roles_permissions import Permissions def check_post_permission(request, post_model, post_pk, post_permission): diff --git a/dojo/api_v2/prefetch/mixins.py b/dojo/api_v2/prefetch/mixins.py index b43a44c7d7..b54d82a2e8 100644 --- a/dojo/api_v2/prefetch/mixins.py +++ b/dojo/api_v2/prefetch/mixins.py @@ -1,5 +1,6 @@ -from rest_framework.response import Response from rest_framework.mixins import ListModelMixin, RetrieveModelMixin +from rest_framework.response import Response + from .prefetcher import _Prefetcher diff --git a/dojo/api_v2/prefetch/prefetcher.py b/dojo/api_v2/prefetch/prefetcher.py index c97cc3fab7..1b207c394d 100644 --- a/dojo/api_v2/prefetch/prefetcher.py +++ b/dojo/api_v2/prefetch/prefetcher.py @@ -1,8 +1,10 @@ -from rest_framework.serializers import ModelSerializer -from . import utils import inspect import sys +from rest_framework.serializers import ModelSerializer + +from . import utils + # Reduce the scope of search for serializers. SERIALIZER_DEFS_MODULE = "dojo.api_v2.serializers" diff --git a/dojo/api_v2/serializers.py b/dojo/api_v2/serializers.py index dc949649ee..f6544e60b9 100644 --- a/dojo/api_v2/serializers.py +++ b/dojo/api_v2/serializers.py @@ -1,13 +1,38 @@ +import json +import logging import re -from dojo.finding.queries import get_authorized_findings -from dojo.group.utils import get_auth_group_name -from django.contrib.auth.models import Group +from datetime import datetime from typing import List + +import six +import tagulous +from django.conf import settings +from django.contrib.auth.models import Group, Permission +from django.contrib.auth.password_validation import validate_password +from django.core.exceptions import PermissionDenied, ValidationError +from django.db.utils import IntegrityError +from django.urls import reverse +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ from drf_spectacular.utils import extend_schema_field +from rest_framework import serializers from rest_framework.exceptions import NotFound from rest_framework.fields import DictField, MultipleChoiceField -from datetime import datetime -from dojo.endpoint.utils import endpoint_filter + +import dojo.jira_link.helper as jira_helper +from dojo.authorization.authorization import user_has_permission +from dojo.authorization.roles_permissions import Permissions +from dojo.endpoint.utils import endpoint_filter, endpoint_meta_import +from dojo.finding.helper import ( + save_vulnerability_ids, + save_vulnerability_ids_template, +) +from dojo.finding.queries import get_authorized_findings +from dojo.group.utils import get_auth_group_name +from dojo.importers.importer.importer import DojoDefaultImporter as Importer +from dojo.importers.reimporter.reimporter import ( + DojoDefaultReImporter as ReImporter, +) from dojo.importers.reimporter.utils import ( get_or_create_engagement, get_target_engagement_if_exists, @@ -16,113 +41,86 @@ get_target_test_if_exists, ) from dojo.models import ( + DEFAULT_NOTIFICATION, IMPORT_ACTIONS, + NOTIFICATION_CHOICES, SEVERITIES, - SLA_Configuration, + SEVERITY_CHOICES, STATS_FIELDS, + Announcement, + Answer, + Answered_Survey, + App_Analysis, + Check_List, + ChoiceAnswer, + ChoiceQuestion, + Cred_Mapping, + Cred_User, + Development_Environment, + Dojo_Group, + Dojo_Group_Member, Dojo_User, - Finding_Group, - Product, + DojoMeta, + Endpoint, + Endpoint_Params, + Endpoint_Status, Engagement, - Test, + Engagement_Presets, + Engagement_Survey, + FileUpload, Finding, - User, - Stub_Finding, - Risk_Acceptance, + Finding_Group, Finding_Template, - Test_Type, - Development_Environment, - NoteHistory, - JIRA_Issue, - Tool_Product_Settings, - Tool_Configuration, - Tool_Type, - Product_Type, + General_Survey, + Global_Role, JIRA_Instance, - Endpoint, + JIRA_Issue, JIRA_Project, - Cred_Mapping, - Notes, - DojoMeta, + Language_Type, + Languages, + Network_Locations, Note_Type, - App_Analysis, - Endpoint_Status, - Cred_User, + NoteHistory, + Notes, + Notifications, + Product, + Product_API_Scan_Configuration, + Product_Group, + Product_Member, + Product_Type, + Product_Type_Group, + Product_Type_Member, + Question, + Regulation, + Risk_Acceptance, + Role, + SLA_Configuration, Sonarqube_Issue, Sonarqube_Issue_Transition, - Endpoint_Params, - Regulation, + Stub_Finding, System_Settings, - FileUpload, - SEVERITY_CHOICES, + Test, Test_Import, Test_Import_Finding_Action, - Product_Type_Member, - Product_Member, - Product_Group, - Product_Type_Group, - Dojo_Group, - Role, - Global_Role, - Dojo_Group_Member, - Language_Type, - Languages, - Notifications, - NOTIFICATION_CHOICES, - Engagement_Presets, - Network_Locations, + Test_Type, + TextAnswer, + TextQuestion, + Tool_Configuration, + Tool_Product_Settings, + Tool_Type, + User, UserContactInfo, - Product_API_Scan_Configuration, - DEFAULT_NOTIFICATION, Vulnerability_Id, Vulnerability_Id_Template, get_current_date, - Question, - TextQuestion, - ChoiceQuestion, - Answer, - TextAnswer, - ChoiceAnswer, - Engagement_Survey, - Answered_Survey, - General_Survey, - Check_List, - Announcement, ) - from dojo.tools.factory import ( - requires_file, get_choices_sorted, + requires_file, requires_tool_type, ) -from dojo.utils import is_scan_file_too_large -from django.conf import settings -from rest_framework import serializers -from django.core.exceptions import ValidationError, PermissionDenied -from django.contrib.auth.password_validation import validate_password -from django.contrib.auth.models import Permission -from django.utils import timezone -from django.urls import reverse -from django.db.utils import IntegrityError -import six -from django.utils.translation import gettext_lazy as _ -import json -import dojo.jira_link.helper as jira_helper -import logging -import tagulous -from dojo.endpoint.utils import endpoint_meta_import -from dojo.importers.importer.importer import DojoDefaultImporter as Importer -from dojo.importers.reimporter.reimporter import ( - DojoDefaultReImporter as ReImporter, -) -from dojo.authorization.authorization import user_has_permission -from dojo.authorization.roles_permissions import Permissions -from dojo.finding.helper import ( - save_vulnerability_ids, - save_vulnerability_ids_template, -) from dojo.user.utils import get_configuration_permissions_codenames - +from dojo.utils import is_scan_file_too_large logger = logging.getLogger(__name__) deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") diff --git a/dojo/api_v2/views.py b/dojo/api_v2/views.py index 334c4d746b..38abf945c7 100644 --- a/dojo/api_v2/views.py +++ b/dojo/api_v2/views.py @@ -1,170 +1,174 @@ -from rest_framework.generics import GenericAPIView -from drf_spectacular.types import OpenApiTypes +import base64 +import logging +import mimetypes +from datetime import datetime + +import tagulous from crum import get_current_user -from django.http import HttpResponse, Http404, FileResponse -from django.shortcuts import get_object_or_404 -from django.utils import timezone +from dateutil.relativedelta import relativedelta +from django.conf import settings from django.contrib.auth.models import Permission from django.core.exceptions import ValidationError -from rest_framework import viewsets, mixins, status -from rest_framework.response import Response from django.db import IntegrityError -from rest_framework.permissions import DjangoModelPermissions, IsAuthenticated +from django.http import FileResponse, Http404, HttpResponse +from django.shortcuts import get_object_or_404 +from django.utils import timezone +from django_filters.rest_framework import DjangoFilterBackend +from drf_spectacular.renderers import OpenApiJsonRenderer2 +from drf_spectacular.types import OpenApiTypes +from drf_spectacular.utils import ( + OpenApiParameter, + OpenApiResponse, + extend_schema, + extend_schema_view, +) +from drf_spectacular.views import SpectacularAPIView +from rest_framework import mixins, status, viewsets from rest_framework.decorators import action +from rest_framework.generics import GenericAPIView from rest_framework.parsers import MultiPartParser -from django_filters.rest_framework import DjangoFilterBackend -import base64 -import mimetypes +from rest_framework.permissions import DjangoModelPermissions, IsAuthenticated +from rest_framework.response import Response + +import dojo.jira_link.helper as jira_helper +from dojo.api_v2 import ( + mixins as dojo_mixins, +) +from dojo.api_v2 import ( + permissions, + prefetch, + serializers, +) +from dojo.authorization.roles_permissions import Permissions +from dojo.cred.queries import get_authorized_cred_mappings +from dojo.endpoint.queries import ( + get_authorized_endpoint_status, + get_authorized_endpoints, +) +from dojo.endpoint.views import get_endpoint_ids +from dojo.engagement.queries import get_authorized_engagements from dojo.engagement.services import close_engagement, reopen_engagement +from dojo.filters import ( + ApiAppAnalysisFilter, + ApiCredentialsFilter, + ApiEndpointFilter, + ApiEngagementFilter, + ApiFindingFilter, + ApiProductFilter, + ApiRiskAcceptanceFilter, + ApiTemplateFindingFilter, + ApiTestFilter, + ReportFindingFilter, +) +from dojo.finding.queries import ( + get_authorized_findings, + get_authorized_stub_findings, +) +from dojo.finding.views import ( + duplicate_cluster, + reset_finding_duplicate_status_internal, + set_finding_as_original_internal, +) +from dojo.group.queries import ( + get_authorized_group_members, + get_authorized_groups, +) from dojo.importers.reimporter.utils import ( get_target_engagement_if_exists, get_target_product_if_exists, get_target_test_if_exists, ) +from dojo.jira_link.queries import ( + get_authorized_jira_issues, + get_authorized_jira_projects, +) from dojo.models import ( + Announcement, + Answer, + Answered_Survey, + App_Analysis, + BurpRawRequestResponse, + Check_List, + Cred_Mapping, + Cred_User, + Development_Environment, + Dojo_Group, + Dojo_Group_Member, + Dojo_User, + DojoMeta, + Endpoint, + Endpoint_Status, + Engagement, + Engagement_Presets, + Engagement_Survey, + FileUpload, + Finding, + Finding_Template, + General_Survey, + Global_Role, + JIRA_Instance, + JIRA_Issue, + JIRA_Project, Language_Type, Languages, + Network_Locations, + Note_Type, + Notes, Notifications, Product, + Product_API_Scan_Configuration, + Product_Group, + Product_Member, Product_Type, - Engagement, + Product_Type_Group, + Product_Type_Member, + Question, + Regulation, + Risk_Acceptance, + Role, SLA_Configuration, + Sonarqube_Issue, + Sonarqube_Issue_Transition, + Stub_Finding, + System_Settings, Test, Test_Import, Test_Type, - Finding, - User, - Stub_Finding, - Finding_Template, - Notes, - JIRA_Issue, - Tool_Product_Settings, Tool_Configuration, + Tool_Product_Settings, Tool_Type, - Endpoint, - JIRA_Project, - JIRA_Instance, - DojoMeta, - Development_Environment, - Dojo_User, - Note_Type, - System_Settings, - App_Analysis, - Endpoint_Status, - Sonarqube_Issue, - Sonarqube_Issue_Transition, - Regulation, - Risk_Acceptance, - BurpRawRequestResponse, - FileUpload, - Product_Type_Member, - Product_Member, - Dojo_Group, - Product_Group, - Product_Type_Group, - Role, - Global_Role, - Dojo_Group_Member, - Engagement_Presets, - Network_Locations, + User, UserContactInfo, - Product_API_Scan_Configuration, - Cred_Mapping, - Cred_User, - Question, - Answer, - Engagement_Survey, - Answered_Survey, - General_Survey, - Check_List, - Announcement, -) -from dojo.endpoint.views import get_endpoint_ids -from dojo.reports.views import ( - report_url_resolver, - prefetch_related_findings_for_report, -) -from dojo.finding.views import ( - set_finding_as_original_internal, - reset_finding_duplicate_status_internal, - duplicate_cluster, -) -from dojo.filters import ( - ReportFindingFilter, - ApiCredentialsFilter, - ApiFindingFilter, - ApiProductFilter, - ApiEngagementFilter, - ApiEndpointFilter, - ApiAppAnalysisFilter, - ApiTestFilter, - ApiTemplateFindingFilter, - ApiRiskAcceptanceFilter, -) -from dojo.risk_acceptance import api as ra_api -from dateutil.relativedelta import relativedelta -from django.conf import settings -from datetime import datetime -from dojo.utils import ( - get_system_setting, - get_setting, - async_delete, -) -from dojo.api_v2 import ( - serializers, - permissions, - prefetch, - mixins as dojo_mixins, -) -import dojo.jira_link.helper as jira_helper -import logging -import tagulous -from dojo.product_type.queries import ( - get_authorized_product_types, - get_authorized_product_type_members, - get_authorized_product_type_groups, ) from dojo.product.queries import ( - get_authorized_products, get_authorized_app_analysis, get_authorized_dojo_meta, - get_authorized_product_members, - get_authorized_product_groups, - get_authorized_languages, get_authorized_engagement_presets, + get_authorized_languages, get_authorized_product_api_scan_configurations, + get_authorized_product_groups, + get_authorized_product_members, + get_authorized_products, ) -from dojo.engagement.queries import get_authorized_engagements -from dojo.risk_acceptance.queries import get_authorized_risk_acceptances -from dojo.test.queries import get_authorized_tests, get_authorized_test_imports -from dojo.finding.queries import ( - get_authorized_findings, - get_authorized_stub_findings, -) -from dojo.endpoint.queries import ( - get_authorized_endpoints, - get_authorized_endpoint_status, -) -from dojo.group.queries import ( - get_authorized_groups, - get_authorized_group_members, +from dojo.product_type.queries import ( + get_authorized_product_type_groups, + get_authorized_product_type_members, + get_authorized_product_types, ) -from dojo.jira_link.queries import ( - get_authorized_jira_projects, - get_authorized_jira_issues, +from dojo.reports.views import ( + prefetch_related_findings_for_report, + report_url_resolver, ) +from dojo.risk_acceptance import api as ra_api +from dojo.risk_acceptance.queries import get_authorized_risk_acceptances +from dojo.test.queries import get_authorized_test_imports, get_authorized_tests from dojo.tool_product.queries import get_authorized_tool_product_settings -from dojo.cred.queries import get_authorized_cred_mappings -from drf_spectacular.utils import ( - OpenApiParameter, - OpenApiResponse, - extend_schema, - extend_schema_view, -) -from drf_spectacular.views import SpectacularAPIView -from drf_spectacular.renderers import OpenApiJsonRenderer2 -from dojo.authorization.roles_permissions import Permissions from dojo.user.utils import get_configuration_permissions_codenames +from dojo.utils import ( + async_delete, + get_setting, + get_system_setting, +) logger = logging.getLogger(__name__) diff --git a/dojo/apps.py b/dojo/apps.py index 693d0328de..aea61e29f8 100644 --- a/dojo/apps.py +++ b/dojo/apps.py @@ -73,8 +73,8 @@ def ready(self): # Importing the signals file is good enough if using the reciever decorator import dojo.announcement.signals # noqa: F401 import dojo.product.signals # noqa: F401 - import dojo.test.signals # noqa: F401 import dojo.sla_config.helpers # noqa: F401 + import dojo.test.signals # noqa: F401 def get_model_fields_with_extra(model, extra_fields=()): diff --git a/dojo/authorization/authorization.py b/dojo/authorization/authorization.py index 8974f2c478..2888513715 100644 --- a/dojo/authorization/authorization.py +++ b/dojo/authorization/authorization.py @@ -1,5 +1,5 @@ from django.core.exceptions import PermissionDenied -from dojo.request_cache import cache_for_request + from dojo.authorization.roles_permissions import ( Permissions, Roles, @@ -7,25 +7,26 @@ get_roles_with_permissions, ) from dojo.models import ( - Product_Type, - Product_Type_Member, - Product, - Product_Member, + App_Analysis, + Cred_Mapping, + Dojo_Group, + Dojo_Group_Member, + Endpoint, Engagement, - Test, Finding, - Endpoint, Finding_Group, + Languages, + Product, + Product_API_Scan_Configuration, Product_Group, + Product_Member, + Product_Type, Product_Type_Group, - Dojo_Group, - Dojo_Group_Member, - Languages, - App_Analysis, + Product_Type_Member, Stub_Finding, - Product_API_Scan_Configuration, - Cred_Mapping, + Test, ) +from dojo.request_cache import cache_for_request def user_has_configuration_permission(user, permission): diff --git a/dojo/authorization/authorization_decorators.py b/dojo/authorization/authorization_decorators.py index ec2c26aefd..3fa1926ec8 100644 --- a/dojo/authorization/authorization_decorators.py +++ b/dojo/authorization/authorization_decorators.py @@ -1,10 +1,12 @@ import functools + from django.core.exceptions import PermissionDenied from django.shortcuts import get_object_or_404 + from dojo.authorization.authorization import ( + user_has_configuration_permission, user_has_global_permission_or_403, user_has_permission_or_403, - user_has_configuration_permission, ) diff --git a/dojo/banner/urls.py b/dojo/banner/urls.py index 4b99585db9..309f735263 100644 --- a/dojo/banner/urls.py +++ b/dojo/banner/urls.py @@ -1,4 +1,5 @@ from django.urls import re_path + from dojo.banner import views urlpatterns = [ diff --git a/dojo/banner/views.py b/dojo/banner/views.py index bfd4616062..5d81a1cd6e 100644 --- a/dojo/banner/views.py +++ b/dojo/banner/views.py @@ -1,16 +1,16 @@ import logging -from django.shortcuts import render, get_object_or_404 from django.contrib import messages -from django.urls import reverse from django.http import HttpResponseRedirect -from dojo.utils import add_breadcrumb +from django.shortcuts import get_object_or_404, render +from django.urls import reverse -from dojo.forms import LoginBanner -from dojo.models import BannerConf from dojo.authorization.authorization_decorators import ( user_is_configuration_authorized, ) +from dojo.forms import LoginBanner +from dojo.models import BannerConf +from dojo.utils import add_breadcrumb logger = logging.getLogger(__name__) diff --git a/dojo/benchmark/urls.py b/dojo/benchmark/urls.py index f30e3fa8c8..8b51e3e593 100644 --- a/dojo/benchmark/urls.py +++ b/dojo/benchmark/urls.py @@ -1,4 +1,5 @@ from django.urls import re_path + from . import views urlpatterns = [ diff --git a/dojo/benchmark/views.py b/dojo/benchmark/views.py index 86961e66fe..2169fd34d0 100644 --- a/dojo/benchmark/views.py +++ b/dojo/benchmark/views.py @@ -1,30 +1,30 @@ import logging + +from crum import get_current_user from django.contrib import messages -from django.urls import reverse -from django.http import HttpResponseRedirect, JsonResponse -from django.shortcuts import render, get_object_or_404 from django.db.models import Count, Q +from django.http import HttpResponseRedirect, JsonResponse +from django.shortcuts import get_object_or_404, render +from django.urls import reverse from django.utils.translation import gettext as _ +from dojo.authorization.authorization_decorators import user_is_authorized +from dojo.authorization.roles_permissions import Permissions from dojo.forms import Benchmark_Product_SummaryForm, DeleteBenchmarkForm from dojo.models import ( - Benchmark_Type, Benchmark_Category, - Benchmark_Requirement, Benchmark_Product, - Product, Benchmark_Product_Summary, + Benchmark_Requirement, + Benchmark_Type, + Product, ) +from dojo.templatetags.display_tags import asvs_level from dojo.utils import ( - add_breadcrumb, Product_Tab, + add_breadcrumb, redirect_to_return_url_or_else, ) -from dojo.authorization.authorization_decorators import user_is_authorized -from dojo.authorization.roles_permissions import Permissions -from dojo.templatetags.display_tags import asvs_level - -from crum import get_current_user logger = logging.getLogger(__name__) diff --git a/dojo/celery.py b/dojo/celery.py index 1fbf6e73fc..b2c742a792 100644 --- a/dojo/celery.py +++ b/dojo/celery.py @@ -1,8 +1,9 @@ +import logging import os + from celery import Celery from celery.signals import setup_logging from django.conf import settings -import logging logger = logging.getLogger(__name__) diff --git a/dojo/components/urls.py b/dojo/components/urls.py index 0183e3e807..c13ee47e0e 100644 --- a/dojo/components/urls.py +++ b/dojo/components/urls.py @@ -1,4 +1,5 @@ from django.urls import re_path + from dojo.components import views urlpatterns = [ diff --git a/dojo/components/views.py b/dojo/components/views.py index 82898f6fa8..d4a7490fbb 100644 --- a/dojo/components/views.py +++ b/dojo/components/views.py @@ -1,13 +1,14 @@ -from django.shortcuts import render +from django.contrib.postgres.aggregates import StringAgg +from django.db import connection from django.db.models import Count, Q from django.db.models.expressions import Value -from dojo.utils import add_breadcrumb, get_page_items, get_system_setting -from dojo.filters import ComponentFilter, ComponentFilterWithoutObjectLookups +from django.shortcuts import render + +from dojo.authorization.roles_permissions import Permissions from dojo.components.sql_group_concat import Sql_GroupConcat -from django.db import connection -from django.contrib.postgres.aggregates import StringAgg +from dojo.filters import ComponentFilter, ComponentFilterWithoutObjectLookups from dojo.finding.queries import get_authorized_findings -from dojo.authorization.roles_permissions import Permissions +from dojo.utils import add_breadcrumb, get_page_items, get_system_setting def components(request): diff --git a/dojo/cred/queries.py b/dojo/cred/queries.py index 7127c86e5f..d86c432fc6 100644 --- a/dojo/cred/queries.py +++ b/dojo/cred/queries.py @@ -1,8 +1,8 @@ from crum import get_current_user from django.db.models import Exists, OuterRef, Q -from dojo.models import Cred_Mapping, Product_Member, Product_Type_Member, \ - Product_Group, Product_Type_Group + from dojo.authorization.authorization import get_roles_for_permission, user_has_global_permission +from dojo.models import Cred_Mapping, Product_Group, Product_Member, Product_Type_Group, Product_Type_Member def get_authorized_cred_mappings(permission, queryset=None): diff --git a/dojo/cred/urls.py b/dojo/cred/urls.py index 3459418bd2..65a3d4300f 100644 --- a/dojo/cred/urls.py +++ b/dojo/cred/urls.py @@ -1,4 +1,5 @@ from django.urls import re_path + from . import views urlpatterns = [ diff --git a/dojo/cred/views.py b/dojo/cred/views.py index 53d3315be1..26d5d62f87 100644 --- a/dojo/cred/views.py +++ b/dojo/cred/views.py @@ -1,19 +1,17 @@ import logging + from django.contrib import messages -from django.urls import reverse from django.http import HttpResponseRedirect -from django.shortcuts import render, get_object_or_404 +from django.shortcuts import get_object_or_404, render +from django.urls import reverse from django.utils import timezone -from dojo.models import Finding, Product, Engagement, Cred_User, Cred_Mapping, Test -from dojo.utils import add_breadcrumb, Product_Tab -from dojo.forms import CredUserForm, NoteForm, CredMappingFormProd, CredMappingForm -from dojo.utils import dojo_crypto_encrypt, prepare_for_view -from dojo.authorization.authorization_decorators import user_is_authorized +from dojo.authorization.authorization_decorators import user_is_authorized, user_is_configuration_authorized from dojo.authorization.roles_permissions import Permissions -from dojo.authorization.authorization_decorators import user_is_configuration_authorized from dojo.cred.queries import get_authorized_cred_mappings - +from dojo.forms import CredMappingForm, CredMappingFormProd, CredUserForm, NoteForm +from dojo.models import Cred_Mapping, Cred_User, Engagement, Finding, Product, Test +from dojo.utils import Product_Tab, add_breadcrumb, dojo_crypto_encrypt, prepare_for_view logger = logging.getLogger(__name__) diff --git a/dojo/decorators.py b/dojo/decorators.py index fddb253723..664989f8ff 100644 --- a/dojo/decorators.py +++ b/dojo/decorators.py @@ -1,21 +1,20 @@ +import logging from functools import wraps -from dojo.models import Finding, Dojo_User -from django.db import models -from django.conf import settings -from django_ratelimit.exceptions import Ratelimited -from django_ratelimit.core import is_ratelimited +from django.conf import settings +from django.db import models from django_ratelimit import UNSAFE +from django_ratelimit.core import is_ratelimited +from django_ratelimit.exceptions import Ratelimited -import logging - +from dojo.models import Dojo_User, Finding logger = logging.getLogger(__name__) def we_want_async(*args, func=None, **kwargs): - from dojo.utils import get_current_user from dojo.models import Dojo_User + from dojo.utils import get_current_user sync = kwargs.get('sync', False) if sync: diff --git a/dojo/development_environment/views.py b/dojo/development_environment/views.py index 8de454f1a8..1bf998fadf 100644 --- a/dojo/development_environment/views.py +++ b/dojo/development_environment/views.py @@ -1,19 +1,19 @@ # #dev envs import logging -from django.contrib.auth.decorators import login_required from django.contrib import messages -from django.urls import reverse -from django.http import HttpResponseRedirect -from django.shortcuts import render, get_object_or_404 +from django.contrib.auth.decorators import login_required from django.db.models.deletion import RestrictedError +from django.http import HttpResponseRedirect +from django.shortcuts import get_object_or_404, render +from django.urls import reverse -from dojo.filters import DevelopmentEnvironmentFilter -from dojo.forms import Development_EnvironmentForm, Delete_Dev_EnvironmentForm -from dojo.models import Development_Environment -from dojo.utils import get_page_items, add_breadcrumb from dojo.authorization.authorization import user_has_configuration_permission_or_403 from dojo.authorization.authorization_decorators import user_is_configuration_authorized +from dojo.filters import DevelopmentEnvironmentFilter +from dojo.forms import Delete_Dev_EnvironmentForm, Development_EnvironmentForm +from dojo.models import Development_Environment +from dojo.utils import add_breadcrumb, get_page_items logger = logging.getLogger(__name__) diff --git a/dojo/endpoint/queries.py b/dojo/endpoint/queries.py index fa1b02c2be..e9facac14f 100644 --- a/dojo/endpoint/queries.py +++ b/dojo/endpoint/queries.py @@ -1,8 +1,15 @@ from crum import get_current_user from django.db.models import Exists, OuterRef, Q -from dojo.models import Endpoint, Endpoint_Status, Product_Member, Product_Type_Member, \ - Product_Group, Product_Type_Group + from dojo.authorization.authorization import get_roles_for_permission, user_has_global_permission +from dojo.models import ( + Endpoint, + Endpoint_Status, + Product_Group, + Product_Member, + Product_Type_Group, + Product_Type_Member, +) def get_authorized_endpoints(permission, queryset=None, user=None): diff --git a/dojo/endpoint/utils.py b/dojo/endpoint/utils.py index 9fd400979d..e34f478f33 100644 --- a/dojo/endpoint/utils.py +++ b/dojo/endpoint/utils.py @@ -1,19 +1,17 @@ -import logging -import re import csv import io +import logging +import re -from django.urls import reverse from django.contrib import messages -from django.core.exceptions import MultipleObjectsReturned -from hyperlink._url import SCHEME_PORT_MAP - +from django.core.exceptions import MultipleObjectsReturned, ValidationError from django.core.validators import validate_ipv46_address -from django.core.exceptions import ValidationError -from django.db.models import Q, Count +from django.db.models import Count, Q from django.http import HttpResponseRedirect +from django.urls import reverse +from hyperlink._url import SCHEME_PORT_MAP -from dojo.models import Endpoint, DojoMeta +from dojo.models import DojoMeta, Endpoint logger = logging.getLogger(__name__) diff --git a/dojo/endpoint/views.py b/dojo/endpoint/views.py index 076f42772d..d8c8deaba6 100644 --- a/dojo/endpoint/views.py +++ b/dojo/endpoint/views.py @@ -1,30 +1,38 @@ import logging from datetime import datetime + from dateutil.relativedelta import relativedelta -from django.contrib import messages +from django.apps import apps from django.conf import settings -from django.urls import reverse -from django.http import HttpResponseRedirect -from django.shortcuts import render, get_object_or_404 -from django.utils import timezone +from django.contrib import messages from django.contrib.admin.utils import NestedObjects from django.db import DEFAULT_DB_ALIAS -from django.db.models import Q, QuerySet, Count +from django.db.models import Count, Q, QuerySet +from django.http import HttpResponseRedirect +from django.shortcuts import get_object_or_404, render +from django.urls import reverse +from django.utils import timezone -from dojo.endpoint.utils import clean_hosts_run, endpoint_meta_import -from dojo.filters import EndpointFilter, EndpointFilterWithoutObjectLookups -from dojo.forms import EditEndpointForm, \ - DeleteEndpointForm, AddEndpointForm, DojoMetaDataForm, ImportEndpointMetaForm -from dojo.models import Product, Endpoint, Finding, DojoMeta, Endpoint_Status -from dojo.utils import get_page_items, add_breadcrumb, get_period_counts, Product_Tab, calculate_grade, redirect, \ - add_error_message_to_response, is_scan_file_too_large, get_system_setting -from dojo.notifications.helper import create_notification +from dojo.authorization.authorization import user_has_permission_or_403 from dojo.authorization.authorization_decorators import user_is_authorized from dojo.authorization.roles_permissions import Permissions -from dojo.authorization.authorization import user_has_permission_or_403 from dojo.endpoint.queries import get_authorized_endpoints -from django.apps import apps - +from dojo.endpoint.utils import clean_hosts_run, endpoint_meta_import +from dojo.filters import EndpointFilter, EndpointFilterWithoutObjectLookups +from dojo.forms import AddEndpointForm, DeleteEndpointForm, DojoMetaDataForm, EditEndpointForm, ImportEndpointMetaForm +from dojo.models import DojoMeta, Endpoint, Endpoint_Status, Finding, Product +from dojo.notifications.helper import create_notification +from dojo.utils import ( + Product_Tab, + add_breadcrumb, + add_error_message_to_response, + calculate_grade, + get_page_items, + get_period_counts, + get_system_setting, + is_scan_file_too_large, + redirect, +) logger = logging.getLogger(__name__) diff --git a/dojo/engagement/queries.py b/dojo/engagement/queries.py index 54b66ecd08..d5a7f44593 100644 --- a/dojo/engagement/queries.py +++ b/dojo/engagement/queries.py @@ -1,8 +1,8 @@ from crum import get_current_user from django.db.models import Exists, OuterRef, Q -from dojo.models import Engagement, Product_Member, Product_Type_Member, \ - Product_Group, Product_Type_Group + from dojo.authorization.authorization import get_roles_for_permission, user_has_global_permission +from dojo.models import Engagement, Product_Group, Product_Member, Product_Type_Group, Product_Type_Member def get_authorized_engagements(permission): diff --git a/dojo/engagement/services.py b/dojo/engagement/services.py index 8ae54bb963..0331e87c5b 100644 --- a/dojo/engagement/services.py +++ b/dojo/engagement/services.py @@ -3,8 +3,9 @@ from django.db.models.signals import pre_save from django.dispatch import receiver -from dojo.models import Engagement + import dojo.jira_link.helper as jira_helper +from dojo.models import Engagement logger = logging.getLogger(__name__) diff --git a/dojo/engagement/views.py b/dojo/engagement/views.py index 49752edbb9..4f38ec4d32 100644 --- a/dojo/engagement/views.py +++ b/dojo/engagement/views.py @@ -1,70 +1,108 @@ -import logging import csv +import logging +import operator import re -from typing import List -from django.views import View -from openpyxl import Workbook -from openpyxl.styles import Font +from datetime import datetime +from functools import reduce from tempfile import NamedTemporaryFile +from time import strftime +from typing import List -from datetime import datetime -import operator -from django.contrib.auth.models import User from django.conf import settings from django.contrib import messages -from django.core.exceptions import ValidationError, PermissionDenied -from django.urls import reverse, Resolver404 -from django.db.models import Q, Count -from django.http import HttpResponseRedirect, StreamingHttpResponse, HttpResponse, FileResponse, QueryDict, HttpRequest -from django.shortcuts import render, get_object_or_404 -from django.views.decorators.cache import cache_page -from django.utils import timezone -from time import strftime from django.contrib.admin.utils import NestedObjects +from django.contrib.auth.models import User +from django.core.exceptions import PermissionDenied, ValidationError from django.db import DEFAULT_DB_ALIAS +from django.db.models import Count, Q +from django.db.models.query import Prefetch, QuerySet +from django.http import FileResponse, HttpRequest, HttpResponse, HttpResponseRedirect, QueryDict, StreamingHttpResponse +from django.shortcuts import get_object_or_404, render +from django.urls import Resolver404, reverse +from django.utils import timezone +from django.views import View +from django.views.decorators.cache import cache_page +from django.views.decorators.vary import vary_on_cookie +from openpyxl import Workbook +from openpyxl.styles import Font +import dojo.jira_link.helper as jira_helper +import dojo.notifications.helper as notifications_helper +import dojo.risk_acceptance.helper as ra_helper +from dojo.authorization.authorization import user_has_permission_or_403 +from dojo.authorization.authorization_decorators import user_is_authorized +from dojo.authorization.roles_permissions import Permissions +from dojo.endpoint.utils import save_endpoints_to_add +from dojo.engagement.queries import get_authorized_engagements from dojo.engagement.services import close_engagement, reopen_engagement from dojo.filters import ( - EngagementFilter, - EngagementFilterWithoutObjectLookups, EngagementDirectFilter, EngagementDirectFilterWithoutObjectLookups, + EngagementFilter, + EngagementFilterWithoutObjectLookups, EngagementTestFilter, - EngagementTestFilterWithoutObjectLookups + EngagementTestFilterWithoutObjectLookups, ) -from dojo.forms import CheckForm, \ - UploadThreatForm, RiskAcceptanceForm, NoteForm, DoneForm, \ - EngForm, TestForm, ReplaceRiskAcceptanceProofForm, AddFindingsRiskAcceptanceForm, DeleteEngagementForm, ImportScanForm, \ - CredMappingForm, JIRAEngagementForm, JIRAImportScanForm, TypedNoteForm, JIRAProjectForm, \ - EditRiskAcceptanceForm - -from dojo.models import Finding, Product, Engagement, Test, \ - Check_List, Test_Import, Notes, \ - Risk_Acceptance, Development_Environment, Endpoint, \ - Cred_Mapping, System_Settings, Note_Type, Product_API_Scan_Configuration -from dojo.tools.factory import get_scan_types_sorted -from dojo.utils import add_error_message_to_response, add_success_message_to_response, get_page_items, add_breadcrumb, handle_uploaded_threat, \ - FileIterWrapper, get_cal_event, Product_Tab, is_scan_file_too_large, async_delete, \ - get_system_setting, get_setting, redirect_to_return_url_or_else, get_return_url, calculate_grade -from dojo.notifications.helper import create_notification -from dojo.finding.views import find_available_notetypes -from functools import reduce -from django.db.models.query import Prefetch, QuerySet -import dojo.jira_link.helper as jira_helper -import dojo.risk_acceptance.helper as ra_helper -from dojo.risk_acceptance.helper import prefetch_for_expiration from dojo.finding.helper import NOT_ACCEPTED_FINDINGS_QUERY -from django.views.decorators.vary import vary_on_cookie -from dojo.authorization.authorization import user_has_permission_or_403 -from dojo.authorization.roles_permissions import Permissions +from dojo.finding.views import find_available_notetypes +from dojo.forms import ( + AddFindingsRiskAcceptanceForm, + CheckForm, + CredMappingForm, + DeleteEngagementForm, + DoneForm, + EditRiskAcceptanceForm, + EngForm, + ImportScanForm, + JIRAEngagementForm, + JIRAImportScanForm, + JIRAProjectForm, + NoteForm, + ReplaceRiskAcceptanceProofForm, + RiskAcceptanceForm, + TestForm, + TypedNoteForm, + UploadThreatForm, +) +from dojo.importers.importer.importer import DojoDefaultImporter as Importer +from dojo.models import ( + Check_List, + Cred_Mapping, + Development_Environment, + Endpoint, + Engagement, + Finding, + Note_Type, + Notes, + Product, + Product_API_Scan_Configuration, + Risk_Acceptance, + System_Settings, + Test, + Test_Import, +) +from dojo.notifications.helper import create_notification from dojo.product.queries import get_authorized_products -from dojo.engagement.queries import get_authorized_engagements +from dojo.risk_acceptance.helper import prefetch_for_expiration +from dojo.tools.factory import get_scan_types_sorted from dojo.user.queries import get_authorized_users -from dojo.authorization.authorization_decorators import user_is_authorized -from dojo.importers.importer.importer import DojoDefaultImporter as Importer -import dojo.notifications.helper as notifications_helper -from dojo.endpoint.utils import save_endpoints_to_add - +from dojo.utils import ( + FileIterWrapper, + Product_Tab, + add_breadcrumb, + add_error_message_to_response, + add_success_message_to_response, + async_delete, + calculate_grade, + get_cal_event, + get_page_items, + get_return_url, + get_setting, + get_system_setting, + handle_uploaded_threat, + is_scan_file_too_large, + redirect_to_return_url_or_else, +) logger = logging.getLogger(__name__) diff --git a/dojo/filters.py b/dojo/filters.py index c58e8ea37f..0613034032 100644 --- a/dojo/filters.py +++ b/dojo/filters.py @@ -1,50 +1,95 @@ import collections +import decimal +import logging import warnings -from dojo.risk_acceptance.queries import get_authorized_risk_acceptances -from drf_spectacular.types import OpenApiTypes +from datetime import datetime, timedelta -from drf_spectacular.utils import extend_schema_field -from dojo.finding.helper import ACCEPTED_FINDINGS_QUERY, NOT_ACCEPTED_FINDINGS_QUERY, WAS_ACCEPTED_FINDINGS_QUERY, CLOSED_FINDINGS_QUERY, FALSE_POSITIVE_FINDINGS_QUERY, INACTIVE_FINDINGS_QUERY, OPEN_FINDINGS_QUERY, OUT_OF_SCOPE_FINDINGS_QUERY, VERIFIED_FINDINGS_QUERY, UNDER_REVIEW_QUERY -import logging -from datetime import timedelta, datetime +import pytz +import six +import tagulous +from auditlog.models import LogEntry from django import forms from django.apps import apps -from auditlog.models import LogEntry from django.conf import settings -import six -from django.utils.translation import gettext_lazy as _ +from django.contrib.contenttypes.models import ContentType +from django.db.models import JSONField, Q +from django.forms import HiddenInput from django.utils import timezone -from django_filters import FilterSet, CharFilter, OrderingFilter, \ - ModelMultipleChoiceFilter, ModelChoiceFilter, MultipleChoiceFilter, \ - BooleanFilter, NumberFilter, DateFilter, RangeFilter +from django.utils.translation import gettext_lazy as _ +from django_filters import ( + BooleanFilter, + CharFilter, + DateFilter, + FilterSet, + ModelChoiceFilter, + ModelMultipleChoiceFilter, + MultipleChoiceFilter, + NumberFilter, + OrderingFilter, + RangeFilter, +) from django_filters import rest_framework as filters from django_filters.filters import ChoiceFilter, _truncate -from django.db.models import JSONField -import pytz -from django.db.models import Q -from dojo.models import Dojo_User, Finding_Group, Product_API_Scan_Configuration, Product_Type, Finding, Product, Test_Import, Test_Type, \ - Endpoint, Development_Environment, Finding_Template, Note_Type, Risk_Acceptance, Cred_Mapping, \ - Engagement_Survey, Question, TextQuestion, ChoiceQuestion, Endpoint_Status, Engagement, \ - ENGAGEMENT_STATUS_CHOICES, Test, App_Analysis, SEVERITY_CHOICES, EFFORT_FOR_FIXING_CHOICES, Dojo_Group, Vulnerability_Id, \ - Test_Import_Finding_Action, IMPORT_ACTIONS -from dojo.utils import get_system_setting -from django.contrib.contenttypes.models import ContentType -import tagulous +from drf_spectacular.types import OpenApiTypes +from drf_spectacular.utils import extend_schema_field from polymorphic.base import ManagerInheritanceWarning + # from tagulous.forms import TagWidget # import tagulous from dojo.authorization.roles_permissions import Permissions -from dojo.product_type.queries import get_authorized_product_types -from dojo.product.queries import get_authorized_products +from dojo.endpoint.queries import get_authorized_endpoints from dojo.engagement.queries import get_authorized_engagements -from dojo.test.queries import get_authorized_tests +from dojo.finding.helper import ( + ACCEPTED_FINDINGS_QUERY, + CLOSED_FINDINGS_QUERY, + FALSE_POSITIVE_FINDINGS_QUERY, + INACTIVE_FINDINGS_QUERY, + NOT_ACCEPTED_FINDINGS_QUERY, + OPEN_FINDINGS_QUERY, + OUT_OF_SCOPE_FINDINGS_QUERY, + UNDER_REVIEW_QUERY, + VERIFIED_FINDINGS_QUERY, + WAS_ACCEPTED_FINDINGS_QUERY, +) from dojo.finding.queries import get_authorized_findings -from dojo.endpoint.queries import get_authorized_endpoints from dojo.finding_group.queries import get_authorized_finding_groups +from dojo.models import ( + EFFORT_FOR_FIXING_CHOICES, + ENGAGEMENT_STATUS_CHOICES, + IMPORT_ACTIONS, + SEVERITY_CHOICES, + App_Analysis, + ChoiceQuestion, + Cred_Mapping, + Development_Environment, + Dojo_Group, + Dojo_User, + Endpoint, + Endpoint_Status, + Engagement, + Engagement_Survey, + Finding, + Finding_Group, + Finding_Template, + Note_Type, + Product, + Product_API_Scan_Configuration, + Product_Type, + Question, + Risk_Acceptance, + Test, + Test_Import, + Test_Import_Finding_Action, + Test_Type, + TextQuestion, + Vulnerability_Id, +) +from dojo.product.queries import get_authorized_products +from dojo.product_type.queries import get_authorized_product_types +from dojo.risk_acceptance.queries import get_authorized_risk_acceptances +from dojo.test.queries import get_authorized_tests from dojo.user.queries import get_authorized_users -from django.forms import HiddenInput -from dojo.utils import is_finding_groups_enabled -import decimal +from dojo.utils import get_system_setting, is_finding_groups_enabled logger = logging.getLogger(__name__) diff --git a/dojo/finding/helper.py b/dojo/finding/helper.py index 48a6c25786..1a5ffb4c2e 100644 --- a/dojo/finding/helper.py +++ b/dojo/finding/helper.py @@ -1,19 +1,29 @@ +import logging +from time import strftime + +from django.conf import settings from django.db.models.query_utils import Q from django.db.models.signals import post_delete, pre_delete from django.dispatch.dispatcher import receiver -from dojo.celery import app -from dojo.decorators import dojo_async_task, dojo_model_from_id, dojo_model_to_id -import dojo.jira_link.helper as jira_helper -import logging -from time import strftime from django.utils import timezone -from django.conf import settings from fieldsignals import pre_save_changed -from dojo.utils import get_current_user, mass_model_updater, to_str_typed -from dojo.models import Engagement, Finding, Finding_Group, System_Settings, Test, Endpoint, Endpoint_Status, \ - Vulnerability_Id, Vulnerability_Id_Template -from dojo.endpoint.utils import save_endpoints_to_add +import dojo.jira_link.helper as jira_helper +from dojo.celery import app +from dojo.decorators import dojo_async_task, dojo_model_from_id, dojo_model_to_id +from dojo.endpoint.utils import save_endpoints_to_add +from dojo.models import ( + Endpoint, + Endpoint_Status, + Engagement, + Finding, + Finding_Group, + System_Settings, + Test, + Vulnerability_Id, + Vulnerability_Id_Template, +) +from dojo.utils import get_current_user, mass_model_updater, to_str_typed logger = logging.getLogger(__name__) deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") diff --git a/dojo/finding/queries.py b/dojo/finding/queries.py index 7994eec895..e10cfca3dd 100644 --- a/dojo/finding/queries.py +++ b/dojo/finding/queries.py @@ -1,8 +1,16 @@ from crum import get_current_user from django.db.models import Exists, OuterRef, Q -from dojo.models import Finding, Product_Member, Product_Type_Member, Stub_Finding, \ - Product_Group, Product_Type_Group, Vulnerability_Id + from dojo.authorization.authorization import get_roles_for_permission, user_has_global_permission +from dojo.models import ( + Finding, + Product_Group, + Product_Member, + Product_Type_Group, + Product_Type_Member, + Stub_Finding, + Vulnerability_Id, +) def get_authorized_groups(permission, user=None): diff --git a/dojo/finding/views.py b/dojo/finding/views.py index efe026e9ec..f28a37c2fb 100644 --- a/dojo/finding/views.py +++ b/dojo/finding/views.py @@ -1,132 +1,128 @@ # # findings import base64 +import contextlib +import copy import json import logging import mimetypes -import contextlib from collections import OrderedDict, defaultdict -from django.db import models -from django.db.models.functions import Length +from itertools import chain + from django.conf import settings from django.contrib import messages -from django.core.exceptions import PermissionDenied, ValidationError from django.core import serializers +from django.core.exceptions import PermissionDenied, ValidationError +from django.db import models +from django.db.models import Count, Q, QuerySet +from django.db.models.functions import Length +from django.db.models.query import Prefetch +from django.http import Http404, HttpRequest, HttpResponse, HttpResponseRedirect, JsonResponse, StreamingHttpResponse +from django.shortcuts import get_object_or_404, render +from django.template.defaultfilters import pluralize from django.urls import reverse -from django.http import Http404, HttpResponse, JsonResponse, HttpRequest -from django.http import HttpResponseRedirect -from django.http import StreamingHttpResponse -from django.shortcuts import render, get_object_or_404 -from django.utils import formats +from django.utils import formats, timezone from django.utils.safestring import mark_safe -from django.utils import timezone -from django.views.decorators.http import require_POST from django.views import View -from itertools import chain +from django.views.decorators.http import require_POST from imagekit import ImageSpec from imagekit.processors import ResizeToFill -from dojo.utils import ( - add_error_message_to_response, - add_field_errors_to_response, - add_success_message_to_response, - close_external_issue, - redirect, - reopen_external_issue, - do_false_positive_history, - match_finding_to_existing_findings, - get_page_items_and_count, + +import dojo.finding.helper as finding_helper +import dojo.jira_link.helper as jira_helper +import dojo.risk_acceptance.helper as ra_helper +from dojo.authorization.authorization import user_has_permission_or_403 +from dojo.authorization.authorization_decorators import ( + user_has_global_permission, + user_is_authorized, ) -import copy +from dojo.authorization.roles_permissions import Permissions from dojo.filters import ( - TemplateFindingFilter, - SimilarFindingFilter, - SimilarFindingFilterWithoutObjectLookups, - FindingFilter, - FindingFilterWithoutObjectLookups, AcceptedFindingFilter, AcceptedFindingFilterWithoutObjectLookups, - TestImportFindingActionFilter, + FindingFilter, + FindingFilterWithoutObjectLookups, + SimilarFindingFilter, + SimilarFindingFilterWithoutObjectLookups, + TemplateFindingFilter, TestImportFilter, + TestImportFindingActionFilter, ) +from dojo.finding.queries import get_authorized_findings from dojo.forms import ( - EditPlannedRemediationDateFindingForm, - NoteForm, - TypedNoteForm, - CloseFindingForm, - FindingForm, - PromoteFindingForm, - FindingTemplateForm, - DeleteFindingTemplateForm, - JIRAFindingForm, - GITHUBFindingForm, - ReviewFindingForm, + ApplyFindingTemplateForm, ClearFindingReviewForm, + CloseFindingForm, + CopyFindingForm, DefectFindingForm, - StubFindingForm, DeleteFindingForm, + DeleteFindingTemplateForm, DeleteStubFindingForm, - ApplyFindingTemplateForm, - FindingFormID, + EditPlannedRemediationDateFindingForm, FindingBulkUpdateForm, + FindingForm, + FindingFormID, + FindingTemplateForm, + GITHUBFindingForm, + JIRAFindingForm, MergeFindings, - CopyFindingForm, + NoteForm, + PromoteFindingForm, + ReviewFindingForm, + StubFindingForm, + TypedNoteForm, ) from dojo.models import ( IMPORT_UNTOUCHED_FINDING, - Finding, - Finding_Group, - Notes, - NoteHistory, - Note_Type, BurpRawRequestResponse, - Stub_Finding, + Cred_Mapping, + Dojo_User, Endpoint, - Finding_Template, Endpoint_Status, + Engagement, FileAccessToken, - GITHUB_PKey, + Finding, + Finding_Group, + Finding_Template, GITHUB_Issue, - Dojo_User, - Cred_Mapping, - Test, + GITHUB_PKey, + Note_Type, + NoteHistory, + Notes, Product, + Stub_Finding, + System_Settings, + Test, Test_Import, Test_Import_Finding_Action, User, - Engagement, Vulnerability_Id_Template, - System_Settings, ) +from dojo.notifications.helper import create_notification +from dojo.test.queries import get_authorized_tests from dojo.utils import ( - get_page_items, - add_breadcrumb, FileIterWrapper, - process_notifications, - get_system_setting, - apply_cwe_to_template, Product_Tab, + add_breadcrumb, + add_error_message_to_response, + add_external_issue, + add_field_errors_to_response, + add_success_message_to_response, + apply_cwe_to_template, calculate_grade, - redirect_to_return_url_or_else, + close_external_issue, + do_false_positive_history, + get_page_items, + get_page_items_and_count, get_return_url, - add_external_issue, - update_external_issue, + get_system_setting, get_words_for_field, + match_finding_to_existing_findings, + process_notifications, + redirect, + redirect_to_return_url_or_else, + reopen_external_issue, + update_external_issue, ) -from dojo.notifications.helper import create_notification - -from django.template.defaultfilters import pluralize -from django.db.models import Q, QuerySet, Count -from django.db.models.query import Prefetch -import dojo.jira_link.helper as jira_helper -import dojo.risk_acceptance.helper as ra_helper -import dojo.finding.helper as finding_helper -from dojo.authorization.authorization import user_has_permission_or_403 -from dojo.authorization.authorization_decorators import ( - user_is_authorized, - user_has_global_permission, -) -from dojo.authorization.roles_permissions import Permissions -from dojo.finding.queries import get_authorized_findings -from dojo.test.queries import get_authorized_tests JFORM_PUSH_TO_JIRA_MESSAGE = "jform.push_to_jira: %s" diff --git a/dojo/finding_group/queries.py b/dojo/finding_group/queries.py index a6eadebb20..9bc4b95ffa 100644 --- a/dojo/finding_group/queries.py +++ b/dojo/finding_group/queries.py @@ -1,8 +1,8 @@ from crum import get_current_user from django.db.models import Exists, OuterRef, Q -from dojo.models import Finding_Group, Product_Member, Product_Type_Member, \ - Product_Group, Product_Type_Group + from dojo.authorization.authorization import get_roles_for_permission, user_has_global_permission +from dojo.models import Finding_Group, Product_Group, Product_Member, Product_Type_Group, Product_Type_Member def get_authorized_finding_groups(permission, queryset=None, user=None): diff --git a/dojo/finding_group/views.py b/dojo/finding_group/views.py index c49698e77f..8dfe80a317 100644 --- a/dojo/finding_group/views.py +++ b/dojo/finding_group/views.py @@ -1,8 +1,5 @@ -from dojo.utils import Product_Tab, add_breadcrumb, get_words_for_field, get_page_items, get_system_setting -from dojo.forms import DeleteFindingGroupForm, EditFindingGroupForm, FindingBulkUpdateForm -from dojo.notifications.helper import create_notification -from dojo.finding.views import prefetch_for_findings -from dojo.filters import FindingFilter, FindingFilterWithoutObjectLookups +import logging + from django.contrib import messages from django.contrib.admin.utils import NestedObjects from django.db.utils import DEFAULT_DB_ALIAS @@ -10,12 +7,17 @@ from django.shortcuts import get_object_or_404, render from django.urls.base import reverse from django.views.decorators.http import require_POST -from dojo.models import Finding_Group, Product, Engagement, Finding, GITHUB_PKey -import logging + import dojo.jira_link.helper as jira_helper +from dojo.authorization.authorization import user_has_permission_or_403 from dojo.authorization.authorization_decorators import user_is_authorized from dojo.authorization.roles_permissions import Permissions -from dojo.authorization.authorization import user_has_permission_or_403 +from dojo.filters import FindingFilter, FindingFilterWithoutObjectLookups +from dojo.finding.views import prefetch_for_findings +from dojo.forms import DeleteFindingGroupForm, EditFindingGroupForm, FindingBulkUpdateForm +from dojo.models import Engagement, Finding, Finding_Group, GITHUB_PKey, Product +from dojo.notifications.helper import create_notification +from dojo.utils import Product_Tab, add_breadcrumb, get_page_items, get_system_setting, get_words_for_field logger = logging.getLogger(__name__) diff --git a/dojo/forms.py b/dojo/forms.py index 2a09eeafe7..7189c3b50e 100644 --- a/dojo/forms.py +++ b/dojo/forms.py @@ -1,58 +1,108 @@ +import logging import os -import re -from datetime import datetime, date import pickle +import re import warnings -from dojo.widgets import TableCheckboxWidget -from crispy_forms.bootstrap import InlineRadios, InlineCheckboxes +from datetime import date, datetime + +import tagulous +from crispy_forms.bootstrap import InlineCheckboxes, InlineRadios from crispy_forms.helper import FormHelper from crispy_forms.layout import Layout -from django.db.models import Count, Q +from crum import get_current_user from dateutil.relativedelta import relativedelta from django import forms -from django.contrib.auth.password_validation import validate_password +from django.conf import settings from django.contrib.auth.models import Permission +from django.contrib.auth.password_validation import validate_password from django.core import validators from django.core.exceptions import ValidationError +from django.db.models import Count, Q from django.forms import modelformset_factory -from django.forms.widgets import Widget, Select +from django.forms.widgets import Select, Widget +from django.urls import reverse +from django.utils import timezone from django.utils.dates import MONTHS from django.utils.safestring import mark_safe -from django.utils import timezone from django.utils.translation import gettext_lazy as _ from polymorphic.base import ManagerInheritanceWarning -import tagulous - -from dojo.endpoint.utils import endpoint_get_or_create, endpoint_filter, \ - validate_endpoints_to_add -from dojo.models import Announcement, Finding, Finding_Group, Product_Type, Product, Note_Type, \ - Check_List, SLA_Configuration, User, Engagement, Test, Test_Type, Notes, Risk_Acceptance, \ - Development_Environment, Dojo_User, Endpoint, Stub_Finding, Finding_Template, \ - JIRA_Issue, JIRA_Project, JIRA_Instance, GITHUB_Issue, GITHUB_PKey, GITHUB_Conf, UserContactInfo, Tool_Type, \ - Tool_Configuration, Tool_Product_Settings, Cred_User, Cred_Mapping, System_Settings, Notifications, \ - App_Analysis, Objects_Product, Benchmark_Product, Benchmark_Requirement, \ - Benchmark_Product_Summary, Engagement_Presets, DojoMeta, \ - Engagement_Survey, Answered_Survey, TextAnswer, ChoiceAnswer, Choice, Question, TextQuestion, \ - ChoiceQuestion, General_Survey, Regulation, FileUpload, SEVERITY_CHOICES, EFFORT_FOR_FIXING_CHOICES, Product_Type_Member, \ - Product_Member, Global_Role, Dojo_Group, Product_Group, Product_Type_Group, Dojo_Group_Member, \ - Product_API_Scan_Configuration - -from dojo.tools.factory import requires_file, get_choices_sorted, requires_tool_type -from django.urls import reverse from tagulous.forms import TagField -import logging -from crum import get_current_user -from dojo.utils import get_system_setting, get_product, is_finding_groups_enabled, \ - get_password_requirements_string -from django.conf import settings + +import dojo.jira_link.helper as jira_helper from dojo.authorization.roles_permissions import Permissions -from dojo.product_type.queries import get_authorized_product_types -from dojo.product.queries import get_authorized_products +from dojo.endpoint.utils import endpoint_filter, endpoint_get_or_create, validate_endpoints_to_add from dojo.finding.queries import get_authorized_findings -from dojo.user.queries import get_authorized_users_for_product_and_product_type, get_authorized_users -from dojo.user.utils import get_configuration_permissions_fields from dojo.group.queries import get_authorized_groups, get_group_member_roles -import dojo.jira_link.helper as jira_helper +from dojo.models import ( + EFFORT_FOR_FIXING_CHOICES, + SEVERITY_CHOICES, + Announcement, + Answered_Survey, + App_Analysis, + Benchmark_Product, + Benchmark_Product_Summary, + Benchmark_Requirement, + Check_List, + Choice, + ChoiceAnswer, + ChoiceQuestion, + Cred_Mapping, + Cred_User, + Development_Environment, + Dojo_Group, + Dojo_Group_Member, + Dojo_User, + DojoMeta, + Endpoint, + Engagement, + Engagement_Presets, + Engagement_Survey, + FileUpload, + Finding, + Finding_Group, + Finding_Template, + General_Survey, + GITHUB_Conf, + GITHUB_Issue, + GITHUB_PKey, + Global_Role, + JIRA_Instance, + JIRA_Issue, + JIRA_Project, + Note_Type, + Notes, + Notifications, + Objects_Product, + Product, + Product_API_Scan_Configuration, + Product_Group, + Product_Member, + Product_Type, + Product_Type_Group, + Product_Type_Member, + Question, + Regulation, + Risk_Acceptance, + SLA_Configuration, + Stub_Finding, + System_Settings, + Test, + Test_Type, + TextAnswer, + TextQuestion, + Tool_Configuration, + Tool_Product_Settings, + Tool_Type, + User, + UserContactInfo, +) +from dojo.product.queries import get_authorized_products +from dojo.product_type.queries import get_authorized_product_types +from dojo.tools.factory import get_choices_sorted, requires_file, requires_tool_type +from dojo.user.queries import get_authorized_users, get_authorized_users_for_product_and_product_type +from dojo.user.utils import get_configuration_permissions_fields +from dojo.utils import get_password_requirements_string, get_product, get_system_setting, is_finding_groups_enabled +from dojo.widgets import TableCheckboxWidget logger = logging.getLogger(__name__) diff --git a/dojo/github.py b/dojo/github.py index 512393d20b..d6737bf639 100644 --- a/dojo/github.py +++ b/dojo/github.py @@ -2,12 +2,13 @@ import logging import sys +from django.template.loader import render_to_string + # External libs from github import Github # Dojo related imports -from dojo.models import Engagement, Product, GITHUB_PKey, GITHUB_Issue -from django.template.loader import render_to_string +from dojo.models import Engagement, GITHUB_Issue, GITHUB_PKey, Product # Create global logger = logging.getLogger(__name__) diff --git a/dojo/github_issue_link/urls.py b/dojo/github_issue_link/urls.py index 05f70a58cf..e5ffebb94c 100644 --- a/dojo/github_issue_link/urls.py +++ b/dojo/github_issue_link/urls.py @@ -1,4 +1,5 @@ from django.urls import re_path + from . import views urlpatterns = [ diff --git a/dojo/github_issue_link/views.py b/dojo/github_issue_link/views.py index e2e13ea948..aa4e9269cb 100644 --- a/dojo/github_issue_link/views.py +++ b/dojo/github_issue_link/views.py @@ -4,18 +4,19 @@ # Third party imports from django.contrib import messages from django.contrib.admin.utils import NestedObjects -from django.urls import reverse from django.db import DEFAULT_DB_ALIAS -from django.http import HttpResponseRedirect, HttpResponse -from django.shortcuts import render, get_object_or_404 +from django.http import HttpResponse, HttpResponseRedirect +from django.shortcuts import get_object_or_404, render +from django.urls import reverse from django.views.decorators.csrf import csrf_exempt from github import Github +from dojo.authorization.authorization_decorators import user_is_configuration_authorized + # Local application/library imports -from dojo.forms import GITHUBForm, DeleteGITHUBConfForm +from dojo.forms import DeleteGITHUBConfForm, GITHUBForm from dojo.models import GITHUB_Conf from dojo.utils import add_breadcrumb -from dojo.authorization.authorization_decorators import user_is_configuration_authorized logger = logging.getLogger(__name__) diff --git a/dojo/group/queries.py b/dojo/group/queries.py index dd1114ad74..db4d8d633d 100644 --- a/dojo/group/queries.py +++ b/dojo/group/queries.py @@ -1,8 +1,9 @@ from crum import get_current_user from django.db.models import Exists, OuterRef -from dojo.models import Dojo_Group, Dojo_Group_Member, Product_Group, Product_Type_Group, Role + from dojo.authorization.authorization import get_roles_for_permission from dojo.authorization.roles_permissions import Permissions +from dojo.models import Dojo_Group, Dojo_Group_Member, Product_Group, Product_Type_Group, Role def get_authorized_groups(permission): diff --git a/dojo/group/utils.py b/dojo/group/utils.py index bf46fc7150..09ea0e7939 100644 --- a/dojo/group/utils.py +++ b/dojo/group/utils.py @@ -1,9 +1,10 @@ from crum import get_current_user +from django.conf import settings from django.contrib.auth.models import Group -from django.db.models.signals import post_save, post_delete +from django.db.models.signals import post_delete, post_save from django.dispatch import receiver + from dojo.models import Dojo_Group, Dojo_Group_Member, Role -from django.conf import settings def get_auth_group_name(group, attempt=0): diff --git a/dojo/group/views.py b/dojo/group/views.py index d454a8d977..46d2dd3196 100644 --- a/dojo/group/views.py +++ b/dojo/group/views.py @@ -1,30 +1,46 @@ import logging -from django.views import View -from django.db.models.query import QuerySet + from django.contrib import messages +from django.contrib.admin.utils import NestedObjects from django.contrib.auth.decorators import user_passes_test from django.contrib.auth.models import Group -from django.db.models.deletion import RestrictedError -from django.urls import reverse -from django.http import HttpResponseRedirect, HttpRequest from django.core.exceptions import PermissionDenied -from django.shortcuts import render, get_object_or_404 -from django.contrib.admin.utils import NestedObjects from django.db import DEFAULT_DB_ALIAS +from django.db.models.deletion import RestrictedError +from django.db.models.query import QuerySet +from django.http import HttpRequest, HttpResponseRedirect +from django.shortcuts import get_object_or_404, render +from django.urls import reverse +from django.views import View + +from dojo.authorization.authorization import ( + user_has_configuration_permission, + user_has_permission, + user_has_permission_or_403, +) +from dojo.authorization.authorization_decorators import user_is_authorized, user_is_configuration_authorized from dojo.authorization.roles_permissions import Permissions -from dojo.authorization.authorization import user_has_permission -from dojo.authorization.authorization_decorators import user_is_authorized from dojo.filters import GroupFilter -from dojo.forms import DojoGroupForm, DeleteGroupForm, Add_Product_Group_GroupForm, \ - Add_Product_Type_Group_GroupForm, Add_Group_MemberForm, Edit_Group_MemberForm, \ - Delete_Group_MemberForm, GlobalRoleForm, ConfigurationPermissionsForm -from dojo.models import Dojo_Group, Product_Group, Product_Type_Group, Dojo_Group_Member, Global_Role -from dojo.utils import get_page_items, add_breadcrumb, is_title_in_breadcrumbs, redirect_to_return_url_or_else -from dojo.group.queries import get_authorized_groups, get_product_groups_for_group, \ - get_product_type_groups_for_group, get_group_members_for_group -from dojo.authorization.authorization_decorators import user_is_configuration_authorized -from dojo.authorization.authorization import user_has_configuration_permission, user_has_permission_or_403 +from dojo.forms import ( + Add_Group_MemberForm, + Add_Product_Group_GroupForm, + Add_Product_Type_Group_GroupForm, + ConfigurationPermissionsForm, + Delete_Group_MemberForm, + DeleteGroupForm, + DojoGroupForm, + Edit_Group_MemberForm, + GlobalRoleForm, +) +from dojo.group.queries import ( + get_authorized_groups, + get_group_members_for_group, + get_product_groups_for_group, + get_product_type_groups_for_group, +) from dojo.group.utils import get_auth_group_name +from dojo.models import Dojo_Group, Dojo_Group_Member, Global_Role, Product_Group, Product_Type_Group +from dojo.utils import add_breadcrumb, get_page_items, is_title_in_breadcrumbs, redirect_to_return_url_or_else logger = logging.getLogger(__name__) diff --git a/dojo/home/views.py b/dojo/home/views.py index 1048b9e1cc..26039f4a28 100644 --- a/dojo/home/views.py +++ b/dojo/home/views.py @@ -3,19 +3,18 @@ from typing import Dict from dateutil.relativedelta import relativedelta - -from django.urls import reverse -from django.http import HttpResponseRedirect, HttpResponse, HttpRequest +from django.db.models import Count, Q +from django.http import HttpRequest, HttpResponse, HttpResponseRedirect from django.shortcuts import render +from django.urls import reverse from django.utils import timezone -from django.db.models import Count, Q -from dojo.utils import add_breadcrumb, get_punchcard_data -from dojo.models import Answered_Survey +from dojo.authorization.authorization import user_has_configuration_permission from dojo.authorization.roles_permissions import Permissions from dojo.engagement.queries import get_authorized_engagements from dojo.finding.queries import get_authorized_findings -from dojo.authorization.authorization import user_has_configuration_permission +from dojo.models import Answered_Survey +from dojo.utils import add_breadcrumb, get_punchcard_data def home(request: HttpRequest) -> HttpResponse: diff --git a/dojo/importers/importer/importer.py b/dojo/importers/importer/importer.py index c2d55d5f30..19c5acac1a 100644 --- a/dojo/importers/importer/importer.py +++ b/dojo/importers/importer/importer.py @@ -1,23 +1,22 @@ import base64 +import logging -from django.db.models.query_utils import Q -from dojo.importers import utils as importer_utils -from dojo.decorators import dojo_async_task -from dojo.utils import get_current_user, is_finding_groups_enabled -from dojo.celery import app -from django.core.exceptions import ValidationError +from django.conf import settings from django.core import serializers +from django.core.exceptions import ValidationError +from django.core.files.base import ContentFile +from django.db.models.query_utils import Q +from django.utils import timezone + import dojo.finding.helper as finding_helper import dojo.jira_link.helper as jira_helper import dojo.notifications.helper as notifications_helper -from django.conf import settings -from django.core.files.base import ContentFile -from django.utils import timezone -from dojo.models import (BurpRawRequestResponse, FileUpload, - Finding, Test, Test_Import, Test_Type) +from dojo.celery import app +from dojo.decorators import dojo_async_task +from dojo.importers import utils as importer_utils +from dojo.models import BurpRawRequestResponse, FileUpload, Finding, Test, Test_Import, Test_Type from dojo.tools.factory import get_parser -import logging - +from dojo.utils import get_current_user, is_finding_groups_enabled logger = logging.getLogger(__name__) deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") diff --git a/dojo/importers/reimporter/reimporter.py b/dojo/importers/reimporter/reimporter.py index 8061123aaf..c24f5f961a 100644 --- a/dojo/importers/reimporter/reimporter.py +++ b/dojo/importers/reimporter/reimporter.py @@ -1,22 +1,23 @@ import base64 import logging -import dojo.finding.helper as finding_helper -import dojo.jira_link.helper as jira_helper -import dojo.notifications.helper as notifications_helper -from dojo.decorators import dojo_async_task -from dojo.celery import app from django.conf import settings -from django.core.exceptions import ValidationError from django.core import serializers +from django.core.exceptions import ValidationError from django.core.files.base import ContentFile +from django.db.models import Q from django.utils import timezone + +import dojo.finding.helper as finding_helper +import dojo.jira_link.helper as jira_helper +import dojo.notifications.helper as notifications_helper +from dojo.celery import app +from dojo.decorators import dojo_async_task from dojo.importers import utils as importer_utils from dojo.importers.reimporter import utils as reimporter_utils from dojo.models import BurpRawRequestResponse, FileUpload, Finding, Notes, Test_Import from dojo.tools.factory import get_parser from dojo.utils import get_current_user, is_finding_groups_enabled -from django.db.models import Q logger = logging.getLogger(__name__) deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") diff --git a/dojo/importers/reimporter/utils.py b/dojo/importers/reimporter/utils.py index 8f332150aa..4ec9ce1752 100644 --- a/dojo/importers/reimporter/utils.py +++ b/dojo/importers/reimporter/utils.py @@ -1,15 +1,16 @@ +import logging from datetime import timedelta + from crum import get_current_user from django.conf import settings -from dojo.importers import utils as importer_utils -from dojo.models import Engagement, Finding, Q, Product, Product_Member, Product_Type, Product_Type_Member, Role, Test from django.utils import timezone -from dojo.decorators import dojo_async_task + from dojo.celery import app -import logging +from dojo.decorators import dojo_async_task +from dojo.importers import utils as importer_utils +from dojo.models import Engagement, Finding, Product, Product_Member, Product_Type, Product_Type_Member, Q, Role, Test from dojo.utils import get_last_object_or_none, get_object_or_none - logger = logging.getLogger(__name__) deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") diff --git a/dojo/importers/utils.py b/dojo/importers/utils.py index 7f5fb5fcc7..255e2ffa2e 100644 --- a/dojo/importers/utils.py +++ b/dojo/importers/utils.py @@ -1,17 +1,24 @@ -from django.core.exceptions import ValidationError -from django.core.exceptions import MultipleObjectsReturned +import logging + from django.conf import settings +from django.core.exceptions import MultipleObjectsReturned, ValidationError +from django.urls import reverse from django.utils.timezone import make_aware -from dojo.decorators import dojo_async_task + from dojo.celery import app +from dojo.decorators import dojo_async_task from dojo.endpoint.utils import endpoint_get_or_create +from dojo.models import ( + IMPORT_CLOSED_FINDING, + IMPORT_CREATED_FINDING, + IMPORT_REACTIVATED_FINDING, + IMPORT_UNTOUCHED_FINDING, + Endpoint_Status, + Test_Import, + Test_Import_Finding_Action, + Vulnerability_Id, +) from dojo.utils import max_safe -from django.urls import reverse -from dojo.models import IMPORT_CLOSED_FINDING, IMPORT_CREATED_FINDING, \ - IMPORT_REACTIVATED_FINDING, IMPORT_UNTOUCHED_FINDING, Test_Import, Test_Import_Finding_Action, \ - Endpoint_Status, Vulnerability_Id -import logging - logger = logging.getLogger(__name__) diff --git a/dojo/jira_link/helper.py b/dojo/jira_link/helper.py index 4862501356..df99a77096 100644 --- a/dojo/jira_link/helper.py +++ b/dojo/jira_link/helper.py @@ -1,26 +1,47 @@ -import logging -from typing import Any -from dojo.utils import add_error_message_to_response, get_system_setting, to_str_typed -import os import io import json +import logging +import os +from typing import Any + import requests from django.conf import settings +from django.contrib import messages from django.template import TemplateDoesNotExist from django.template.loader import render_to_string +from django.urls import reverse from django.utils import timezone from jira import JIRA from jira.exceptions import JIRAError -from dojo.models import Finding, Finding_Group, Risk_Acceptance, Stub_Finding, Test, Engagement, Product, \ - JIRA_Issue, JIRA_Project, System_Settings, Notes, JIRA_Instance, User from requests.auth import HTTPBasicAuth -from dojo.notifications.helper import create_notification -from django.contrib import messages + from dojo.celery import app from dojo.decorators import dojo_async_task, dojo_model_from_id, dojo_model_to_id -from dojo.utils import truncate_with_dots, prod_name, get_file_images -from django.urls import reverse -from dojo.forms import JIRAProjectForm, JIRAEngagementForm +from dojo.forms import JIRAEngagementForm, JIRAProjectForm +from dojo.models import ( + Engagement, + Finding, + Finding_Group, + JIRA_Instance, + JIRA_Issue, + JIRA_Project, + Notes, + Product, + Risk_Acceptance, + Stub_Finding, + System_Settings, + Test, + User, +) +from dojo.notifications.helper import create_notification +from dojo.utils import ( + add_error_message_to_response, + get_file_images, + get_system_setting, + prod_name, + to_str_typed, + truncate_with_dots, +) logger = logging.getLogger(__name__) diff --git a/dojo/jira_link/queries.py b/dojo/jira_link/queries.py index 00d0c741c4..4b9d9c09b7 100644 --- a/dojo/jira_link/queries.py +++ b/dojo/jira_link/queries.py @@ -1,8 +1,8 @@ from crum import get_current_user from django.db.models import Exists, OuterRef, Q -from dojo.models import JIRA_Issue, JIRA_Project, Product_Member, Product_Type_Member, \ - Product_Group, Product_Type_Group + from dojo.authorization.authorization import get_roles_for_permission, user_has_global_permission +from dojo.models import JIRA_Issue, JIRA_Project, Product_Group, Product_Member, Product_Type_Group, Product_Type_Member def get_authorized_jira_projects(permission, user=None): diff --git a/dojo/jira_link/urls.py b/dojo/jira_link/urls.py index 6737307912..40eef551f6 100644 --- a/dojo/jira_link/urls.py +++ b/dojo/jira_link/urls.py @@ -1,4 +1,5 @@ from django.urls import re_path + from . import views urlpatterns = [ diff --git a/dojo/jira_link/views.py b/dojo/jira_link/views.py index e652b8703e..057436dc14 100644 --- a/dojo/jira_link/views.py +++ b/dojo/jira_link/views.py @@ -1,28 +1,31 @@ # Standard library imports +import datetime import json import logging -import datetime + # Third party imports from django.contrib import messages from django.contrib.admin.utils import NestedObjects -from django.urls import reverse +from django.core.exceptions import PermissionDenied from django.db import DEFAULT_DB_ALIAS -from django.http import HttpResponseRedirect, HttpResponse, Http404 -from django.shortcuts import render, get_object_or_404 +from django.http import Http404, HttpResponse, HttpResponseRedirect +from django.shortcuts import get_object_or_404, render +from django.urls import reverse from django.utils import timezone from django.utils.dateparse import parse_datetime +from django.views import View from django.views.decorators.csrf import csrf_exempt -from django.core.exceptions import PermissionDenied -# Local application/library imports -from dojo.forms import JIRAForm, DeleteJIRAInstanceForm, ExpressJIRAForm -from dojo.models import System_Settings, User, JIRA_Instance, JIRA_Issue, Notes -from dojo.utils import add_breadcrumb, add_error_message_to_response -from dojo.notifications.helper import create_notification from django.views.decorators.http import require_POST + import dojo.jira_link.helper as jira_helper -from django.views import View from dojo.authorization.authorization import user_has_configuration_permission +# Local application/library imports +from dojo.forms import DeleteJIRAInstanceForm, ExpressJIRAForm, JIRAForm +from dojo.models import JIRA_Instance, JIRA_Issue, Notes, System_Settings, User +from dojo.notifications.helper import create_notification +from dojo.utils import add_breadcrumb, add_error_message_to_response + logger = logging.getLogger(__name__) diff --git a/dojo/management/commands/clear_alerts.py b/dojo/management/commands/clear_alerts.py index a977d29c22..c9b018b9ae 100644 --- a/dojo/management/commands/clear_alerts.py +++ b/dojo/management/commands/clear_alerts.py @@ -1,4 +1,5 @@ from django.core.management.base import BaseCommand + from dojo.models import Alerts, Dojo_User """ diff --git a/dojo/management/commands/dedupe.py b/dojo/management/commands/dedupe.py index 27ce037ee2..928b4d3144 100644 --- a/dojo/management/commands/dedupe.py +++ b/dojo/management/commands/dedupe.py @@ -1,9 +1,16 @@ +import logging + from django.core.management.base import BaseCommand from pytz import timezone from dojo.models import Finding, Product -from dojo.utils import calculate_grade, do_dedupe_finding, do_dedupe_finding_task, get_system_setting, mass_model_updater -import logging +from dojo.utils import ( + calculate_grade, + do_dedupe_finding, + do_dedupe_finding_task, + get_system_setting, + mass_model_updater, +) locale = timezone(get_system_setting('time_zone')) diff --git a/dojo/management/commands/dupecheck.py b/dojo/management/commands/dupecheck.py index 92567173c9..2fc252c7ae 100644 --- a/dojo/management/commands/dupecheck.py +++ b/dojo/management/commands/dupecheck.py @@ -1,7 +1,7 @@ from django.core.management.base import BaseCommand from django.db.models import Count -from dojo.models import Product, Product_Type, Tool_Type, JIRA_Issue +from dojo.models import JIRA_Issue, Product, Product_Type, Tool_Type """ Author: Aaron Weaver diff --git a/dojo/management/commands/endpoint_migration.py b/dojo/management/commands/endpoint_migration.py index d0ddc3d06c..b04893b4d4 100644 --- a/dojo/management/commands/endpoint_migration.py +++ b/dojo/management/commands/endpoint_migration.py @@ -1,8 +1,9 @@ -from django.core.management.base import BaseCommand +import logging + from django.apps import apps -from dojo.endpoint.utils import clean_hosts_run +from django.core.management.base import BaseCommand -import logging +from dojo.endpoint.utils import clean_hosts_run logger = logging.getLogger(__name__) diff --git a/dojo/management/commands/fix_0120.py b/dojo/management/commands/fix_0120.py index 8f572b34a7..127503fa97 100644 --- a/dojo/management/commands/fix_0120.py +++ b/dojo/management/commands/fix_0120.py @@ -1,10 +1,11 @@ +import logging + from django.core.management.base import BaseCommand -from dojo.models import Test +from django.db import DEFAULT_DB_ALIAS, connections from django.db.migrations.executor import MigrationExecutor -from django.db import connections, DEFAULT_DB_ALIAS from django.db.utils import OperationalError -import logging +from dojo.models import Test logger = logging.getLogger(__name__) diff --git a/dojo/management/commands/fix_broken_endpoint_status.py b/dojo/management/commands/fix_broken_endpoint_status.py index 85c2463b3a..7924b60321 100644 --- a/dojo/management/commands/fix_broken_endpoint_status.py +++ b/dojo/management/commands/fix_broken_endpoint_status.py @@ -1,8 +1,9 @@ -from django.core.management.base import BaseCommand +import logging + from django.apps import apps -from dojo.endpoint.utils import remove_broken_endpoint_statuses +from django.core.management.base import BaseCommand -import logging +from dojo.endpoint.utils import remove_broken_endpoint_statuses logger = logging.getLogger(__name__) diff --git a/dojo/management/commands/fix_loop_duplicates.py b/dojo/management/commands/fix_loop_duplicates.py index 992e96f286..7f69b23002 100644 --- a/dojo/management/commands/fix_loop_duplicates.py +++ b/dojo/management/commands/fix_loop_duplicates.py @@ -1,6 +1,9 @@ -from dojo.finding.helper import fix_loop_duplicates -from django.core.management.base import BaseCommand import logging + +from django.core.management.base import BaseCommand + +from dojo.finding.helper import fix_loop_duplicates + logger = logging.getLogger(__name__) deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") diff --git a/dojo/management/commands/import_github_languages.py b/dojo/management/commands/import_github_languages.py index 8dbaf866eb..a21e57cd9d 100644 --- a/dojo/management/commands/import_github_languages.py +++ b/dojo/management/commands/import_github_languages.py @@ -1,9 +1,10 @@ import json import logging + import requests from django.core.management.base import BaseCommand -from dojo.models import Language_Type +from dojo.models import Language_Type logger = logging.getLogger(__name__) diff --git a/dojo/management/commands/import_surveys.py b/dojo/management/commands/import_surveys.py index 5fc230fbb4..902ba3180a 100644 --- a/dojo/management/commands/import_surveys.py +++ b/dojo/management/commands/import_surveys.py @@ -1,10 +1,11 @@ +import os + from django.core.management.base import BaseCommand -from pytz import timezone from django.db import connection -import os +from pytz import timezone -from dojo.utils import get_system_setting from dojo.models import TextQuestion +from dojo.utils import get_system_setting locale = timezone(get_system_setting('time_zone')) diff --git a/dojo/management/commands/initialize_permissions.py b/dojo/management/commands/initialize_permissions.py index 61630eef2f..a5a204d686 100644 --- a/dojo/management/commands/initialize_permissions.py +++ b/dojo/management/commands/initialize_permissions.py @@ -1,8 +1,8 @@ import logging -from django.core.management.base import BaseCommand -from django.contrib.contenttypes.models import ContentType -from django.contrib.auth.models import Permission +from django.contrib.auth.models import Permission +from django.contrib.contenttypes.models import ContentType +from django.core.management.base import BaseCommand logger = logging.getLogger(__name__) diff --git a/dojo/management/commands/initialize_test_types.py b/dojo/management/commands/initialize_test_types.py index 992e5e9105..f4ccc00bbe 100644 --- a/dojo/management/commands/initialize_test_types.py +++ b/dojo/management/commands/initialize_test_types.py @@ -1,6 +1,7 @@ from django.core.management.base import BaseCommand -from dojo.tools.factory import PARSERS + from dojo.models import Test_Type, Tool_Type +from dojo.tools.factory import PARSERS class Command(BaseCommand): diff --git a/dojo/management/commands/jira_async_updates.py b/dojo/management/commands/jira_async_updates.py index b0f1683e74..e85afdc177 100644 --- a/dojo/management/commands/jira_async_updates.py +++ b/dojo/management/commands/jira_async_updates.py @@ -2,7 +2,7 @@ from django.utils import timezone from jira.exceptions import JIRAError -from dojo.models import Finding, Notes, User, Dojo_User +from dojo.models import Dojo_User, Finding, Notes, User """ Author: Aaron Weaver diff --git a/dojo/management/commands/jira_refactor_data_migration.py b/dojo/management/commands/jira_refactor_data_migration.py index 6a04a5581b..bbd79a76cf 100644 --- a/dojo/management/commands/jira_refactor_data_migration.py +++ b/dojo/management/commands/jira_refactor_data_migration.py @@ -1,7 +1,9 @@ +import logging + from django.core.management.base import BaseCommand -from dojo.models import JIRA_Issue, JIRA_Instance + import dojo.jira_link.helper as jira_helper -import logging +from dojo.models import JIRA_Instance, JIRA_Issue logger = logging.getLogger(__name__) diff --git a/dojo/management/commands/jira_status_reconciliation.py b/dojo/management/commands/jira_status_reconciliation.py index 2b175cd940..918b91a28f 100644 --- a/dojo/management/commands/jira_status_reconciliation.py +++ b/dojo/management/commands/jira_status_reconciliation.py @@ -1,11 +1,14 @@ +import logging + from dateutil.relativedelta import relativedelta from django.conf import settings from django.core.management.base import BaseCommand from django.utils import timezone from django.utils.dateparse import parse_datetime -from dojo.models import Engagement, Finding, Product + import dojo.jira_link.helper as jira_helper -import logging +from dojo.models import Engagement, Finding, Product + logger = logging.getLogger(__name__) diff --git a/dojo/management/commands/migrate_authorization_v2.py b/dojo/management/commands/migrate_authorization_v2.py index bd08fe3f7f..35fa8bbd97 100644 --- a/dojo/management/commands/migrate_authorization_v2.py +++ b/dojo/management/commands/migrate_authorization_v2.py @@ -1,6 +1,6 @@ import logging -from django.core.management.base import BaseCommand +from django.core.management.base import BaseCommand logger = logging.getLogger(__name__) diff --git a/dojo/management/commands/migrate_staff_users.py b/dojo/management/commands/migrate_staff_users.py index ce9e82b102..3015a2f44a 100644 --- a/dojo/management/commands/migrate_staff_users.py +++ b/dojo/management/commands/migrate_staff_users.py @@ -1,11 +1,11 @@ import logging import sys -from django.core.management.base import BaseCommand + from django.contrib.auth.models import Permission +from django.core.management.base import BaseCommand from dojo.models import Dojo_Group, Dojo_Group_Member, Dojo_User, Role - logger = logging.getLogger(__name__) diff --git a/dojo/management/commands/migrate_surveys.py b/dojo/management/commands/migrate_surveys.py index 25d38c028c..98cea012ab 100644 --- a/dojo/management/commands/migrate_surveys.py +++ b/dojo/management/commands/migrate_surveys.py @@ -1,8 +1,9 @@ +import sys + from django.core.management.base import BaseCommand from django.db import connection -import sys -from dojo.models import TextQuestion +from dojo.models import TextQuestion """ Author: Cody Maffucci diff --git a/dojo/management/commands/migrate_textquestions.py b/dojo/management/commands/migrate_textquestions.py index cdecda0947..d62836c4d3 100644 --- a/dojo/management/commands/migrate_textquestions.py +++ b/dojo/management/commands/migrate_textquestions.py @@ -1,8 +1,8 @@ import logging + from django.core.management.base import BaseCommand from django.db import connection - logger = logging.getLogger(__name__) diff --git a/dojo/management/commands/print_settings.py b/dojo/management/commands/print_settings.py index 4b1165e260..518e22aa6e 100644 --- a/dojo/management/commands/print_settings.py +++ b/dojo/management/commands/print_settings.py @@ -1,8 +1,9 @@ -from django.core.management.base import BaseCommand -from django.conf import settings import os from pprint import pprint +from django.conf import settings +from django.core.management.base import BaseCommand + class Command(BaseCommand): help = 'Display all the currently loaded settings in the project' diff --git a/dojo/management/commands/push_to_jira_update.py b/dojo/management/commands/push_to_jira_update.py index 3454b0bce8..2b3c10b0bb 100644 --- a/dojo/management/commands/push_to_jira_update.py +++ b/dojo/management/commands/push_to_jira_update.py @@ -1,9 +1,9 @@ from django.core.management.base import BaseCommand from pytz import timezone +import dojo.jira_link.helper as jira_helper from dojo.models import Finding from dojo.utils import get_system_setting -import dojo.jira_link.helper as jira_helper locale = timezone(get_system_setting('time_zone')) diff --git a/dojo/management/commands/rename_mend_findings.py b/dojo/management/commands/rename_mend_findings.py index 4d6b87880d..336988e64c 100644 --- a/dojo/management/commands/rename_mend_findings.py +++ b/dojo/management/commands/rename_mend_findings.py @@ -1,5 +1,6 @@ from django.core.management.base import BaseCommand from pytz import timezone + from dojo.celery import app locale = timezone(get_system_setting('time_zone')) diff --git a/dojo/management/commands/risk_acceptance_handle_expiration.py b/dojo/management/commands/risk_acceptance_handle_expiration.py index 03ad80c5f1..a627c1161c 100644 --- a/dojo/management/commands/risk_acceptance_handle_expiration.py +++ b/dojo/management/commands/risk_acceptance_handle_expiration.py @@ -1,6 +1,7 @@ +from crum import impersonate from django.core.management.base import BaseCommand + import dojo.risk_acceptance.helper as ra_helper -from crum import impersonate from dojo.models import Dojo_User diff --git a/dojo/management/commands/sla_notifications.py b/dojo/management/commands/sla_notifications.py index 663666161e..395891742a 100644 --- a/dojo/management/commands/sla_notifications.py +++ b/dojo/management/commands/sla_notifications.py @@ -1,4 +1,5 @@ from django.core.management.base import BaseCommand + from dojo.utils import sla_compute_and_notify """ diff --git a/dojo/management/commands/system_settings.py b/dojo/management/commands/system_settings.py index 78484bb6d2..6731154451 100644 --- a/dojo/management/commands/system_settings.py +++ b/dojo/management/commands/system_settings.py @@ -1,4 +1,5 @@ from django.core.management.base import BaseCommand + from dojo.models import System_Settings diff --git a/dojo/management/commands/test_celery_decorator.py b/dojo/management/commands/test_celery_decorator.py index 517e280c70..6fe77e0234 100644 --- a/dojo/management/commands/test_celery_decorator.py +++ b/dojo/management/commands/test_celery_decorator.py @@ -1,10 +1,11 @@ +from functools import wraps + from django.core.management.base import BaseCommand -from dojo.models import Finding, Notes # from dojo.utils import get_system_setting, do_dedupe_finding, dojo_async_task from dojo.celery import app -from functools import wraps +from dojo.models import Finding, Notes from dojo.utils import test_valentijn diff --git a/dojo/management/commands/validatededupeconfig.py b/dojo/management/commands/validatededupeconfig.py index dd5a0f6939..fb2973b42d 100644 --- a/dojo/management/commands/validatededupeconfig.py +++ b/dojo/management/commands/validatededupeconfig.py @@ -1,6 +1,7 @@ import logging from django.core.management.base import BaseCommand + from dojo.checks import check_configuration_deduplication logger = logging.getLogger(__name__) diff --git a/dojo/metrics/views.py b/dojo/metrics/views.py index 09933edc51..a92c439524 100644 --- a/dojo/metrics/views.py +++ b/dojo/metrics/views.py @@ -5,21 +5,27 @@ from calendar import monthrange from collections import OrderedDict from datetime import date, datetime, timedelta +from functools import reduce from math import ceil from operator import itemgetter from dateutil.relativedelta import relativedelta from django.contrib import messages from django.core.exceptions import PermissionDenied -from django.urls import reverse -from django.db.models import Q, Sum, Case, When, IntegerField, Value, Count +from django.db.models import Case, Count, IntegerField, Q, Sum, Value, When from django.db.models.query import QuerySet from django.http import HttpResponseRedirect -from django.shortcuts import render, get_object_or_404 +from django.shortcuts import get_object_or_404, render +from django.urls import reverse +from django.utils import timezone from django.utils.html import escape +from django.utils.translation import gettext as _ from django.views.decorators.cache import cache_page -from django.utils import timezone +from django.views.decorators.vary import vary_on_cookie +from dojo.authorization.authorization import user_has_permission_or_403 +from dojo.authorization.roles_permissions import Permissions +from dojo.endpoint.queries import get_authorized_endpoint_status from dojo.filters import ( MetricsEndpointFilter, MetricsEndpointFilterWithoutObjectLookups, @@ -27,21 +33,23 @@ MetricsFindingFilterWithoutObjectLookups, UserFilter, ) -from dojo.forms import SimpleMetricsForm, ProductTypeCountsForm, ProductTagCountsForm -from dojo.models import Product_Type, Finding, Product, Engagement, Test, \ - Risk_Acceptance, Dojo_User, Endpoint_Status -from dojo.utils import get_page_items, add_breadcrumb, findings_this_period, opened_in_period, count_findings, \ - get_period_counts, get_system_setting, get_punchcard_data, queryset_check -from functools import reduce -from django.views.decorators.vary import vary_on_cookie -from dojo.authorization.roles_permissions import Permissions +from dojo.finding.helper import ACCEPTED_FINDINGS_QUERY, CLOSED_FINDINGS_QUERY +from dojo.finding.queries import get_authorized_findings +from dojo.forms import ProductTagCountsForm, ProductTypeCountsForm, SimpleMetricsForm +from dojo.models import Dojo_User, Endpoint_Status, Engagement, Finding, Product, Product_Type, Risk_Acceptance, Test from dojo.product.queries import get_authorized_products from dojo.product_type.queries import get_authorized_product_types -from dojo.finding.queries import get_authorized_findings -from dojo.finding.helper import ACCEPTED_FINDINGS_QUERY, CLOSED_FINDINGS_QUERY -from dojo.endpoint.queries import get_authorized_endpoint_status -from dojo.authorization.authorization import user_has_permission_or_403 -from django.utils.translation import gettext as _ +from dojo.utils import ( + add_breadcrumb, + count_findings, + findings_this_period, + get_page_items, + get_period_counts, + get_punchcard_data, + get_system_setting, + opened_in_period, + queryset_check, +) logger = logging.getLogger(__name__) diff --git a/dojo/middleware.py b/dojo/middleware.py index 4e54fe9e81..59a61eba81 100644 --- a/dojo/middleware.py +++ b/dojo/middleware.py @@ -1,13 +1,13 @@ -from django.http import HttpResponseRedirect -from django.conf import settings -from urllib.parse import quote -from re import compile import logging +from re import compile from threading import local +from urllib.parse import quote + +from django.conf import settings from django.db import models +from django.http import HttpResponseRedirect from django.urls import reverse - logger = logging.getLogger(__name__) EXEMPT_URLS = [compile(settings.LOGIN_URL.lstrip('/'))] diff --git a/dojo/models.py b/dojo/models.py index d7bac77823..a5322c3313 100644 --- a/dojo/models.py +++ b/dojo/models.py @@ -1,47 +1,46 @@ import base64 +import copy import hashlib import logging import os import re -import copy import warnings -from typing import Dict, Set, Optional +from datetime import datetime +from typing import Dict, Optional, Set from uuid import uuid4 -from django.conf import settings + +import hyperlink +import tagulous.admin from auditlog.registry import auditlog +from cvss import CVSS3 +from dateutil.relativedelta import relativedelta +from django import forms +from django.conf import settings from django.contrib import admin from django.contrib.auth import get_user_model from django.contrib.auth.models import Group -from django.db.models.expressions import Case, When -from django.urls import reverse -from django.core.validators import RegexValidator, validate_ipv46_address, MinValueValidator, MaxValueValidator -from django.core.files.base import ContentFile from django.core.exceptions import ValidationError -from django.db import models, connection -from django.db.models import Q, Count +from django.core.files.base import ContentFile +from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator, validate_ipv46_address +from django.db import connection, models +from django.db.models import Count, JSONField, Q +from django.db.models.expressions import Case, When from django.db.models.functions import Lower -from django_extensions.db.models import TimeStampedModel +from django.urls import reverse +from django.utils import timezone from django.utils.deconstruct import deconstructible -from django.utils.timezone import now from django.utils.functional import cached_property -from django.utils import timezone from django.utils.html import escape -from pytz import all_timezones -from polymorphic.models import PolymorphicModel -from polymorphic.managers import PolymorphicManager -from polymorphic.base import ManagerInheritanceWarning -from multiselectfield import MultiSelectField -from django import forms +from django.utils.timezone import now from django.utils.translation import gettext as _ -from dateutil.relativedelta import relativedelta -from datetime import datetime +from django_extensions.db.models import TimeStampedModel +from multiselectfield import MultiSelectField +from polymorphic.base import ManagerInheritanceWarning +from polymorphic.managers import PolymorphicManager +from polymorphic.models import PolymorphicModel +from pytz import all_timezones from tagulous.models import TagField from tagulous.models.managers import FakeTagRelatedManager -import tagulous.admin -from django.db.models import JSONField -import hyperlink -from cvss import CVSS3 - logger = logging.getLogger(__name__) deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") @@ -3274,6 +3273,7 @@ def get_file_path_with_raw_link(self): def get_references_with_links(self): import re + from dojo.utils import create_bleached_link if self.references is None: return None diff --git a/dojo/note_type/views.py b/dojo/note_type/views.py index 76d9c051b9..0535d67b5a 100644 --- a/dojo/note_type/views.py +++ b/dojo/note_type/views.py @@ -1,15 +1,15 @@ import logging -from django.shortcuts import render, get_object_or_404 from django.contrib import messages -from django.urls import reverse from django.http import HttpResponseRedirect +from django.shortcuts import get_object_or_404, render +from django.urls import reverse -from dojo.forms import NoteTypeForm, EditNoteTypeForm, DisableOrEnableNoteTypeForm -from dojo.models import Note_Type -from dojo.filters import NoteTypesFilter -from dojo.utils import get_page_items, add_breadcrumb from dojo.authorization.authorization_decorators import user_is_configuration_authorized +from dojo.filters import NoteTypesFilter +from dojo.forms import DisableOrEnableNoteTypeForm, EditNoteTypeForm, NoteTypeForm +from dojo.models import Note_Type +from dojo.utils import add_breadcrumb, get_page_items logger = logging.getLogger(__name__) diff --git a/dojo/notes/urls.py b/dojo/notes/urls.py index 92435303f5..0f5ce2b0b1 100644 --- a/dojo/notes/urls.py +++ b/dojo/notes/urls.py @@ -1,4 +1,5 @@ from django.urls import re_path + from . import views urlpatterns = [ diff --git a/dojo/notes/views.py b/dojo/notes/views.py index edea3a9ca6..3ccb8ae1f8 100644 --- a/dojo/notes/views.py +++ b/dojo/notes/views.py @@ -3,19 +3,20 @@ # Third party imports from django.contrib import messages -from django.urls import reverse +from django.core.exceptions import PermissionDenied from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, render -from django.core.exceptions import PermissionDenied +from django.urls import reverse from django.utils import timezone from django.utils.translation import gettext as _ -# Local application/library imports -from dojo.forms import DeleteNoteForm, NoteForm, TypedNoteForm -from dojo.models import Notes, Engagement, Test, Finding, NoteHistory, Note_Type from dojo.authorization.authorization import user_has_permission_or_403 from dojo.authorization.roles_permissions import Permissions +# Local application/library imports +from dojo.forms import DeleteNoteForm, NoteForm, TypedNoteForm +from dojo.models import Engagement, Finding, Note_Type, NoteHistory, Notes, Test + logger = logging.getLogger(__name__) diff --git a/dojo/notifications/helper.py b/dojo/notifications/helper.py index c492b407f6..2728b9a148 100644 --- a/dojo/notifications/helper.py +++ b/dojo/notifications/helper.py @@ -1,9 +1,9 @@ import logging -import requests +import requests from django.conf import settings from django.core.mail import EmailMessage -from django.db.models import Q, Count, Prefetch +from django.db.models import Count, Prefetch, Q from django.template import TemplateDoesNotExist from django.template.loader import render_to_string from django.urls import reverse @@ -12,7 +12,7 @@ from dojo.authorization.roles_permissions import Permissions from dojo.celery import app from dojo.decorators import dojo_async_task, we_want_async -from dojo.models import Notifications, Dojo_User, Alerts, UserContactInfo, System_Settings +from dojo.models import Alerts, Dojo_User, Notifications, System_Settings, UserContactInfo from dojo.user.queries import get_authorized_users_for_product_and_product_type, get_authorized_users_for_product_type logger = logging.getLogger(__name__) @@ -331,9 +331,10 @@ def send_alert_notification(event, user=None, *args, **kwargs): def get_slack_user_id(user_email): - from dojo.utils import get_system_setting import json + from dojo.utils import get_system_setting + user_id = None res = requests.request( diff --git a/dojo/notifications/urls.py b/dojo/notifications/urls.py index 68d8c3f22a..8ac8cf2171 100644 --- a/dojo/notifications/urls.py +++ b/dojo/notifications/urls.py @@ -1,4 +1,5 @@ from django.urls import re_path + from . import views urlpatterns = [ diff --git a/dojo/notifications/views.py b/dojo/notifications/views.py index 72ce533a57..10616dd1b1 100644 --- a/dojo/notifications/views.py +++ b/dojo/notifications/views.py @@ -1,16 +1,15 @@ import logging from django.contrib import messages -from django.shortcuts import render +from django.core.exceptions import PermissionDenied from django.http import HttpRequest +from django.shortcuts import render from django.utils.translation import gettext as _ from django.views import View -from django.core.exceptions import PermissionDenied -from dojo.models import Notifications -from dojo.utils import get_enabled_notifications_list -from dojo.utils import add_breadcrumb from dojo.forms import NotificationsForm +from dojo.models import Notifications +from dojo.utils import add_breadcrumb, get_enabled_notifications_list logger = logging.getLogger(__name__) diff --git a/dojo/object/urls.py b/dojo/object/urls.py index 4859ccbd11..aa87010b32 100644 --- a/dojo/object/urls.py +++ b/dojo/object/urls.py @@ -1,4 +1,5 @@ from django.urls import re_path + from . import views urlpatterns = [ diff --git a/dojo/object/views.py b/dojo/object/views.py index 20be866c1a..86d45e067f 100644 --- a/dojo/object/views.py +++ b/dojo/object/views.py @@ -1,14 +1,16 @@ import logging + from django.contrib import messages from django.core.exceptions import BadRequest -from django.urls import reverse from django.http import HttpResponseRedirect -from django.shortcuts import render, get_object_or_404 -from dojo.models import Product, Objects_Product -from dojo.forms import ObjectSettingsForm, DeleteObjectsSettingsForm -from dojo.utils import Product_Tab -from dojo.authorization.roles_permissions import Permissions +from django.shortcuts import get_object_or_404, render +from django.urls import reverse + from dojo.authorization.authorization_decorators import user_is_authorized +from dojo.authorization.roles_permissions import Permissions +from dojo.forms import DeleteObjectsSettingsForm, ObjectSettingsForm +from dojo.models import Objects_Product, Product +from dojo.utils import Product_Tab logger = logging.getLogger(__name__) diff --git a/dojo/okta.py b/dojo/okta.py index 856f6004e8..e1aaf13432 100644 --- a/dojo/okta.py +++ b/dojo/okta.py @@ -4,12 +4,12 @@ python-social-auth/socail-core """ -from six.moves.urllib.parse import urljoin from jose import jwt -from jose.jwt import JWTError, ExpiredSignatureError -from social_core.utils import append_slash +from jose.jwt import ExpiredSignatureError, JWTError +from six.moves.urllib.parse import urljoin from social_core.backends.oauth import BaseOAuth2 from social_core.backends.open_id_connect import OpenIdConnectAuth +from social_core.utils import append_slash class OktaMixin: diff --git a/dojo/pipeline.py b/dojo/pipeline.py index f5405af9ee..8f05d35d4c 100644 --- a/dojo/pipeline.py +++ b/dojo/pipeline.py @@ -1,14 +1,15 @@ -import gitlab -import re import logging -import requests +import re +import gitlab +import requests import social_core.pipeline.user from django.conf import settings -from dojo.models import Product, Product_Member, Product_Type, Role, Dojo_Group, Dojo_Group_Member from social_core.backends.azuread_tenant import AzureADTenantOAuth2 from social_core.backends.google import GoogleOAuth2 + from dojo.authorization.roles_permissions import Permissions, Roles +from dojo.models import Dojo_Group, Dojo_Group_Member, Product, Product_Member, Product_Type, Role from dojo.product.queries import get_authorized_products logger = logging.getLogger(__name__) diff --git a/dojo/product/helpers.py b/dojo/product/helpers.py index 74530744cd..13c512c9c9 100644 --- a/dojo/product/helpers.py +++ b/dojo/product/helpers.py @@ -1,9 +1,9 @@ import contextlib import logging + from dojo.celery import app -from dojo.models import SLA_Configuration, Product, Engagement, Test, Finding, Endpoint from dojo.decorators import dojo_async_task - +from dojo.models import Endpoint, Engagement, Finding, Product, SLA_Configuration, Test logger = logging.getLogger(__name__) diff --git a/dojo/product/queries.py b/dojo/product/queries.py index 331205fae6..96f1b626cb 100644 --- a/dojo/product/queries.py +++ b/dojo/product/queries.py @@ -1,13 +1,26 @@ from crum import get_current_user from django.db.models import Exists, OuterRef, Q -from dojo.models import Product, Product_Member, Product_Type_Member, App_Analysis, \ - DojoMeta, Product_Group, Product_Type_Group, Languages, Engagement_Presets, \ - Product_API_Scan_Configuration -from dojo.authorization.authorization import get_roles_for_permission, user_has_global_permission, user_has_permission, \ - role_has_permission -from dojo.group.queries import get_authorized_groups +from dojo.authorization.authorization import ( + get_roles_for_permission, + role_has_permission, + user_has_global_permission, + user_has_permission, +) from dojo.authorization.roles_permissions import Permissions +from dojo.group.queries import get_authorized_groups +from dojo.models import ( + App_Analysis, + DojoMeta, + Engagement_Presets, + Languages, + Product, + Product_API_Scan_Configuration, + Product_Group, + Product_Member, + Product_Type_Group, + Product_Type_Member, +) def get_authorized_products(permission, user=None): diff --git a/dojo/product/signals.py b/dojo/product/signals.py index 17ffc6b4b6..10869a5f28 100644 --- a/dojo/product/signals.py +++ b/dojo/product/signals.py @@ -1,10 +1,12 @@ import contextlib +import logging + from django.db.models import signals from django.dispatch import receiver -import logging -from dojo.models import Product, Engagement, Test, Finding, Endpoint -from dojo.utils import get_system_setting + +from dojo.models import Endpoint, Engagement, Finding, Product, Test from dojo.product import helpers as async_product_funcs +from dojo.utils import get_system_setting logger = logging.getLogger(__name__) diff --git a/dojo/product/urls.py b/dojo/product/urls.py index 263d87b66f..5daa8a2ce4 100644 --- a/dojo/product/urls.py +++ b/dojo/product/urls.py @@ -1,7 +1,7 @@ from django.urls import re_path -from dojo.product import views from dojo.engagement import views as dojo_engagement_views +from dojo.product import views urlpatterns = [ # product diff --git a/dojo/product/views.py b/dojo/product/views.py index 85b6bf2768..024b5c5d02 100644 --- a/dojo/product/views.py +++ b/dojo/product/views.py @@ -1,35 +1,35 @@ # # product +import base64 import calendar as tcalendar import logging -import base64 - from collections import OrderedDict -from datetime import datetime, date, timedelta -from dateutil.relativedelta import relativedelta -from github import Github +from datetime import date, datetime, timedelta from math import ceil +from dateutil.relativedelta import relativedelta from django.contrib import messages from django.contrib.admin.utils import NestedObjects from django.contrib.postgres.aggregates import StringAgg +from django.core.exceptions import PermissionDenied, ValidationError from django.db import DEFAULT_DB_ALIAS, connection -from django.db.models import Sum, Count, Q, Max, Prefetch, F, OuterRef, Subquery +from django.db.models import Count, F, Max, OuterRef, Prefetch, Q, Subquery, Sum from django.db.models.expressions import Value from django.db.models.query import QuerySet -from django.core.exceptions import ValidationError, PermissionDenied -from django.http import HttpResponseRedirect, Http404, JsonResponse, HttpRequest -from django.shortcuts import render, get_object_or_404 +from django.http import Http404, HttpRequest, HttpResponseRedirect, JsonResponse +from django.shortcuts import get_object_or_404, render from django.urls import reverse from django.utils import timezone from django.utils.translation import gettext as _ from django.views import View +from github import Github -from dojo.templatetags.display_tags import asvs_calc_level +import dojo.finding.helper as finding_helper +import dojo.jira_link.helper as jira_helper +from dojo.authorization.authorization import user_has_permission, user_has_permission_or_403 +from dojo.authorization.authorization_decorators import user_is_authorized +from dojo.authorization.roles_permissions import Permissions +from dojo.components.sql_group_concat import Sql_GroupConcat from dojo.filters import ( - ProductEngagementFilter, - ProductEngagementFilterWithoutObjectLookups, - ProductFilter, - ProductFilterWithoutObjectLookups, EngagementFilter, EngagementFilterWithoutObjectLookups, MetricsEndpointFilter, @@ -37,37 +37,93 @@ MetricsFindingFilter, MetricsFindingFilterWithoutObjectLookups, ProductComponentFilter, + ProductEngagementFilter, + ProductEngagementFilterWithoutObjectLookups, + ProductFilter, + ProductFilterWithoutObjectLookups, +) +from dojo.forms import ( + Add_Product_GroupForm, + Add_Product_MemberForm, + AdHocFindingForm, + AppAnalysisForm, + Delete_Product_GroupForm, + Delete_Product_MemberForm, + DeleteAppAnalysisForm, + DeleteEngagementPresetsForm, + DeleteProduct_API_Scan_ConfigurationForm, + DeleteProductForm, + DojoMetaDataForm, + Edit_Product_Group_Form, + Edit_Product_MemberForm, + EngagementPresetsForm, + EngForm, + GITHUB_Product_Form, + GITHUBFindingForm, + JIRAEngagementForm, + JIRAFindingForm, + JIRAProjectForm, + Product_API_Scan_ConfigurationForm, + ProductForm, + ProductNotificationsForm, + SLA_Configuration, +) +from dojo.models import ( + App_Analysis, + Benchmark_Product_Summary, + BurpRawRequestResponse, + DojoMeta, + Endpoint, + Endpoint_Status, + Engagement, + Engagement_Presets, + Finding, + GITHUB_PKey, + Languages, + Note_Type, + Notifications, + Product, + Product_API_Scan_Configuration, + Product_Group, + Product_Member, + Product_Type, + System_Settings, + Test, + Test_Type, ) -from dojo.forms import ProductForm, EngForm, DeleteProductForm, DojoMetaDataForm, JIRAProjectForm, JIRAFindingForm, \ - AdHocFindingForm, \ - EngagementPresetsForm, DeleteEngagementPresetsForm, ProductNotificationsForm, \ - GITHUB_Product_Form, GITHUBFindingForm, AppAnalysisForm, JIRAEngagementForm, Add_Product_MemberForm, \ - Edit_Product_MemberForm, Delete_Product_MemberForm, Add_Product_GroupForm, Edit_Product_Group_Form, \ - Delete_Product_GroupForm, SLA_Configuration, \ - DeleteAppAnalysisForm, Product_API_Scan_ConfigurationForm, DeleteProduct_API_Scan_ConfigurationForm -from dojo.models import Product_Type, Note_Type, Finding, Product, Engagement, Test, GITHUB_PKey, \ - Test_Type, System_Settings, Languages, App_Analysis, Benchmark_Product_Summary, Endpoint_Status, \ - Endpoint, Engagement_Presets, DojoMeta, Notifications, BurpRawRequestResponse, Product_Member, \ - Product_Group, Product_API_Scan_Configuration -from dojo.utils import add_external_issue, add_error_message_to_response, add_field_errors_to_response, get_page_items, \ - add_breadcrumb, async_delete, calculate_finding_age, \ - get_system_setting, get_setting, Product_Tab, get_punchcard_data, queryset_check, is_title_in_breadcrumbs, \ - get_enabled_notifications_list, get_zero_severity_level, sum_by_severity_level, get_open_findings_burndown - from dojo.notifications.helper import create_notification -from dojo.components.sql_group_concat import Sql_GroupConcat -from dojo.authorization.authorization import user_has_permission, user_has_permission_or_403 -from dojo.authorization.roles_permissions import Permissions -from dojo.authorization.authorization_decorators import user_is_authorized -from dojo.product.queries import get_authorized_products, get_authorized_members_for_product, \ - get_authorized_groups_for_product -from dojo.product_type.queries import get_authorized_members_for_product_type, get_authorized_groups_for_product_type, \ - get_authorized_product_types +from dojo.product.queries import ( + get_authorized_groups_for_product, + get_authorized_members_for_product, + get_authorized_products, +) +from dojo.product_type.queries import ( + get_authorized_groups_for_product_type, + get_authorized_members_for_product_type, + get_authorized_product_types, +) +from dojo.templatetags.display_tags import asvs_calc_level from dojo.tool_config.factory import create_API from dojo.tools.factory import get_api_scan_configuration_hints - -import dojo.finding.helper as finding_helper -import dojo.jira_link.helper as jira_helper +from dojo.utils import ( + Product_Tab, + add_breadcrumb, + add_error_message_to_response, + add_external_issue, + add_field_errors_to_response, + async_delete, + calculate_finding_age, + get_enabled_notifications_list, + get_open_findings_burndown, + get_page_items, + get_punchcard_data, + get_setting, + get_system_setting, + get_zero_severity_level, + is_title_in_breadcrumbs, + queryset_check, + sum_by_severity_level, +) logger = logging.getLogger(__name__) diff --git a/dojo/product_type/queries.py b/dojo/product_type/queries.py index 6b5f565776..4b658798e2 100644 --- a/dojo/product_type/queries.py +++ b/dojo/product_type/queries.py @@ -1,10 +1,15 @@ from crum import get_current_user from django.db.models import Exists, OuterRef, Q -from dojo.models import Product_Type, Product_Type_Member, Product_Type_Group -from dojo.authorization.authorization import get_roles_for_permission, user_has_global_permission, user_has_permission, \ - role_has_permission -from dojo.group.queries import get_authorized_groups + +from dojo.authorization.authorization import ( + get_roles_for_permission, + role_has_permission, + user_has_global_permission, + user_has_permission, +) from dojo.authorization.roles_permissions import Permissions +from dojo.group.queries import get_authorized_groups +from dojo.models import Product_Type, Product_Type_Group, Product_Type_Member def get_authorized_product_types(permission): diff --git a/dojo/product_type/urls.py b/dojo/product_type/urls.py index c4536aca8b..41f9b840c7 100644 --- a/dojo/product_type/urls.py +++ b/dojo/product_type/urls.py @@ -1,7 +1,7 @@ from django.urls import re_path -from dojo.product_type import views from dojo.product import views as product_views +from dojo.product_type import views urlpatterns = [ # product type diff --git a/dojo/product_type/views.py b/dojo/product_type/views.py index fbc4aae063..1a0e336e7e 100644 --- a/dojo/product_type/views.py +++ b/dojo/product_type/views.py @@ -1,27 +1,38 @@ import logging +from django.contrib import messages from django.contrib.admin.utils import NestedObjects from django.db import DEFAULT_DB_ALIAS -from django.contrib import messages -from django.urls import reverse -from django.http import HttpResponseRedirect -from django.shortcuts import render, get_object_or_404 -from django.utils.translation import gettext as _ -from dojo.filters import ProductTypeFilter -from dojo.forms import Product_TypeForm, Delete_Product_TypeForm, Add_Product_Type_MemberForm, \ - Edit_Product_Type_MemberForm, Delete_Product_Type_MemberForm, Add_Product_Type_GroupForm, \ - Edit_Product_Type_Group_Form, Delete_Product_Type_GroupForm -from dojo.models import Product_Type, Product_Type_Member, Role, Product_Type_Group -from dojo.utils import get_page_items, add_breadcrumb, is_title_in_breadcrumbs, get_setting, async_delete -from dojo.notifications.helper import create_notification from django.db.models import Count, Q from django.db.models.query import QuerySet +from django.http import HttpResponseRedirect +from django.shortcuts import get_object_or_404, render +from django.urls import reverse +from django.utils.translation import gettext as _ + from dojo.authorization.authorization import user_has_permission -from dojo.authorization.roles_permissions import Permissions from dojo.authorization.authorization_decorators import user_has_global_permission, user_is_authorized -from dojo.product_type.queries import get_authorized_product_types, get_authorized_members_for_product_type, \ - get_authorized_groups_for_product_type +from dojo.authorization.roles_permissions import Permissions +from dojo.filters import ProductTypeFilter +from dojo.forms import ( + Add_Product_Type_GroupForm, + Add_Product_Type_MemberForm, + Delete_Product_Type_GroupForm, + Delete_Product_Type_MemberForm, + Delete_Product_TypeForm, + Edit_Product_Type_Group_Form, + Edit_Product_Type_MemberForm, + Product_TypeForm, +) +from dojo.models import Product_Type, Product_Type_Group, Product_Type_Member, Role +from dojo.notifications.helper import create_notification from dojo.product.queries import get_authorized_products +from dojo.product_type.queries import ( + get_authorized_groups_for_product_type, + get_authorized_members_for_product_type, + get_authorized_product_types, +) +from dojo.utils import add_breadcrumb, async_delete, get_page_items, get_setting, is_title_in_breadcrumbs logger = logging.getLogger(__name__) diff --git a/dojo/regulations/urls.py b/dojo/regulations/urls.py index d99ba89440..a16d3c9cca 100644 --- a/dojo/regulations/urls.py +++ b/dojo/regulations/urls.py @@ -1,4 +1,5 @@ from django.urls import re_path + from . import views urlpatterns = [ diff --git a/dojo/regulations/views.py b/dojo/regulations/views.py index 232a87574a..0bcd19bf7b 100644 --- a/dojo/regulations/views.py +++ b/dojo/regulations/views.py @@ -1,17 +1,17 @@ # # product import logging -from django.contrib.auth.decorators import login_required from django.contrib import messages -from django.urls import reverse +from django.contrib.auth.decorators import login_required from django.http import HttpResponseRedirect from django.shortcuts import render -from dojo.utils import add_breadcrumb +from django.urls import reverse + +from dojo.authorization.authorization import user_has_configuration_permission_or_403 +from dojo.authorization.authorization_decorators import user_is_configuration_authorized from dojo.forms import RegulationForm from dojo.models import Regulation -from dojo.authorization.authorization_decorators import user_is_configuration_authorized -from dojo.authorization.authorization import user_has_configuration_permission_or_403 - +from dojo.utils import add_breadcrumb logger = logging.getLogger(__name__) diff --git a/dojo/remote_user.py b/dojo/remote_user.py index a82ae52a31..2576d9a284 100644 --- a/dojo/remote_user.py +++ b/dojo/remote_user.py @@ -1,12 +1,14 @@ import logging -from django.contrib.auth.middleware import RemoteUserMiddleware as OriginalRemoteUserMiddleware + +from django.conf import settings from django.contrib.auth.backends import RemoteUserBackend as OriginalRemoteUserBackend +from django.contrib.auth.middleware import RemoteUserMiddleware as OriginalRemoteUserMiddleware from drf_spectacular.extensions import OpenApiAuthenticationExtension -from rest_framework.authentication import RemoteUserAuthentication as OriginalRemoteUserAuthentication from netaddr import IPAddress -from django.conf import settings -from dojo.pipeline import assign_user_to_groups, cleanup_old_groups_for_user +from rest_framework.authentication import RemoteUserAuthentication as OriginalRemoteUserAuthentication + from dojo.models import Dojo_Group +from dojo.pipeline import assign_user_to_groups, cleanup_old_groups_for_user logger = logging.getLogger(__name__) diff --git a/dojo/reports/views.py b/dojo/reports/views.py index 8f071ec0f7..3b2d8c193b 100644 --- a/dojo/reports/views.py +++ b/dojo/reports/views.py @@ -1,35 +1,46 @@ +import csv import logging import re -import csv -from openpyxl import Workbook -from openpyxl.styles import Font -from tempfile import NamedTemporaryFile - - from datetime import datetime +from tempfile import NamedTemporaryFile from dateutil.relativedelta import relativedelta from django.conf import settings +from django.core.exceptions import PermissionDenied from django.http import Http404, HttpResponse, QueryDict -from django.shortcuts import render, get_object_or_404 +from django.shortcuts import get_object_or_404, render from django.utils import timezone -from django.core.exceptions import PermissionDenied from django.views import View +from openpyxl import Workbook +from openpyxl.styles import Font -from dojo.filters import ReportFindingFilter, EndpointReportFilter, \ - EndpointFilter, EndpointFilterWithoutObjectLookups -from dojo.forms import ReportOptionsForm -from dojo.models import Product_Type, Finding, Product, Engagement, Test, \ - Dojo_User, Endpoint, Risk_Acceptance -from dojo.reports.widgets import CoverPage, PageBreak, TableOfContents, WYSIWYGContent, FindingList, EndpointList, \ - CustomReportJsonForm, ReportOptions, report_widget_factory -from dojo.utils import get_page_items, add_breadcrumb, get_system_setting, get_period_counts_legacy, Product_Tab, \ - get_words_for_field +from dojo.authorization.authorization import user_has_permission_or_403 from dojo.authorization.authorization_decorators import user_is_authorized from dojo.authorization.roles_permissions import Permissions -from dojo.authorization.authorization import user_has_permission_or_403 +from dojo.filters import EndpointFilter, EndpointFilterWithoutObjectLookups, EndpointReportFilter, ReportFindingFilter from dojo.finding.queries import get_authorized_findings from dojo.finding.views import BaseListFindings +from dojo.forms import ReportOptionsForm +from dojo.models import Dojo_User, Endpoint, Engagement, Finding, Product, Product_Type, Risk_Acceptance, Test +from dojo.reports.widgets import ( + CoverPage, + CustomReportJsonForm, + EndpointList, + FindingList, + PageBreak, + ReportOptions, + TableOfContents, + WYSIWYGContent, + report_widget_factory, +) +from dojo.utils import ( + Product_Tab, + add_breadcrumb, + get_page_items, + get_period_counts_legacy, + get_system_setting, + get_words_for_field, +) logger = logging.getLogger(__name__) diff --git a/dojo/reports/widgets.py b/dojo/reports/widgets.py index 6d0ca15656..665b7758b4 100644 --- a/dojo/reports/widgets.py +++ b/dojo/reports/widgets.py @@ -14,7 +14,7 @@ from dojo.filters import EndpointFilter, EndpointFilterWithoutObjectLookups, ReportFindingFilter from dojo.forms import CustomReportOptionsForm from dojo.models import Endpoint, Finding -from dojo.utils import get_page_items, get_words_for_field, get_system_setting +from dojo.utils import get_page_items, get_system_setting, get_words_for_field """ Widgets are content sections that can be included on reports. The report builder will allow any number of widgets diff --git a/dojo/risk_acceptance/api.py b/dojo/risk_acceptance/api.py index b23a0d1dfc..bb78356fdf 100644 --- a/dojo/risk_acceptance/api.py +++ b/dojo/risk_acceptance/api.py @@ -1,7 +1,8 @@ from abc import ABC, abstractmethod -from typing import NamedTuple, List +from typing import List, NamedTuple from django.db.models import QuerySet +from django.utils import timezone from drf_spectacular.utils import extend_schema from rest_framework import serializers, status from rest_framework.decorators import action @@ -9,11 +10,9 @@ from rest_framework.response import Response from dojo.api_v2.serializers import RiskAcceptanceSerializer -from dojo.models import Risk_Acceptance, User, Vulnerability_Id -from django.utils import timezone from dojo.authorization.roles_permissions import Permissions from dojo.engagement.queries import get_authorized_engagements - +from dojo.models import Risk_Acceptance, User, Vulnerability_Id AcceptedRisk = NamedTuple('AcceptedRisk', (('vulnerability_id', str), ('justification', str), ('accepted_by', str))) diff --git a/dojo/risk_acceptance/helper.py b/dojo/risk_acceptance/helper.py index 7fcaa796c9..0159517ebf 100644 --- a/dojo/risk_acceptance/helper.py +++ b/dojo/risk_acceptance/helper.py @@ -1,14 +1,16 @@ +import logging + +from dateutil.relativedelta import relativedelta from django.core.exceptions import PermissionDenied +from django.urls import reverse from django.utils import timezone -from dojo.utils import get_system_setting, get_full_url -from dateutil.relativedelta import relativedelta + import dojo.jira_link.helper as jira_helper +from dojo.celery import app from dojo.jira_link.helper import escape_for_jira +from dojo.models import Finding, Risk_Acceptance, System_Settings from dojo.notifications.helper import create_notification -from django.urls import reverse -from dojo.celery import app -from dojo.models import System_Settings, Risk_Acceptance, Finding -import logging +from dojo.utils import get_full_url, get_system_setting logger = logging.getLogger(__name__) diff --git a/dojo/risk_acceptance/queries.py b/dojo/risk_acceptance/queries.py index cc11b3ec8a..2d45fb6445 100644 --- a/dojo/risk_acceptance/queries.py +++ b/dojo/risk_acceptance/queries.py @@ -1,8 +1,8 @@ from crum import get_current_user from django.db.models import Exists, OuterRef, Q -from dojo.models import Product_Member, Product_Type_Member, \ - Product_Group, Product_Type_Group, Risk_Acceptance + from dojo.authorization.authorization import get_roles_for_permission, user_has_global_permission +from dojo.models import Product_Group, Product_Member, Product_Type_Group, Product_Type_Member, Risk_Acceptance def get_authorized_risk_acceptances(permission): diff --git a/dojo/search/views.py b/dojo/search/views.py index 717ced2059..946462a9e3 100644 --- a/dojo/search/views.py +++ b/dojo/search/views.py @@ -1,25 +1,26 @@ +import itertools import logging +import re +import shlex -from django.utils.translation import gettext as _ +from django.conf import settings +from django.db.models import Q from django.shortcuts import render +from django.utils.translation import gettext as _ from watson import search as watson -from django.db.models import Q -from dojo.forms import SimpleSearchForm -from dojo.models import Finding, Finding_Template, Product, Test, Engagement, Languages -from dojo.utils import add_breadcrumb, get_page_items, get_words_for_field, get_system_setting -import re -from dojo.finding.views import prefetch_for_findings + +from dojo.authorization.roles_permissions import Permissions +from dojo.endpoint.queries import get_authorized_endpoints from dojo.endpoint.views import prefetch_for_endpoints -from dojo.filters import FindingFilter, FindingFilterWithoutObjectLookups -from django.conf import settings -import shlex -import itertools -from dojo.product.queries import get_authorized_products, get_authorized_app_analysis from dojo.engagement.queries import get_authorized_engagements -from dojo.test.queries import get_authorized_tests +from dojo.filters import FindingFilter, FindingFilterWithoutObjectLookups from dojo.finding.queries import get_authorized_findings, get_authorized_vulnerability_ids -from dojo.endpoint.queries import get_authorized_endpoints -from dojo.authorization.roles_permissions import Permissions +from dojo.finding.views import prefetch_for_findings +from dojo.forms import SimpleSearchForm +from dojo.models import Engagement, Finding, Finding_Template, Languages, Product, Test +from dojo.product.queries import get_authorized_app_analysis, get_authorized_products +from dojo.test.queries import get_authorized_tests +from dojo.utils import add_breadcrumb, get_page_items, get_system_setting, get_words_for_field logger = logging.getLogger(__name__) diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index d8f37f8680..1c28b9f67e 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -1,15 +1,16 @@ # Django settings for DefectDojo -import os -from datetime import timedelta -from celery.schedules import crontab -from dojo import __version__ -import environ -from netaddr import IPNetwork, IPSet import json import logging +import os import warnings +from datetime import timedelta from email.utils import getaddresses +import environ +from celery.schedules import crontab +from netaddr import IPNetwork, IPSet + +from dojo import __version__ logger = logging.getLogger(__name__) @@ -896,9 +897,10 @@ def saml2_attrib_map_format(dict): SAML2_LOGIN_BUTTON_TEXT = env('DD_SAML2_LOGIN_BUTTON_TEXT') SAML2_LOGOUT_URL = env('DD_SAML2_LOGOUT_URL') if SAML2_ENABLED: + from os import path + import saml2 import saml2.saml - from os import path # SSO_URL = env('DD_SSO_URL') SAML_METADATA = {} if len(env('DD_SAML2_METADATA_AUTO_CONF_URL')) > 0: diff --git a/dojo/settings/settings.py b/dojo/settings/settings.py index 6ec2fdd92c..c44b419e25 100644 --- a/dojo/settings/settings.py +++ b/dojo/settings/settings.py @@ -1,4 +1,4 @@ -from split_settings.tools import optional, include +from split_settings.tools import include, optional # See https://documentation.defectdojo.com/getting_started/configuration/ for options # how to tune the configuration to your needs. diff --git a/dojo/sla_config/helpers.py b/dojo/sla_config/helpers.py index e9665adce4..9d76faaa06 100644 --- a/dojo/sla_config/helpers.py +++ b/dojo/sla_config/helpers.py @@ -1,7 +1,8 @@ import logging -from dojo.models import SLA_Configuration, Product, Finding + from dojo.celery import app from dojo.decorators import dojo_async_task +from dojo.models import Finding, Product, SLA_Configuration logger = logging.getLogger(__name__) diff --git a/dojo/sla_config/urls.py b/dojo/sla_config/urls.py index 73f458ebe6..c0a72f6d5c 100644 --- a/dojo/sla_config/urls.py +++ b/dojo/sla_config/urls.py @@ -1,4 +1,5 @@ from django.urls import re_path + from . import views urlpatterns = [ diff --git a/dojo/sla_config/views.py b/dojo/sla_config/views.py index e85b06ea8f..a333946e39 100644 --- a/dojo/sla_config/views.py +++ b/dojo/sla_config/views.py @@ -8,7 +8,7 @@ from dojo.authorization.authorization import user_has_configuration_permission_or_403 from dojo.authorization.authorization_decorators import user_is_configuration_authorized from dojo.forms import SLAConfigForm -from dojo.models import SLA_Configuration, System_Settings, Product +from dojo.models import Product, SLA_Configuration, System_Settings from dojo.utils import add_breadcrumb logger = logging.getLogger(__name__) diff --git a/dojo/survey/urls.py b/dojo/survey/urls.py index 23c2298153..8880bc3bcc 100644 --- a/dojo/survey/urls.py +++ b/dojo/survey/urls.py @@ -3,10 +3,12 @@ @author: jay7958 ''' -from django.urls import re_path -from django.contrib import admin from django.apps import apps +from django.contrib import admin +from django.urls import re_path + from dojo.survey import views + if not apps.ready: apps.get_models() diff --git a/dojo/survey/views.py b/dojo/survey/views.py index 02191342a8..3dc704fe6e 100644 --- a/dojo/survey/views.py +++ b/dojo/survey/views.py @@ -1,29 +1,55 @@ import pickle -from datetime import date +from datetime import date, timedelta from django.contrib import messages +from django.contrib.admin.utils import NestedObjects from django.contrib.contenttypes.models import ContentType from django.core.exceptions import PermissionDenied +from django.db import DEFAULT_DB_ALIAS +from django.http.response import Http404, HttpResponse, HttpResponseRedirect +from django.shortcuts import get_object_or_404, render from django.urls import reverse -from django.http.response import HttpResponseRedirect, HttpResponse, Http404 -from django.shortcuts import render, get_object_or_404 -from django.utils.html import escape -from datetime import timedelta from django.utils import timezone as tz -from django.contrib.admin.utils import NestedObjects -from django.db import DEFAULT_DB_ALIAS +from django.utils.html import escape -from dojo.filters import QuestionnaireFilter, QuestionFilter -from dojo.models import Engagement, System_Settings -from dojo.utils import add_breadcrumb, get_page_items -from dojo.forms import Add_Questionnaire_Form, Delete_Questionnaire_Form, CreateQuestionnaireForm, Delete_Eng_Survey_Form, \ - EditQuestionnaireQuestionsForm, CreateQuestionForm, CreateTextQuestionForm, AssignUserForm, \ - CreateChoiceQuestionForm, EditTextQuestionForm, EditChoiceQuestionForm, AddChoicesForm, \ - AddEngagementForm, AddGeneralQuestionnaireForm, DeleteGeneralQuestionnaireForm -from dojo.models import Answered_Survey, Engagement_Survey, Answer, TextQuestion, ChoiceQuestion, Choice, General_Survey, Question -from dojo.authorization.authorization import user_has_permission_or_403, user_has_permission, user_has_configuration_permission -from dojo.authorization.roles_permissions import Permissions +from dojo.authorization.authorization import ( + user_has_configuration_permission, + user_has_permission, + user_has_permission_or_403, +) from dojo.authorization.authorization_decorators import user_is_authorized, user_is_configuration_authorized +from dojo.authorization.roles_permissions import Permissions +from dojo.filters import QuestionFilter, QuestionnaireFilter +from dojo.forms import ( + Add_Questionnaire_Form, + AddChoicesForm, + AddEngagementForm, + AddGeneralQuestionnaireForm, + AssignUserForm, + CreateChoiceQuestionForm, + CreateQuestionForm, + CreateQuestionnaireForm, + CreateTextQuestionForm, + Delete_Eng_Survey_Form, + Delete_Questionnaire_Form, + DeleteGeneralQuestionnaireForm, + EditChoiceQuestionForm, + EditQuestionnaireQuestionsForm, + EditTextQuestionForm, +) +from dojo.models import ( + Answer, + Answered_Survey, + Choice, + ChoiceQuestion, + Engagement, + Engagement_Survey, + General_Survey, + Question, + System_Settings, + TextQuestion, +) +from dojo.utils import add_breadcrumb, get_page_items @user_is_authorized(Engagement, Permissions.Engagement_Edit, 'eid') diff --git a/dojo/system_settings/urls.py b/dojo/system_settings/urls.py index ab09d255bc..4fc2fec25c 100644 --- a/dojo/system_settings/urls.py +++ b/dojo/system_settings/urls.py @@ -1,4 +1,5 @@ from django.urls import re_path + from . import views urlpatterns = [ diff --git a/dojo/system_settings/views.py b/dojo/system_settings/views.py index d8e885599d..05b02da1e9 100644 --- a/dojo/system_settings/views.py +++ b/dojo/system_settings/views.py @@ -1,13 +1,14 @@ # # product import logging + +from django.conf import settings from django.contrib import messages from django.contrib.auth.decorators import user_passes_test from django.shortcuts import render -from dojo.models import System_Settings -from dojo.utils import (add_breadcrumb, - get_celery_worker_status) + from dojo.forms import SystemSettingsForm -from django.conf import settings +from dojo.models import System_Settings +from dojo.utils import add_breadcrumb, get_celery_worker_status logger = logging.getLogger(__name__) diff --git a/dojo/tasks.py b/dojo/tasks.py index 25d258f9ee..4d089b0ca0 100644 --- a/dojo/tasks.py +++ b/dojo/tasks.py @@ -1,18 +1,18 @@ import logging +from datetime import date, timedelta + from auditlog.models import LogEntry -from datetime import timedelta, date +from celery.utils.log import get_task_logger from dateutil.relativedelta import relativedelta -from django.db.models import Count, Prefetch from django.conf import settings +from django.db.models import Count, Prefetch from django.urls import reverse -from dojo.celery import app -from celery.utils.log import get_task_logger -from dojo.models import Alerts, Product, Engagement, Finding, System_Settings, User from django.utils import timezone -from dojo.utils import calculate_grade -from dojo.utils import sla_compute_and_notify -from dojo.notifications.helper import create_notification +from dojo.celery import app +from dojo.models import Alerts, Engagement, Finding, Product, System_Settings, User +from dojo.notifications.helper import create_notification +from dojo.utils import calculate_grade, sla_compute_and_notify logger = get_task_logger(__name__) deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") diff --git a/dojo/templatetags/announcement_banner_tags.py b/dojo/templatetags/announcement_banner_tags.py index 54b61491ba..616cd40196 100644 --- a/dojo/templatetags/announcement_banner_tags.py +++ b/dojo/templatetags/announcement_banner_tags.py @@ -1,7 +1,7 @@ -from django.utils.safestring import mark_safe import bleach from bleach.css_sanitizer import CSSSanitizer from django import template +from django.utils.safestring import mark_safe register = template.Library() diff --git a/dojo/templatetags/as_json.py b/dojo/templatetags/as_json.py index 5888563e5e..e197556c17 100644 --- a/dojo/templatetags/as_json.py +++ b/dojo/templatetags/as_json.py @@ -1,5 +1,7 @@ import json + from django import template + register = template.Library() diff --git a/dojo/templatetags/authorization_tags.py b/dojo/templatetags/authorization_tags.py index 46b27ad72e..fd4d17d60d 100644 --- a/dojo/templatetags/authorization_tags.py +++ b/dojo/templatetags/authorization_tags.py @@ -1,8 +1,9 @@ -from django import template import crum +from django import template + +from dojo.authorization.authorization import user_has_configuration_permission as configuration_permission +from dojo.authorization.authorization import user_has_global_permission, user_has_permission from dojo.authorization.roles_permissions import Permissions -from dojo.authorization.authorization import user_has_global_permission, user_has_permission, \ - user_has_configuration_permission as configuration_permission from dojo.request_cache import cache_for_request register = template.Library() diff --git a/dojo/templatetags/display_tags.py b/dojo/templatetags/display_tags.py index f09fca50a8..52e9cd3a4f 100644 --- a/dojo/templatetags/display_tags.py +++ b/dojo/templatetags/display_tags.py @@ -1,27 +1,28 @@ +import datetime +import logging from itertools import chain + +import bleach +import dateutil.relativedelta +import git +import markdown from django import template +from django.conf import settings +from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType +from django.db.models import Case, IntegerField, Sum, Value, When from django.template.defaultfilters import stringfilter +from django.urls import reverse from django.utils import timezone -from django.utils.html import escape, conditional_escape -from django.utils.safestring import mark_safe, SafeData +from django.utils.html import conditional_escape, escape +from django.utils.safestring import SafeData, mark_safe from django.utils.text import normalize_newlines from django.utils.translation import gettext as _ -from django.urls import reverse -from django.contrib.auth.models import User -from dojo.utils import prepare_for_view, get_system_setting, get_full_url, get_file_images -import dojo.utils -from dojo.models import Check_List, FileAccessToken, Finding, System_Settings, Product, Dojo_User, Benchmark_Product -import markdown -from django.db.models import Sum, Case, When, IntegerField, Value -import dateutil.relativedelta -import datetime -import bleach -import git -from django.conf import settings import dojo.jira_link.helper as jira_helper -import logging +import dojo.utils +from dojo.models import Benchmark_Product, Check_List, Dojo_User, FileAccessToken, Finding, Product, System_Settings +from dojo.utils import get_file_images, get_full_url, get_system_setting, prepare_for_view logger = logging.getLogger(__name__) diff --git a/dojo/templatetags/event_tags.py b/dojo/templatetags/event_tags.py index 948aa2f516..1c69ab8d8f 100644 --- a/dojo/templatetags/event_tags.py +++ b/dojo/templatetags/event_tags.py @@ -1,8 +1,6 @@ import re -from django import template -from django import forms - +from django import forms, template register = template.Library() diff --git a/dojo/templatetags/get_attribute.py b/dojo/templatetags/get_attribute.py index c813232639..625a722c4f 100644 --- a/dojo/templatetags/get_attribute.py +++ b/dojo/templatetags/get_attribute.py @@ -1,4 +1,5 @@ from django import template + register = template.Library() diff --git a/dojo/templatetags/get_banner.py b/dojo/templatetags/get_banner.py index aa2e5788c5..da1a0f2e01 100644 --- a/dojo/templatetags/get_banner.py +++ b/dojo/templatetags/get_banner.py @@ -1,7 +1,8 @@ -from django.utils.safestring import mark_safe import bleach from bleach.css_sanitizer import CSSSanitizer from django import template +from django.utils.safestring import mark_safe + from dojo.models import BannerConf register = template.Library() diff --git a/dojo/templatetags/get_endpoint_status.py b/dojo/templatetags/get_endpoint_status.py index 1e7a53c7c4..c3dbfd9cea 100644 --- a/dojo/templatetags/get_endpoint_status.py +++ b/dojo/templatetags/get_endpoint_status.py @@ -1,6 +1,8 @@ from django import template -from dojo.models import Endpoint_Status from django.db.models import Q + +from dojo.models import Endpoint_Status + register = template.Library() diff --git a/dojo/templatetags/get_note_status.py b/dojo/templatetags/get_note_status.py index 611002ed91..17aff8a8f0 100644 --- a/dojo/templatetags/get_note_status.py +++ b/dojo/templatetags/get_note_status.py @@ -1,4 +1,5 @@ from django import template + register = template.Library() diff --git a/dojo/templatetags/get_notetype_availability.py b/dojo/templatetags/get_notetype_availability.py index 574a9cc9f0..e3529ab97d 100644 --- a/dojo/templatetags/get_notetype_availability.py +++ b/dojo/templatetags/get_notetype_availability.py @@ -1,4 +1,5 @@ from django import template + register = template.Library() diff --git a/dojo/templatetags/navigation_tags.py b/dojo/templatetags/navigation_tags.py index 4014885bbd..3a1363af33 100644 --- a/dojo/templatetags/navigation_tags.py +++ b/dojo/templatetags/navigation_tags.py @@ -1,12 +1,11 @@ from django import template -from django.utils.safestring import mark_safe as safe from django.utils.html import escape +from django.utils.safestring import mark_safe as safe from django.utils.translation import gettext as _ from dojo.authorization.roles_permissions import Permissions from dojo.product_type.queries import get_authorized_product_types - register = template.Library() diff --git a/dojo/templatetags/survey_tags.py b/dojo/templatetags/survey_tags.py index e8d78cf8d1..c60edc60e1 100644 --- a/dojo/templatetags/survey_tags.py +++ b/dojo/templatetags/survey_tags.py @@ -4,6 +4,7 @@ @author: jay7958 ''' from django import template + from dojo.models import Answered_Survey, Engagement_Survey register = template.Library() diff --git a/dojo/test/queries.py b/dojo/test/queries.py index d6950a76e0..29400451a0 100644 --- a/dojo/test/queries.py +++ b/dojo/test/queries.py @@ -1,8 +1,8 @@ from crum import get_current_user from django.db.models import Exists, OuterRef, Q -from dojo.models import Test, Product_Member, Product_Type_Member, Test_Import, \ - Product_Group, Product_Type_Group + from dojo.authorization.authorization import get_roles_for_permission, user_has_global_permission +from dojo.models import Product_Group, Product_Member, Product_Type_Group, Product_Type_Member, Test, Test_Import def get_authorized_tests(permission, product=None): diff --git a/dojo/test/signals.py b/dojo/test/signals.py index 4e115f5605..6cfb95a4a3 100644 --- a/dojo/test/signals.py +++ b/dojo/test/signals.py @@ -1,8 +1,10 @@ import contextlib +import logging + from django.db.models import signals from django.dispatch import receiver -import logging -from dojo.models import Test, Finding + +from dojo.models import Finding, Test logger = logging.getLogger(__name__) diff --git a/dojo/test/views.py b/dojo/test/views.py index 75c78d5e9b..c6c9877beb 100644 --- a/dojo/test/views.py +++ b/dojo/test/views.py @@ -1,49 +1,85 @@ # # tests -from django.db.models.query import Prefetch -from dojo.engagement.queries import get_authorized_engagements -from dojo.importers.utils import construct_imported_message +import base64 import logging import operator -import base64 from datetime import datetime +from functools import reduce + from django.conf import settings from django.contrib import messages +from django.contrib.admin.utils import NestedObjects from django.core.exceptions import ValidationError -from django.urls import reverse, Resolver404 -from django.db.models import Q, QuerySet, Count -from django.http import HttpResponseRedirect, HttpResponse, HttpRequest -from django.shortcuts import render, get_object_or_404 -from django.views.decorators.cache import cache_page +from django.db import DEFAULT_DB_ALIAS +from django.db.models import Count, Q, QuerySet +from django.db.models.query import Prefetch +from django.http import HttpRequest, HttpResponse, HttpResponseRedirect +from django.shortcuts import get_object_or_404, render +from django.urls import Resolver404, reverse from django.utils import timezone from django.utils.translation import gettext as _ -from django.contrib.admin.utils import NestedObjects -from django.db import DEFAULT_DB_ALIAS - -from dojo.filters import TemplateFindingFilter, FindingFilter, TestImportFilter, FindingFilterWithoutObjectLookups -from dojo.forms import NoteForm, TestForm, \ - DeleteTestForm, AddFindingForm, TypedNoteForm, \ - ReImportScanForm, JIRAFindingForm, JIRAImportScanForm, \ - FindingBulkUpdateForm, CopyTestForm -from dojo.models import IMPORT_UNTOUCHED_FINDING, Finding, Finding_Group, Test, Note_Type, BurpRawRequestResponse, Endpoint, Stub_Finding, \ - Finding_Template, Cred_Mapping, Test_Import, Product_API_Scan_Configuration, Test_Import_Finding_Action +from django.views import View +from django.views.decorators.cache import cache_page +from django.views.decorators.vary import vary_on_cookie -from dojo.tools.factory import get_choices_sorted, get_scan_types_sorted -from dojo.utils import add_error_message_to_response, add_field_errors_to_response, add_success_message_to_response, get_page_items, get_page_items_and_count, add_breadcrumb, get_cal_event, process_notifications, get_system_setting, \ - Product_Tab, is_scan_file_too_large, get_words_for_field, get_setting, async_delete, redirect_to_return_url_or_else, calculate_grade -from dojo.notifications.helper import create_notification -from dojo.finding.views import find_available_notetypes -from functools import reduce -import dojo.jira_link.helper as jira_helper import dojo.finding.helper as finding_helper -from django.views.decorators.vary import vary_on_cookie -from django.views import View -from dojo.authorization.authorization_decorators import user_is_authorized +import dojo.jira_link.helper as jira_helper from dojo.authorization.authorization import user_has_permission_or_403 +from dojo.authorization.authorization_decorators import user_is_authorized from dojo.authorization.roles_permissions import Permissions +from dojo.engagement.queries import get_authorized_engagements +from dojo.filters import FindingFilter, FindingFilterWithoutObjectLookups, TemplateFindingFilter, TestImportFilter +from dojo.finding.views import find_available_notetypes +from dojo.forms import ( + AddFindingForm, + CopyTestForm, + DeleteTestForm, + FindingBulkUpdateForm, + JIRAFindingForm, + JIRAImportScanForm, + NoteForm, + ReImportScanForm, + TestForm, + TypedNoteForm, +) +from dojo.importers.reimporter.reimporter import DojoDefaultReImporter as ReImporter +from dojo.importers.utils import construct_imported_message +from dojo.models import ( + IMPORT_UNTOUCHED_FINDING, + BurpRawRequestResponse, + Cred_Mapping, + Endpoint, + Finding, + Finding_Group, + Finding_Template, + Note_Type, + Product_API_Scan_Configuration, + Stub_Finding, + Test, + Test_Import, + Test_Import_Finding_Action, +) +from dojo.notifications.helper import create_notification from dojo.test.queries import get_authorized_tests +from dojo.tools.factory import get_choices_sorted, get_scan_types_sorted from dojo.user.queries import get_authorized_users -from dojo.importers.reimporter.reimporter import DojoDefaultReImporter as ReImporter - +from dojo.utils import ( + Product_Tab, + add_breadcrumb, + add_error_message_to_response, + add_field_errors_to_response, + add_success_message_to_response, + async_delete, + calculate_grade, + get_cal_event, + get_page_items, + get_page_items_and_count, + get_setting, + get_system_setting, + get_words_for_field, + is_scan_file_too_large, + process_notifications, + redirect_to_return_url_or_else, +) logger = logging.getLogger(__name__) parse_logger = logging.getLogger('dojo') diff --git a/dojo/test_type/views.py b/dojo/test_type/views.py index fac0689104..3b17556b29 100644 --- a/dojo/test_type/views.py +++ b/dojo/test_type/views.py @@ -1,16 +1,17 @@ # # test types import logging -from django.contrib.auth.decorators import login_required from django.contrib import messages -from django.urls import reverse +from django.contrib.auth.decorators import login_required from django.http import HttpResponseRedirect -from django.shortcuts import render, get_object_or_404 +from django.shortcuts import get_object_or_404, render +from django.urls import reverse + +from dojo.authorization.authorization_decorators import user_is_configuration_authorized from dojo.filters import TestTypeFilter from dojo.forms import Test_TypeForm from dojo.models import Test_Type -from dojo.utils import get_page_items, add_breadcrumb -from dojo.authorization.authorization_decorators import user_is_configuration_authorized +from dojo.utils import add_breadcrumb, get_page_items logger = logging.getLogger(__name__) diff --git a/dojo/tool_config/factory.py b/dojo/tool_config/factory.py index 180164b00b..8a1bb203f4 100644 --- a/dojo/tool_config/factory.py +++ b/dojo/tool_config/factory.py @@ -1,11 +1,10 @@ -from dojo.tools.api_bugcrowd.api_client import BugcrowdAPI from dojo.tools.api_blackduck.api_client import BlackduckAPI +from dojo.tools.api_bugcrowd.api_client import BugcrowdAPI from dojo.tools.api_cobalt.api_client import CobaltAPI from dojo.tools.api_edgescan.api_client import EdgescanAPI from dojo.tools.api_sonarqube.api_client import SonarQubeAPI from dojo.tools.api_vulners.api_client import VulnersAPI - SCAN_APIS = { 'Bugcrowd API': BugcrowdAPI, 'BlackDuck API': BlackduckAPI, diff --git a/dojo/tool_config/urls.py b/dojo/tool_config/urls.py index 6a7910ee30..0c7c16c9b9 100644 --- a/dojo/tool_config/urls.py +++ b/dojo/tool_config/urls.py @@ -1,4 +1,5 @@ from django.urls import re_path + from . import views urlpatterns = [ diff --git a/dojo/tool_config/views.py b/dojo/tool_config/views.py index 3bb91c7663..de8976e063 100644 --- a/dojo/tool_config/views.py +++ b/dojo/tool_config/views.py @@ -2,15 +2,15 @@ import logging from django.contrib import messages -from django.urls import reverse from django.http import HttpResponseRedirect from django.shortcuts import render -from dojo.models import Tool_Configuration -from dojo.utils import dojo_crypto_encrypt, prepare_for_view -from dojo.utils import add_breadcrumb +from django.urls import reverse + +from dojo.authorization.authorization_decorators import user_is_configuration_authorized from dojo.forms import ToolConfigForm +from dojo.models import Tool_Configuration from dojo.tool_config.factory import create_API -from dojo.authorization.authorization_decorators import user_is_configuration_authorized +from dojo.utils import add_breadcrumb, dojo_crypto_encrypt, prepare_for_view logger = logging.getLogger(__name__) diff --git a/dojo/tool_product/queries.py b/dojo/tool_product/queries.py index 641bc54b5d..b098ef050a 100644 --- a/dojo/tool_product/queries.py +++ b/dojo/tool_product/queries.py @@ -1,8 +1,8 @@ from crum import get_current_user from django.db.models import Exists, OuterRef, Q -from dojo.models import Tool_Product_Settings, Product_Member, Product_Type_Member, \ - Product_Group, Product_Type_Group + from dojo.authorization.authorization import get_roles_for_permission, user_has_global_permission +from dojo.models import Product_Group, Product_Member, Product_Type_Group, Product_Type_Member, Tool_Product_Settings def get_authorized_tool_product_settings(permission): diff --git a/dojo/tool_product/urls.py b/dojo/tool_product/urls.py index f59ad679fc..cb26295adf 100644 --- a/dojo/tool_product/urls.py +++ b/dojo/tool_product/urls.py @@ -1,4 +1,5 @@ from django.urls import re_path + from . import views urlpatterns = [ diff --git a/dojo/tool_product/views.py b/dojo/tool_product/views.py index b4ae55a2ad..1564cb0ad5 100644 --- a/dojo/tool_product/views.py +++ b/dojo/tool_product/views.py @@ -1,17 +1,18 @@ # # product import logging + from django.contrib import messages from django.core.exceptions import BadRequest from django.http import HttpResponseRedirect +from django.shortcuts import get_object_or_404, render from django.urls import reverse -from django.shortcuts import render, get_object_or_404 from django.utils.translation import gettext as _ +from dojo.authorization.authorization_decorators import user_is_authorized +from dojo.authorization.roles_permissions import Permissions from dojo.forms import DeleteToolProductSettingsForm, ToolProductSettingsForm from dojo.models import Product, Tool_Product_Settings from dojo.utils import Product_Tab -from dojo.authorization.authorization_decorators import user_is_authorized -from dojo.authorization.roles_permissions import Permissions logger = logging.getLogger(__name__) diff --git a/dojo/tool_type/urls.py b/dojo/tool_type/urls.py index 4e05a086d4..8d40e00d77 100644 --- a/dojo/tool_type/urls.py +++ b/dojo/tool_type/urls.py @@ -1,4 +1,5 @@ from django.urls import re_path + from . import views urlpatterns = [ diff --git a/dojo/tool_type/views.py b/dojo/tool_type/views.py index 1ab08c59d2..975f174246 100644 --- a/dojo/tool_type/views.py +++ b/dojo/tool_type/views.py @@ -2,15 +2,15 @@ import logging from django.contrib import messages -from django.urls import reverse from django.http import HttpResponseRedirect from django.shortcuts import render +from django.urls import reverse from django.utils.translation import gettext as _ -from dojo.utils import add_breadcrumb +from dojo.authorization.authorization_decorators import user_is_configuration_authorized from dojo.forms import ToolTypeForm from dojo.models import Tool_Type -from dojo.authorization.authorization_decorators import user_is_configuration_authorized +from dojo.utils import add_breadcrumb logger = logging.getLogger(__name__) diff --git a/dojo/tools/acunetix/parse_acunetix360_json.py b/dojo/tools/acunetix/parse_acunetix360_json.py index 75fb523820..93285a1fb5 100644 --- a/dojo/tools/acunetix/parse_acunetix360_json.py +++ b/dojo/tools/acunetix/parse_acunetix360_json.py @@ -1,7 +1,9 @@ import json -from dateutil import parser + import html2text from cvss import parser as cvss_parser +from dateutil import parser + from dojo.models import Endpoint, Finding diff --git a/dojo/tools/acunetix/parse_acunetix_xml.py b/dojo/tools/acunetix/parse_acunetix_xml.py index da84cbe853..ae6ca8d5ee 100644 --- a/dojo/tools/acunetix/parse_acunetix_xml.py +++ b/dojo/tools/acunetix/parse_acunetix_xml.py @@ -1,11 +1,14 @@ import hashlib +import logging + import dateutil import html2text -import logging import hyperlink from cvss import parser as cvss_parser from defusedxml.ElementTree import parse + from dojo.models import Endpoint, Finding + logger = logging.getLogger(__name__) diff --git a/dojo/tools/anchore_grype/parser.py b/dojo/tools/anchore_grype/parser.py index f129a7c9b3..395955b1eb 100644 --- a/dojo/tools/anchore_grype/parser.py +++ b/dojo/tools/anchore_grype/parser.py @@ -1,4 +1,5 @@ import json + from cvss import parser as cvss_parser from cvss.cvss3 import CVSS3 diff --git a/dojo/tools/api_blackduck/importer.py b/dojo/tools/api_blackduck/importer.py index f84f3e6166..c2606cd0af 100644 --- a/dojo/tools/api_blackduck/importer.py +++ b/dojo/tools/api_blackduck/importer.py @@ -1,4 +1,5 @@ from django.core.exceptions import ValidationError + from dojo.models import Product_API_Scan_Configuration from .api_client import BlackduckAPI diff --git a/dojo/tools/api_bugcrowd/api_client.py b/dojo/tools/api_bugcrowd/api_client.py index 933378724d..6bed971e31 100644 --- a/dojo/tools/api_bugcrowd/api_client.py +++ b/dojo/tools/api_bugcrowd/api_client.py @@ -1,6 +1,7 @@ -import requests from urllib.parse import urlencode +import requests + class BugcrowdAPI: """ diff --git a/dojo/tools/api_bugcrowd/importer.py b/dojo/tools/api_bugcrowd/importer.py index f49ffb1bee..677174cac0 100644 --- a/dojo/tools/api_bugcrowd/importer.py +++ b/dojo/tools/api_bugcrowd/importer.py @@ -1,6 +1,9 @@ import logging + from django.core.exceptions import ValidationError + from dojo.models import Product_API_Scan_Configuration + from .api_client import BugcrowdAPI logger = logging.getLogger(__name__) diff --git a/dojo/tools/api_bugcrowd/parser.py b/dojo/tools/api_bugcrowd/parser.py index 173357f182..6ad71f295c 100644 --- a/dojo/tools/api_bugcrowd/parser.py +++ b/dojo/tools/api_bugcrowd/parser.py @@ -1,13 +1,15 @@ import json +import logging +import re import textwrap from datetime import datetime -from dojo.models import Endpoint, Finding -from .importer import BugcrowdApiImporter -import re + import dateutil.parser -import logging from django.core.exceptions import ValidationError +from dojo.models import Endpoint, Finding + +from .importer import BugcrowdApiImporter SCAN_BUGCROWD_API = "Bugcrowd API Import" diff --git a/dojo/tools/api_cobalt/importer.py b/dojo/tools/api_cobalt/importer.py index d1296bd4ef..068745cfee 100644 --- a/dojo/tools/api_cobalt/importer.py +++ b/dojo/tools/api_cobalt/importer.py @@ -1,6 +1,9 @@ import logging + from django.core.exceptions import ValidationError + from dojo.models import Product_API_Scan_Configuration + from .api_client import CobaltAPI logger = logging.getLogger(__name__) diff --git a/dojo/tools/api_cobalt/parser.py b/dojo/tools/api_cobalt/parser.py index 6be1a4e855..df0425d92b 100644 --- a/dojo/tools/api_cobalt/parser.py +++ b/dojo/tools/api_cobalt/parser.py @@ -1,9 +1,10 @@ import json import textwrap from datetime import datetime + from dojo.models import Endpoint, Finding -from .importer import CobaltApiImporter +from .importer import CobaltApiImporter SCAN_COBALTIO_API = "Cobalt.io API Import" diff --git a/dojo/tools/api_edgescan/api_client.py b/dojo/tools/api_edgescan/api_client.py index 89510721b9..e74c6b9409 100644 --- a/dojo/tools/api_edgescan/api_client.py +++ b/dojo/tools/api_edgescan/api_client.py @@ -1,7 +1,8 @@ -import requests import json from json.decoder import JSONDecodeError +import requests + class EdgescanAPI: """ diff --git a/dojo/tools/api_edgescan/importer.py b/dojo/tools/api_edgescan/importer.py index a5e7c3301d..e740051afa 100644 --- a/dojo/tools/api_edgescan/importer.py +++ b/dojo/tools/api_edgescan/importer.py @@ -1,5 +1,7 @@ from django.core.exceptions import ValidationError + from dojo.models import Product_API_Scan_Configuration + from .api_client import EdgescanAPI diff --git a/dojo/tools/api_edgescan/parser.py b/dojo/tools/api_edgescan/parser.py index 8442c7cc66..b9becbfc5d 100644 --- a/dojo/tools/api_edgescan/parser.py +++ b/dojo/tools/api_edgescan/parser.py @@ -1,7 +1,9 @@ import json from cvss import parser as cvss_parser + from dojo.models import Endpoint, Finding + from .importer import EdgescanImporter ES_SEVERITIES = {1: "Info", 2: "Low", 3: "Medium", 4: "High", 5: "Critical"} diff --git a/dojo/tools/api_sonarqube/importer.py b/dojo/tools/api_sonarqube/importer.py index b0ebe9e3db..11406eb5a5 100644 --- a/dojo/tools/api_sonarqube/importer.py +++ b/dojo/tools/api_sonarqube/importer.py @@ -1,14 +1,15 @@ import logging import re +import textwrap import html2text -from lxml import etree -import textwrap from django.conf import settings from django.core.exceptions import ValidationError +from lxml import etree from dojo.models import Finding, Sonarqube_Issue from dojo.notifications.helper import create_notification + from .api_client import SonarQubeAPI logger = logging.getLogger(__name__) diff --git a/dojo/tools/api_sonarqube/parser.py b/dojo/tools/api_sonarqube/parser.py index 8a57a8d80b..972d8efc7d 100644 --- a/dojo/tools/api_sonarqube/parser.py +++ b/dojo/tools/api_sonarqube/parser.py @@ -1,6 +1,5 @@ from .importer import SonarQubeApiImporter - SCAN_SONARQUBE_API = "SonarQube API Import" diff --git a/dojo/tools/api_sonarqube/updater.py b/dojo/tools/api_sonarqube/updater.py index 4cbf28dc3e..67c724660d 100644 --- a/dojo/tools/api_sonarqube/updater.py +++ b/dojo/tools/api_sonarqube/updater.py @@ -2,6 +2,7 @@ from collections import deque from dojo.models import Sonarqube_Issue_Transition + from .importer import SonarQubeApiImporter logger = logging.getLogger(__name__) diff --git a/dojo/tools/api_sonarqube/updater_from_source.py b/dojo/tools/api_sonarqube/updater_from_source.py index ee8fdb33d6..1c97f8fe40 100644 --- a/dojo/tools/api_sonarqube/updater_from_source.py +++ b/dojo/tools/api_sonarqube/updater_from_source.py @@ -2,9 +2,10 @@ from django.utils import timezone +import dojo.risk_acceptance.helper as ra_helper from dojo.models import Finding, Risk_Acceptance + from .importer import SonarQubeApiImporter -import dojo.risk_acceptance.helper as ra_helper logger = logging.getLogger(__name__) diff --git a/dojo/tools/api_vulners/importer.py b/dojo/tools/api_vulners/importer.py index a0b543699c..89950ae97d 100644 --- a/dojo/tools/api_vulners/importer.py +++ b/dojo/tools/api_vulners/importer.py @@ -1,6 +1,9 @@ import logging + from django.core.exceptions import ValidationError + from dojo.models import Product_API_Scan_Configuration + from .api_client import VulnersAPI logger = logging.getLogger(__name__) diff --git a/dojo/tools/api_vulners/parser.py b/dojo/tools/api_vulners/parser.py index 04969f19c3..a6203ec559 100644 --- a/dojo/tools/api_vulners/parser.py +++ b/dojo/tools/api_vulners/parser.py @@ -1,8 +1,10 @@ import json import logging + from cvss.cvss3 import CVSS3 from dojo.models import Endpoint, Finding + from .importer import VulnersImporter logger = logging.getLogger(__name__) diff --git a/dojo/tools/asff/parser.py b/dojo/tools/asff/parser.py index f47dd87645..3b01ef7c3e 100644 --- a/dojo/tools/asff/parser.py +++ b/dojo/tools/asff/parser.py @@ -1,6 +1,8 @@ import json + import dateutil from netaddr import IPAddress + from dojo.models import Endpoint, Finding SEVERITY_MAPPING = { diff --git a/dojo/tools/auditjs/parser.py b/dojo/tools/auditjs/parser.py index 73c3ca8ce0..678e11e8e6 100644 --- a/dojo/tools/auditjs/parser.py +++ b/dojo/tools/auditjs/parser.py @@ -1,9 +1,11 @@ import json -from json.decoder import JSONDecodeError import re -from dojo.models import Finding -from cvss import CVSS3, CVSS2 +from json.decoder import JSONDecodeError + import cvss.parser +from cvss import CVSS2, CVSS3 + +from dojo.models import Finding class AuditJSParser: diff --git a/dojo/tools/aws_scout2/parser.py b/dojo/tools/aws_scout2/parser.py index 8fd45eba17..6b30e6c0da 100644 --- a/dojo/tools/aws_scout2/parser.py +++ b/dojo/tools/aws_scout2/parser.py @@ -2,9 +2,10 @@ import textwrap from datetime import datetime -from dojo.models import Finding from html2text import html2text +from dojo.models import Finding + class AWSScout2Parser: # FIXME bad very bad diff --git a/dojo/tools/awssecurityhub/compliance.py b/dojo/tools/awssecurityhub/compliance.py index 914a196b80..83b0f23972 100644 --- a/dojo/tools/awssecurityhub/compliance.py +++ b/dojo/tools/awssecurityhub/compliance.py @@ -1,4 +1,5 @@ from datetime import datetime + from dojo.models import Finding diff --git a/dojo/tools/awssecurityhub/guardduty.py b/dojo/tools/awssecurityhub/guardduty.py index 5ec977e46d..5d33c913a9 100644 --- a/dojo/tools/awssecurityhub/guardduty.py +++ b/dojo/tools/awssecurityhub/guardduty.py @@ -1,5 +1,6 @@ from datetime import datetime -from dojo.models import Finding, Endpoint + +from dojo.models import Endpoint, Finding class GuardDuty: diff --git a/dojo/tools/awssecurityhub/inspector.py b/dojo/tools/awssecurityhub/inspector.py index 2eecd309c2..8ffe0bb18b 100644 --- a/dojo/tools/awssecurityhub/inspector.py +++ b/dojo/tools/awssecurityhub/inspector.py @@ -1,5 +1,6 @@ from datetime import datetime -from dojo.models import Finding, Endpoint + +from dojo.models import Endpoint, Finding class Inspector: diff --git a/dojo/tools/awssecurityhub/parser.py b/dojo/tools/awssecurityhub/parser.py index 6cda17bb23..54babccf73 100644 --- a/dojo/tools/awssecurityhub/parser.py +++ b/dojo/tools/awssecurityhub/parser.py @@ -1,7 +1,8 @@ import json -from dojo.tools.awssecurityhub.inspector import Inspector -from dojo.tools.awssecurityhub.guardduty import GuardDuty + from dojo.tools.awssecurityhub.compliance import Compliance +from dojo.tools.awssecurityhub.guardduty import GuardDuty +from dojo.tools.awssecurityhub.inspector import Inspector class AwsSecurityHubParser: diff --git a/dojo/tools/azure_security_center_recommendations/parser.py b/dojo/tools/azure_security_center_recommendations/parser.py index 19dc794dab..e4f02cf3b8 100644 --- a/dojo/tools/azure_security_center_recommendations/parser.py +++ b/dojo/tools/azure_security_center_recommendations/parser.py @@ -1,7 +1,8 @@ -import sys -import io import csv +import io +import sys from datetime import datetime + from dojo.models import Finding diff --git a/dojo/tools/bandit/parser.py b/dojo/tools/bandit/parser.py index 1641e37327..b209648847 100644 --- a/dojo/tools/bandit/parser.py +++ b/dojo/tools/bandit/parser.py @@ -1,4 +1,5 @@ import json + import dateutil.parser from dojo.models import Finding diff --git a/dojo/tools/bearer_cli/parser.py b/dojo/tools/bearer_cli/parser.py index c0a9735150..0aca0bcbe4 100644 --- a/dojo/tools/bearer_cli/parser.py +++ b/dojo/tools/bearer_cli/parser.py @@ -1,4 +1,5 @@ import json + from dojo.models import Finding diff --git a/dojo/tools/blackduck/parser.py b/dojo/tools/blackduck/parser.py index ea05cdb231..4b21c28619 100644 --- a/dojo/tools/blackduck/parser.py +++ b/dojo/tools/blackduck/parser.py @@ -1,6 +1,7 @@ import hashlib from dojo.models import Finding + from .importer import BlackduckImporter diff --git a/dojo/tools/blackduck_binary_analysis/parser.py b/dojo/tools/blackduck_binary_analysis/parser.py index eb47fc7c7c..2f0523223e 100644 --- a/dojo/tools/blackduck_binary_analysis/parser.py +++ b/dojo/tools/blackduck_binary_analysis/parser.py @@ -1,8 +1,10 @@ import hashlib +from cvss import CVSS2, CVSS3 + from dojo.models import Finding + from .importer import BlackduckBinaryAnalysisImporter -from cvss import CVSS2, CVSS3 class BlackduckBinaryAnalysisParser: diff --git a/dojo/tools/blackduck_component_risk/importer.py b/dojo/tools/blackduck_component_risk/importer.py index db10d823b7..14bf05ce47 100644 --- a/dojo/tools/blackduck_component_risk/importer.py +++ b/dojo/tools/blackduck_component_risk/importer.py @@ -1,7 +1,7 @@ import csv import io -import zipfile import logging +import zipfile from pathlib import Path logger = logging.getLogger(__name__) diff --git a/dojo/tools/blackduck_component_risk/parser.py b/dojo/tools/blackduck_component_risk/parser.py index 7f6916962b..7e683364f4 100644 --- a/dojo/tools/blackduck_component_risk/parser.py +++ b/dojo/tools/blackduck_component_risk/parser.py @@ -1,7 +1,8 @@ # Author: apipia, wheelsvt -from .importer import BlackduckCRImporter from dojo.models import Finding +from .importer import BlackduckCRImporter + class BlackduckComponentRiskParser: """ diff --git a/dojo/tools/bugcrowd/parser.py b/dojo/tools/bugcrowd/parser.py index fcd36b1344..d3672255bf 100644 --- a/dojo/tools/bugcrowd/parser.py +++ b/dojo/tools/bugcrowd/parser.py @@ -3,6 +3,7 @@ import io from dateutil import parser + from dojo.models import Endpoint, Finding diff --git a/dojo/tools/burp/parser.py b/dojo/tools/burp/parser.py index cb7e461f33..f260e598b3 100644 --- a/dojo/tools/burp/parser.py +++ b/dojo/tools/burp/parser.py @@ -1,8 +1,10 @@ import base64 import logging import re + import html2text from defusedxml import ElementTree as etree + from dojo.models import Endpoint, Finding logger = logging.getLogger(__name__) diff --git a/dojo/tools/burp_api/parser.py b/dojo/tools/burp_api/parser.py index 6063a41b59..75e4e87507 100644 --- a/dojo/tools/burp_api/parser.py +++ b/dojo/tools/burp_api/parser.py @@ -1,6 +1,6 @@ +import base64 import json import logging -import base64 from dojo.models import Endpoint, Finding diff --git a/dojo/tools/burp_dastardly/parser.py b/dojo/tools/burp_dastardly/parser.py index 686fb59e1a..3d60653488 100644 --- a/dojo/tools/burp_dastardly/parser.py +++ b/dojo/tools/burp_dastardly/parser.py @@ -1,5 +1,7 @@ import logging + from defusedxml import ElementTree as etree + from dojo.models import Finding logger = logging.getLogger(__name__) diff --git a/dojo/tools/burp_graphql/parser.py b/dojo/tools/burp_graphql/parser.py index 4fc968c02b..f6d032bc28 100644 --- a/dojo/tools/burp_graphql/parser.py +++ b/dojo/tools/burp_graphql/parser.py @@ -1,8 +1,8 @@ -import logging import json +import logging import re -import html2text +import html2text from dojo.models import Endpoint, Finding diff --git a/dojo/tools/cargo_audit/parser.py b/dojo/tools/cargo_audit/parser.py index ccff968cc6..e992e93651 100644 --- a/dojo/tools/cargo_audit/parser.py +++ b/dojo/tools/cargo_audit/parser.py @@ -1,5 +1,6 @@ -import json import hashlib +import json + from dojo.models import Finding diff --git a/dojo/tools/checkmarx_one/parser.py b/dojo/tools/checkmarx_one/parser.py index 2f2892585f..d3ef4c77fd 100644 --- a/dojo/tools/checkmarx_one/parser.py +++ b/dojo/tools/checkmarx_one/parser.py @@ -1,6 +1,8 @@ import datetime import json + from dateutil import parser + from dojo.models import Finding diff --git a/dojo/tools/checkmarx_osa/parser.py b/dojo/tools/checkmarx_osa/parser.py index ac3d14e033..c2f8c9fcca 100644 --- a/dojo/tools/checkmarx_osa/parser.py +++ b/dojo/tools/checkmarx_osa/parser.py @@ -1,8 +1,9 @@ import json import logging -from dojo.models import Finding from datetime import datetime +from dojo.models import Finding + logger = logging.getLogger(__name__) diff --git a/dojo/tools/chefinspect/parser.py b/dojo/tools/chefinspect/parser.py index 30feaa586e..1dd413df62 100644 --- a/dojo/tools/chefinspect/parser.py +++ b/dojo/tools/chefinspect/parser.py @@ -1,4 +1,5 @@ import json + from dojo.models import Finding diff --git a/dojo/tools/clair/clair_parser.py b/dojo/tools/clair/clair_parser.py index 381a1b97ed..784132e376 100644 --- a/dojo/tools/clair/clair_parser.py +++ b/dojo/tools/clair/clair_parser.py @@ -1,5 +1,7 @@ import logging + from dojo.models import Finding + logger = logging.getLogger(__name__) diff --git a/dojo/tools/clair/clairklar_parser.py b/dojo/tools/clair/clairklar_parser.py index f942ad30aa..c42ba78b32 100644 --- a/dojo/tools/clair/clairklar_parser.py +++ b/dojo/tools/clair/clairklar_parser.py @@ -1,5 +1,7 @@ import logging + from dojo.models import Finding + logger = logging.getLogger(__name__) diff --git a/dojo/tools/clair/parser.py b/dojo/tools/clair/parser.py index a87e46d5bb..dd03c49d7c 100644 --- a/dojo/tools/clair/parser.py +++ b/dojo/tools/clair/parser.py @@ -1,4 +1,5 @@ import json + from dojo.tools.clair.clair_parser import ClairScan from dojo.tools.clair.clairklar_parser import ClairKlarScan diff --git a/dojo/tools/codechecker/parser.py b/dojo/tools/codechecker/parser.py index f73302e7da..41998099e5 100644 --- a/dojo/tools/codechecker/parser.py +++ b/dojo/tools/codechecker/parser.py @@ -1,5 +1,6 @@ -import json import hashlib +import json + from dojo.models import Finding diff --git a/dojo/tools/contrast/parser.py b/dojo/tools/contrast/parser.py index 17d566ea5e..73e3b94c7b 100644 --- a/dojo/tools/contrast/parser.py +++ b/dojo/tools/contrast/parser.py @@ -1,8 +1,8 @@ import csv +import datetime import hashlib import io import sys -import datetime from dojo.models import Endpoint, Finding diff --git a/dojo/tools/cred_scan/parser.py b/dojo/tools/cred_scan/parser.py index bbca3b687a..6b67305caa 100644 --- a/dojo/tools/cred_scan/parser.py +++ b/dojo/tools/cred_scan/parser.py @@ -1,6 +1,8 @@ import csv import io + from dateutil import parser + from dojo.models import Finding diff --git a/dojo/tools/crunch42/parser.py b/dojo/tools/crunch42/parser.py index 8478132824..ff09dddcd6 100644 --- a/dojo/tools/crunch42/parser.py +++ b/dojo/tools/crunch42/parser.py @@ -1,4 +1,5 @@ import json + from dojo.models import Finding diff --git a/dojo/tools/cyclonedx/helpers.py b/dojo/tools/cyclonedx/helpers.py index 98a76bfe10..fb658dfdc1 100644 --- a/dojo/tools/cyclonedx/helpers.py +++ b/dojo/tools/cyclonedx/helpers.py @@ -1,5 +1,7 @@ -from cvss import CVSS3 import logging + +from cvss import CVSS3 + LOGGER = logging.getLogger(__name__) diff --git a/dojo/tools/cyclonedx/json_parser.py b/dojo/tools/cyclonedx/json_parser.py index ddd1dfbd7b..a57b6debaf 100644 --- a/dojo/tools/cyclonedx/json_parser.py +++ b/dojo/tools/cyclonedx/json_parser.py @@ -1,8 +1,11 @@ import json import logging + import dateutil + from dojo.models import Finding from dojo.tools.cyclonedx.helpers import Cyclonedxhelper + LOGGER = logging.getLogger(__name__) diff --git a/dojo/tools/cyclonedx/xml_parser.py b/dojo/tools/cyclonedx/xml_parser.py index e0be085c0f..91ba3ab0a9 100644 --- a/dojo/tools/cyclonedx/xml_parser.py +++ b/dojo/tools/cyclonedx/xml_parser.py @@ -1,9 +1,12 @@ -import re import logging +import re + import dateutil from defusedxml import ElementTree + from dojo.models import Finding from dojo.tools.cyclonedx.helpers import Cyclonedxhelper + LOGGER = logging.getLogger(__name__) diff --git a/dojo/tools/dawnscanner/parser.py b/dojo/tools/dawnscanner/parser.py index 98b91d36ad..9fb2085a1f 100644 --- a/dojo/tools/dawnscanner/parser.py +++ b/dojo/tools/dawnscanner/parser.py @@ -2,6 +2,7 @@ import re from dateutil import parser + from dojo.models import Finding diff --git a/dojo/tools/dependency_check/parser.py b/dojo/tools/dependency_check/parser.py index 493089dbce..870aba11fb 100644 --- a/dojo/tools/dependency_check/parser.py +++ b/dojo/tools/dependency_check/parser.py @@ -1,12 +1,12 @@ import hashlib import logging import re -import dateutil +from datetime import datetime +import dateutil from cpe import CPE from defusedxml import ElementTree from packageurl import PackageURL -from datetime import datetime from dojo.models import Finding diff --git a/dojo/tools/detect_secrets/parser.py b/dojo/tools/detect_secrets/parser.py index 3e450a02a1..7f139b8230 100644 --- a/dojo/tools/detect_secrets/parser.py +++ b/dojo/tools/detect_secrets/parser.py @@ -1,6 +1,8 @@ -import json import hashlib +import json + import dateutil.parser + from dojo.models import Finding diff --git a/dojo/tools/dockerbench/parser.py b/dojo/tools/dockerbench/parser.py index a00db912d2..4c08b850e0 100644 --- a/dojo/tools/dockerbench/parser.py +++ b/dojo/tools/dockerbench/parser.py @@ -1,7 +1,7 @@ import json +from datetime import datetime from dojo.models import Finding -from datetime import datetime class DockerBenchParser: diff --git a/dojo/tools/dockle/parser.py b/dojo/tools/dockle/parser.py index e2d0be9256..b650694078 100644 --- a/dojo/tools/dockle/parser.py +++ b/dojo/tools/dockle/parser.py @@ -1,5 +1,6 @@ -import json import hashlib +import json + from dojo.models import Finding diff --git a/dojo/tools/dsop/parser.py b/dojo/tools/dsop/parser.py index 64bdc2250e..0e4834f367 100644 --- a/dojo/tools/dsop/parser.py +++ b/dojo/tools/dsop/parser.py @@ -1,4 +1,5 @@ import re + from openpyxl import load_workbook from dojo.models import Finding diff --git a/dojo/tools/factory.py b/dojo/tools/factory.py index 891fd830dd..2ec6f7c036 100644 --- a/dojo/tools/factory.py +++ b/dojo/tools/factory.py @@ -1,12 +1,14 @@ -import re import logging import os -from inspect import isclass -from pathlib import Path +import re from importlib import import_module from importlib.util import find_spec +from inspect import isclass +from pathlib import Path + from django.conf import settings -from dojo.models import Test_Type, Tool_Type, Tool_Configuration + +from dojo.models import Test_Type, Tool_Configuration, Tool_Type PARSERS = {} diff --git a/dojo/tools/fortify/fpr_parser.py b/dojo/tools/fortify/fpr_parser.py index 811bfd4f82..ca4d268668 100644 --- a/dojo/tools/fortify/fpr_parser.py +++ b/dojo/tools/fortify/fpr_parser.py @@ -1,6 +1,8 @@ import re import zipfile + from defusedxml import ElementTree + from dojo.models import Finding diff --git a/dojo/tools/fortify/parser.py b/dojo/tools/fortify/parser.py index 3eef4071d5..85fdc6d33e 100644 --- a/dojo/tools/fortify/parser.py +++ b/dojo/tools/fortify/parser.py @@ -1,5 +1,5 @@ -from dojo.tools.fortify.xml_parser import FortifyXMLParser from dojo.tools.fortify.fpr_parser import FortifyFPRParser +from dojo.tools.fortify.xml_parser import FortifyXMLParser class FortifyParser: diff --git a/dojo/tools/fortify/xml_parser.py b/dojo/tools/fortify/xml_parser.py index a6f1d11d4a..92469da88c 100644 --- a/dojo/tools/fortify/xml_parser.py +++ b/dojo/tools/fortify/xml_parser.py @@ -1,4 +1,5 @@ from defusedxml import ElementTree + from dojo.models import Finding diff --git a/dojo/tools/gcloud_artifact_scan/parser.py b/dojo/tools/gcloud_artifact_scan/parser.py index 54bd27d5a1..d531f9b6f6 100644 --- a/dojo/tools/gcloud_artifact_scan/parser.py +++ b/dojo/tools/gcloud_artifact_scan/parser.py @@ -1,4 +1,5 @@ import json + from dojo.models import Finding diff --git a/dojo/tools/generic/parser.py b/dojo/tools/generic/parser.py index 1e5858bbd7..dffbeeab6d 100644 --- a/dojo/tools/generic/parser.py +++ b/dojo/tools/generic/parser.py @@ -5,6 +5,7 @@ from cvss import parser as cvss_parser from dateutil.parser import parse + from dojo.models import Endpoint, Finding from dojo.tools.parser_test import ParserTest diff --git a/dojo/tools/ggshield/parser.py b/dojo/tools/ggshield/parser.py index d0bc8f5abc..383c334390 100644 --- a/dojo/tools/ggshield/parser.py +++ b/dojo/tools/ggshield/parser.py @@ -1,8 +1,10 @@ -import json import hashlib -from dojo.models import Finding +import json + from dateutil import parser +from dojo.models import Finding + class GgshieldParser: """ diff --git a/dojo/tools/github_vulnerability/parser.py b/dojo/tools/github_vulnerability/parser.py index 4ca7830971..3739fc6f20 100644 --- a/dojo/tools/github_vulnerability/parser.py +++ b/dojo/tools/github_vulnerability/parser.py @@ -1,7 +1,8 @@ -import dateutil import json +import dateutil from cvss import parser as cvss_parser + from dojo.models import Finding diff --git a/dojo/tools/gitlab_container_scan/parser.py b/dojo/tools/gitlab_container_scan/parser.py index 65ceb27f28..4aa245c399 100644 --- a/dojo/tools/gitlab_container_scan/parser.py +++ b/dojo/tools/gitlab_container_scan/parser.py @@ -2,6 +2,7 @@ import textwrap from dateutil.parser import parse + from dojo.models import Finding diff --git a/dojo/tools/gitlab_dast/parser.py b/dojo/tools/gitlab_dast/parser.py index 0c6eab1dbe..83a7829af6 100644 --- a/dojo/tools/gitlab_dast/parser.py +++ b/dojo/tools/gitlab_dast/parser.py @@ -1,7 +1,8 @@ -import json import hashlib +import json from datetime import datetime -from dojo.models import Finding, Endpoint + +from dojo.models import Endpoint, Finding class GitlabDastParser: diff --git a/dojo/tools/gitlab_secret_detection_report/parser.py b/dojo/tools/gitlab_secret_detection_report/parser.py index ce72f04bf9..f3c6f4c6ea 100644 --- a/dojo/tools/gitlab_secret_detection_report/parser.py +++ b/dojo/tools/gitlab_secret_detection_report/parser.py @@ -1,5 +1,6 @@ import json from datetime import datetime + from dojo.models import Finding diff --git a/dojo/tools/govulncheck/parser.py b/dojo/tools/govulncheck/parser.py index 2deb7d70e8..f348a33a06 100644 --- a/dojo/tools/govulncheck/parser.py +++ b/dojo/tools/govulncheck/parser.py @@ -1,7 +1,7 @@ import json -from itertools import groupby -from itertools import islice import logging +from itertools import groupby, islice + from dojo.models import Finding logger = logging.getLogger(__name__) diff --git a/dojo/tools/hcl_appscan/parser.py b/dojo/tools/hcl_appscan/parser.py index 99862e17aa..ddd8c9e60c 100644 --- a/dojo/tools/hcl_appscan/parser.py +++ b/dojo/tools/hcl_appscan/parser.py @@ -1,6 +1,8 @@ from xml.dom import NamespaceErr + from defusedxml import ElementTree as ET -from dojo.models import Finding, Endpoint + +from dojo.models import Endpoint, Finding class HCLAppScanParser: diff --git a/dojo/tools/horusec/parser.py b/dojo/tools/horusec/parser.py index 579cf2d662..8e9571820f 100644 --- a/dojo/tools/horusec/parser.py +++ b/dojo/tools/horusec/parser.py @@ -2,6 +2,7 @@ from datetime import datetime from dateutil.parser import parse + from dojo.models import Finding from dojo.tools.parser_test import ParserTest diff --git a/dojo/tools/humble/parser.py b/dojo/tools/humble/parser.py index c99619dcfd..f9044c0210 100644 --- a/dojo/tools/humble/parser.py +++ b/dojo/tools/humble/parser.py @@ -1,5 +1,6 @@ import json -from dojo.models import Finding, Endpoint + +from dojo.models import Endpoint, Finding class HumbleParser: diff --git a/dojo/tools/hydra/parser.py b/dojo/tools/hydra/parser.py index a91adc88d3..677130bd47 100644 --- a/dojo/tools/hydra/parser.py +++ b/dojo/tools/hydra/parser.py @@ -1,10 +1,11 @@ import json -from datetime import date import logging +from datetime import date -from dojo.models import Finding, Endpoint from django.utils.dateparse import parse_datetime +from dojo.models import Endpoint, Finding + logger = logging.getLogger(__name__) diff --git a/dojo/tools/intsights/parser.py b/dojo/tools/intsights/parser.py index 4c029ce0aa..cd6a61a57a 100644 --- a/dojo/tools/intsights/parser.py +++ b/dojo/tools/intsights/parser.py @@ -1,4 +1,5 @@ import logging + from dojo.models import Finding from dojo.tools.intsights.csv_handler import IntSightsCSVParser from dojo.tools.intsights.json_handler import IntSightsJSONParser diff --git a/dojo/tools/jfrog_xray_api_summary_artifact/parser.py b/dojo/tools/jfrog_xray_api_summary_artifact/parser.py index 43a8145ffb..7453669b47 100644 --- a/dojo/tools/jfrog_xray_api_summary_artifact/parser.py +++ b/dojo/tools/jfrog_xray_api_summary_artifact/parser.py @@ -1,9 +1,9 @@ +import hashlib import json import re -import hashlib from cvss import CVSS3 -from cvss.exceptions import CVSS3RHScoreDoesNotMatch, CVSS3RHMalformedError +from cvss.exceptions import CVSS3RHMalformedError, CVSS3RHScoreDoesNotMatch from dojo.models import Finding diff --git a/dojo/tools/kics/parser.py b/dojo/tools/kics/parser.py index 7974db2ba5..f0b2c1defc 100644 --- a/dojo/tools/kics/parser.py +++ b/dojo/tools/kics/parser.py @@ -1,5 +1,6 @@ -import json import hashlib +import json + from dojo.models import Finding diff --git a/dojo/tools/kubeaudit/parser.py b/dojo/tools/kubeaudit/parser.py index 2fc887685c..065eb45427 100644 --- a/dojo/tools/kubeaudit/parser.py +++ b/dojo/tools/kubeaudit/parser.py @@ -1,4 +1,5 @@ import json + from dojo.models import Finding diff --git a/dojo/tools/kubehunter/parser.py b/dojo/tools/kubehunter/parser.py index af60ef19da..54e2bfa842 100644 --- a/dojo/tools/kubehunter/parser.py +++ b/dojo/tools/kubehunter/parser.py @@ -1,5 +1,6 @@ import hashlib import json + from dojo.models import Finding diff --git a/dojo/tools/kubescape/parser.py b/dojo/tools/kubescape/parser.py index 8f4c790a86..a5797e8402 100644 --- a/dojo/tools/kubescape/parser.py +++ b/dojo/tools/kubescape/parser.py @@ -1,4 +1,5 @@ import json + from dojo.models import Finding diff --git a/dojo/tools/meterian/parser.py b/dojo/tools/meterian/parser.py index f959713a64..ab9fa93392 100644 --- a/dojo/tools/meterian/parser.py +++ b/dojo/tools/meterian/parser.py @@ -1,6 +1,6 @@ import json - from datetime import datetime + from dojo.models import Finding diff --git a/dojo/tools/mobsfscan/parser.py b/dojo/tools/mobsfscan/parser.py index b65f63c980..67c30ffb1c 100644 --- a/dojo/tools/mobsfscan/parser.py +++ b/dojo/tools/mobsfscan/parser.py @@ -1,6 +1,7 @@ -import json import hashlib +import json import re + from dojo.models import Finding diff --git a/dojo/tools/ms_defender/parser.py b/dojo/tools/ms_defender/parser.py index 6cf4ba3cf3..3ce7c9a562 100644 --- a/dojo/tools/ms_defender/parser.py +++ b/dojo/tools/ms_defender/parser.py @@ -1,7 +1,8 @@ import json -from dojo.models import Finding, Endpoint import zipfile +from dojo.models import Endpoint, Finding + class MSDefenderParser: """ diff --git a/dojo/tools/nancy/parser.py b/dojo/tools/nancy/parser.py index 7fae9821fa..19534728c8 100644 --- a/dojo/tools/nancy/parser.py +++ b/dojo/tools/nancy/parser.py @@ -1,6 +1,7 @@ import json from cvss.cvss3 import CVSS3 + from dojo.models import Finding diff --git a/dojo/tools/netsparker/parser.py b/dojo/tools/netsparker/parser.py index f574dbb67b..1a61276fda 100644 --- a/dojo/tools/netsparker/parser.py +++ b/dojo/tools/netsparker/parser.py @@ -1,9 +1,10 @@ -import json -import html2text import datetime +import json +import html2text from cvss import parser as cvss_parser -from dojo.models import Finding, Endpoint + +from dojo.models import Endpoint, Finding class NetsparkerParser: diff --git a/dojo/tools/neuvector_compliance/parser.py b/dojo/tools/neuvector_compliance/parser.py index cf4367143a..adf05d0729 100644 --- a/dojo/tools/neuvector_compliance/parser.py +++ b/dojo/tools/neuvector_compliance/parser.py @@ -3,7 +3,6 @@ from dojo.models import Finding - NEUVECTOR_SCAN_NAME = "NeuVector (compliance)" diff --git a/dojo/tools/nexpose/parser.py b/dojo/tools/nexpose/parser.py index 1af6630a96..67908e03d6 100644 --- a/dojo/tools/nexpose/parser.py +++ b/dojo/tools/nexpose/parser.py @@ -1,11 +1,12 @@ -import html2text import re -from defusedxml import ElementTree -from hyperlink._url import SCHEME_PORT_MAP from datetime import datetime + +import html2text +from defusedxml import ElementTree from django.conf import settings +from hyperlink._url import SCHEME_PORT_MAP -from dojo.models import Finding, Endpoint +from dojo.models import Endpoint, Finding class NexposeParser: diff --git a/dojo/tools/nikto/json_parser.py b/dojo/tools/nikto/json_parser.py index 4e4509c490..bde6ef3e62 100644 --- a/dojo/tools/nikto/json_parser.py +++ b/dojo/tools/nikto/json_parser.py @@ -1,4 +1,5 @@ import json + from dojo.models import Endpoint, Finding diff --git a/dojo/tools/nikto/xml_parser.py b/dojo/tools/nikto/xml_parser.py index 7397029290..ab5dffe906 100644 --- a/dojo/tools/nikto/xml_parser.py +++ b/dojo/tools/nikto/xml_parser.py @@ -1,9 +1,12 @@ -import re import hashlib import logging -from dojo.models import Endpoint, Finding +import re + from defusedxml import ElementTree as ET from django.core.exceptions import ValidationError + +from dojo.models import Endpoint, Finding + logger = logging.getLogger(__name__) diff --git a/dojo/tools/nmap/parser.py b/dojo/tools/nmap/parser.py index b7630f217a..3cb37710a9 100644 --- a/dojo/tools/nmap/parser.py +++ b/dojo/tools/nmap/parser.py @@ -2,6 +2,7 @@ from cpe import CPE from defusedxml.ElementTree import parse + from dojo.models import Endpoint, Finding diff --git a/dojo/tools/noseyparker/parser.py b/dojo/tools/noseyparker/parser.py index 467855173b..7e1138b1be 100644 --- a/dojo/tools/noseyparker/parser.py +++ b/dojo/tools/noseyparker/parser.py @@ -1,7 +1,7 @@ import hashlib import json - from datetime import datetime + from dojo.models import Finding diff --git a/dojo/tools/npm_audit_7_plus/parser.py b/dojo/tools/npm_audit_7_plus/parser.py index b7afa60aed..89c4a8575f 100644 --- a/dojo/tools/npm_audit_7_plus/parser.py +++ b/dojo/tools/npm_audit_7_plus/parser.py @@ -1,6 +1,7 @@ """Parser for NPM Audit v7+ Scan.""" import json import logging + from dojo.models import Finding logger = logging.getLogger(__name__) diff --git a/dojo/tools/nuclei/parser.py b/dojo/tools/nuclei/parser.py index 2318b1dc64..4e97c4f6b7 100644 --- a/dojo/tools/nuclei/parser.py +++ b/dojo/tools/nuclei/parser.py @@ -1,10 +1,11 @@ -import json import hashlib +import json import logging + from cvss import parser as cvss_parser from dateutil import parser as date_parser -from dojo.models import Finding, Endpoint +from dojo.models import Endpoint, Finding logger = logging.getLogger(__name__) diff --git a/dojo/tools/openscap/parser.py b/dojo/tools/openscap/parser.py index 91411b2bba..a96a1cdcca 100644 --- a/dojo/tools/openscap/parser.py +++ b/dojo/tools/openscap/parser.py @@ -2,10 +2,10 @@ import re from defusedxml.ElementTree import parse +from django.core.exceptions import ValidationError +from django.core.validators import validate_ipv46_address from dojo.models import Endpoint, Finding -from django.core.validators import validate_ipv46_address -from django.core.exceptions import ValidationError class OpenscapParser: diff --git a/dojo/tools/openvas/csv_parser.py b/dojo/tools/openvas/csv_parser.py index d6c4f80b4a..ff9e8bf888 100644 --- a/dojo/tools/openvas/csv_parser.py +++ b/dojo/tools/openvas/csv_parser.py @@ -2,8 +2,10 @@ import hashlib import io import re + from dateutil.parser import parse -from dojo.models import Finding, Endpoint + +from dojo.models import Endpoint, Finding class ColumnMappingStrategy: diff --git a/dojo/tools/openvas/xml_parser.py b/dojo/tools/openvas/xml_parser.py index 4466727095..3746d5c27b 100644 --- a/dojo/tools/openvas/xml_parser.py +++ b/dojo/tools/openvas/xml_parser.py @@ -1,5 +1,7 @@ from xml.dom import NamespaceErr + from defusedxml import ElementTree as ET + from dojo.models import Finding diff --git a/dojo/tools/osv_scanner/parser.py b/dojo/tools/osv_scanner/parser.py index 7c411e3884..42e9408825 100644 --- a/dojo/tools/osv_scanner/parser.py +++ b/dojo/tools/osv_scanner/parser.py @@ -1,4 +1,5 @@ import json + from dojo.models import Finding diff --git a/dojo/tools/pmd/parser.py b/dojo/tools/pmd/parser.py index f63f366752..484d289b03 100644 --- a/dojo/tools/pmd/parser.py +++ b/dojo/tools/pmd/parser.py @@ -1,6 +1,7 @@ -import io import csv import hashlib +import io + from dojo.models import Finding diff --git a/dojo/tools/popeye/parser.py b/dojo/tools/popeye/parser.py index 75603e26cf..65ac0d8580 100644 --- a/dojo/tools/popeye/parser.py +++ b/dojo/tools/popeye/parser.py @@ -1,6 +1,7 @@ import hashlib import json import re + from dojo.models import Finding diff --git a/dojo/tools/pwn_sast/parser.py b/dojo/tools/pwn_sast/parser.py index ac0b0a0912..0a4ba9652e 100644 --- a/dojo/tools/pwn_sast/parser.py +++ b/dojo/tools/pwn_sast/parser.py @@ -1,5 +1,5 @@ -import json import hashlib +import json from dojo.models import Finding diff --git a/dojo/tools/qualys/csv_parser.py b/dojo/tools/qualys/csv_parser.py index 53b792af8b..20f5314305 100644 --- a/dojo/tools/qualys/csv_parser.py +++ b/dojo/tools/qualys/csv_parser.py @@ -3,6 +3,7 @@ import logging import re from datetime import datetime + from django.conf import settings from dojo.models import Endpoint, Finding diff --git a/dojo/tools/qualys/parser.py b/dojo/tools/qualys/parser.py index c8a69763d9..79fe3e003a 100644 --- a/dojo/tools/qualys/parser.py +++ b/dojo/tools/qualys/parser.py @@ -1,8 +1,9 @@ import datetime import logging + import html2text -from defusedxml import ElementTree as etree from cvss import CVSS3 +from defusedxml import ElementTree as etree from django.conf import settings from dojo.models import Endpoint, Finding diff --git a/dojo/tools/qualys_webapp/parser.py b/dojo/tools/qualys_webapp/parser.py index e1e1799c43..c978750af5 100644 --- a/dojo/tools/qualys_webapp/parser.py +++ b/dojo/tools/qualys_webapp/parser.py @@ -2,6 +2,7 @@ import re import xml.etree.ElementTree from datetime import datetime + from dojo.models import Endpoint, Finding try: diff --git a/dojo/tools/redhatsatellite/parser.py b/dojo/tools/redhatsatellite/parser.py index 34ff2a8321..6130fb2a7a 100644 --- a/dojo/tools/redhatsatellite/parser.py +++ b/dojo/tools/redhatsatellite/parser.py @@ -1,4 +1,5 @@ import json + from dojo.models import Finding diff --git a/dojo/tools/risk_recon/parser.py b/dojo/tools/risk_recon/parser.py index f75921f6ea..7d14b6ebce 100644 --- a/dojo/tools/risk_recon/parser.py +++ b/dojo/tools/risk_recon/parser.py @@ -1,6 +1,7 @@ import json import dateutil + from dojo.models import Finding from dojo.tools.risk_recon.api import RiskReconAPI diff --git a/dojo/tools/rusty_hog/parser.py b/dojo/tools/rusty_hog/parser.py index 4b870ee796..4ffd6c9ade 100644 --- a/dojo/tools/rusty_hog/parser.py +++ b/dojo/tools/rusty_hog/parser.py @@ -1,6 +1,7 @@ import json -from dojo.tools.parser_test import ParserTest + from dojo.models import Finding +from dojo.tools.parser_test import ParserTest class RustyhogParser: diff --git a/dojo/tools/sarif/parser.py b/dojo/tools/sarif/parser.py index 1f42f6d2a7..d3fa31f742 100644 --- a/dojo/tools/sarif/parser.py +++ b/dojo/tools/sarif/parser.py @@ -2,11 +2,12 @@ import logging import re import textwrap + import dateutil.parser from django.utils.translation import gettext as _ -from dojo.tools.parser_test import ParserTest from dojo.models import Finding +from dojo.tools.parser_test import ParserTest logger = logging.getLogger(__name__) diff --git a/dojo/tools/snyk/parser.py b/dojo/tools/snyk/parser.py index 04120e80ee..055d278d29 100644 --- a/dojo/tools/snyk/parser.py +++ b/dojo/tools/snyk/parser.py @@ -1,6 +1,7 @@ import json from cvss.cvss3 import CVSS3 + from dojo.models import Finding diff --git a/dojo/tools/snyk_code/parser.py b/dojo/tools/snyk_code/parser.py index fa9172774c..cd7d74a4a4 100644 --- a/dojo/tools/snyk_code/parser.py +++ b/dojo/tools/snyk_code/parser.py @@ -1,6 +1,7 @@ import json from cvss.cvss3 import CVSS3 + from dojo.models import Finding diff --git a/dojo/tools/solar_appscreener/parser.py b/dojo/tools/solar_appscreener/parser.py index 2c161631ce..b5655a4292 100644 --- a/dojo/tools/solar_appscreener/parser.py +++ b/dojo/tools/solar_appscreener/parser.py @@ -1,5 +1,6 @@ import csv import io + from dojo.models import Finding diff --git a/dojo/tools/sonarqube/parser.py b/dojo/tools/sonarqube/parser.py index 1645f1bb49..1f268001d8 100644 --- a/dojo/tools/sonarqube/parser.py +++ b/dojo/tools/sonarqube/parser.py @@ -1,11 +1,14 @@ +import json import logging -from dojo.tools.sonarqube.soprasteria_json import SonarQubeSoprasteriaJSON -from dojo.tools.sonarqube.soprasteria_html import SonarQubeSoprasteriaHTML +import zipfile + +from lxml import etree + from dojo.tools.sonarqube.sonarqube_restapi_json import SonarQubeRESTAPIJSON from dojo.tools.sonarqube.sonarqube_restapi_zip import SonarQubeRESTAPIZIP -from lxml import etree -import zipfile -import json +from dojo.tools.sonarqube.soprasteria_html import SonarQubeSoprasteriaHTML +from dojo.tools.sonarqube.soprasteria_json import SonarQubeSoprasteriaJSON + logger = logging.getLogger(__name__) diff --git a/dojo/tools/sonarqube/sonarqube_restapi_json.py b/dojo/tools/sonarqube/sonarqube_restapi_json.py index 53771467d6..6985117ecd 100644 --- a/dojo/tools/sonarqube/sonarqube_restapi_json.py +++ b/dojo/tools/sonarqube/sonarqube_restapi_json.py @@ -1,6 +1,7 @@ -from dojo.models import Finding import re +from dojo.models import Finding + class SonarQubeRESTAPIJSON: def get_json_items(self, json_content, test, mode): diff --git a/dojo/tools/sonarqube/sonarqube_restapi_zip.py b/dojo/tools/sonarqube/sonarqube_restapi_zip.py index 42169e793b..983678423a 100644 --- a/dojo/tools/sonarqube/sonarqube_restapi_zip.py +++ b/dojo/tools/sonarqube/sonarqube_restapi_zip.py @@ -1,6 +1,7 @@ -from dojo.tools.sonarqube.sonarqube_restapi_json import SonarQubeRESTAPIJSON import json +from dojo.tools.sonarqube.sonarqube_restapi_json import SonarQubeRESTAPIJSON + class SonarQubeRESTAPIZIP: def get_items(self, files, test, mode): diff --git a/dojo/tools/sonarqube/soprasteria_helper.py b/dojo/tools/sonarqube/soprasteria_helper.py index fe4e1f3e7b..ac5ca6f68f 100644 --- a/dojo/tools/sonarqube/soprasteria_helper.py +++ b/dojo/tools/sonarqube/soprasteria_helper.py @@ -1,8 +1,11 @@ import logging import re + from django.utils.html import strip_tags from lxml import etree + from dojo.models import Finding + logger = logging.getLogger(__name__) diff --git a/dojo/tools/sonarqube/soprasteria_html.py b/dojo/tools/sonarqube/soprasteria_html.py index 8ee2054427..8865ac618e 100644 --- a/dojo/tools/sonarqube/soprasteria_html.py +++ b/dojo/tools/sonarqube/soprasteria_html.py @@ -1,5 +1,7 @@ import logging + from dojo.tools.sonarqube.soprasteria_helper import SonarQubeSoprasteriaHelper + logger = logging.getLogger(__name__) diff --git a/dojo/tools/sonarqube/soprasteria_json.py b/dojo/tools/sonarqube/soprasteria_json.py index bfd52a69de..5feb49343c 100644 --- a/dojo/tools/sonarqube/soprasteria_json.py +++ b/dojo/tools/sonarqube/soprasteria_json.py @@ -1,6 +1,9 @@ import logging -from dojo.tools.sonarqube.soprasteria_helper import SonarQubeSoprasteriaHelper + from lxml import etree + +from dojo.tools.sonarqube.soprasteria_helper import SonarQubeSoprasteriaHelper + logger = logging.getLogger(__name__) diff --git a/dojo/tools/sonatype/parser.py b/dojo/tools/sonatype/parser.py index 5458f64a9f..ef2f0df367 100644 --- a/dojo/tools/sonatype/parser.py +++ b/dojo/tools/sonatype/parser.py @@ -1,4 +1,5 @@ import json + from dojo.models import Finding from dojo.tools.sonatype.identifier import ComponentIdentifier diff --git a/dojo/tools/spotbugs/parser.py b/dojo/tools/spotbugs/parser.py index 47aeedb98c..367fd54d49 100644 --- a/dojo/tools/spotbugs/parser.py +++ b/dojo/tools/spotbugs/parser.py @@ -1,6 +1,8 @@ import re + import html2text from defusedxml import ElementTree as ET + from dojo.models import Finding diff --git a/dojo/tools/ssh_audit/parser.py b/dojo/tools/ssh_audit/parser.py index efd21be1b8..4e3ddb4b36 100644 --- a/dojo/tools/ssh_audit/parser.py +++ b/dojo/tools/ssh_audit/parser.py @@ -1,4 +1,5 @@ import json + from dojo.models import Endpoint, Finding diff --git a/dojo/tools/stackhawk/parser.py b/dojo/tools/stackhawk/parser.py index 9030dcd9a3..5aa85dfa49 100644 --- a/dojo/tools/stackhawk/parser.py +++ b/dojo/tools/stackhawk/parser.py @@ -1,8 +1,9 @@ import json -from dojo.models import Endpoint, Finding from django.utils.dateparse import parse_datetime +from dojo.models import Endpoint, Finding + class StackHawkScanMetadata: def __init__(self, completed_scan): diff --git a/dojo/tools/sysdig_reports/parser.py b/dojo/tools/sysdig_reports/parser.py index 633780c48b..7d1ad6dc89 100644 --- a/dojo/tools/sysdig_reports/parser.py +++ b/dojo/tools/sysdig_reports/parser.py @@ -1,9 +1,10 @@ -from dojo.models import Finding -from dojo.tools.sysdig_reports.sysdig_csv_parser import CSVParser +import json -from cvss.cvss3 import CVSS3 import cvss.parser -import json +from cvss.cvss3 import CVSS3 + +from dojo.models import Finding +from dojo.tools.sysdig_reports.sysdig_csv_parser import CSVParser class SysdigReportsParser: diff --git a/dojo/tools/sysdig_reports/sysdig_csv_parser.py b/dojo/tools/sysdig_reports/sysdig_csv_parser.py index 8962531d2d..199baa6f9f 100644 --- a/dojo/tools/sysdig_reports/sysdig_csv_parser.py +++ b/dojo/tools/sysdig_reports/sysdig_csv_parser.py @@ -1,5 +1,6 @@ import csv import io + from dojo.tools.sysdig_reports.sysdig_data import SysdigData diff --git a/dojo/tools/terrascan/parser.py b/dojo/tools/terrascan/parser.py index 1c08f310e6..ebc761f93b 100644 --- a/dojo/tools/terrascan/parser.py +++ b/dojo/tools/terrascan/parser.py @@ -1,5 +1,6 @@ -import json import hashlib +import json + from dojo.models import Finding diff --git a/dojo/tools/tfsec/parser.py b/dojo/tools/tfsec/parser.py index 017fe74820..8e145a92d9 100644 --- a/dojo/tools/tfsec/parser.py +++ b/dojo/tools/tfsec/parser.py @@ -1,5 +1,6 @@ -import json import hashlib +import json + from dojo.models import Finding diff --git a/dojo/tools/tool_issue_updater.py b/dojo/tools/tool_issue_updater.py index b9c4fe20b1..79c4d0ff10 100644 --- a/dojo/tools/tool_issue_updater.py +++ b/dojo/tools/tool_issue_updater.py @@ -1,7 +1,5 @@ from dojo.celery import app - -from dojo.decorators import (dojo_async_task, dojo_model_from_id, - dojo_model_to_id) +from dojo.decorators import dojo_async_task, dojo_model_from_id, dojo_model_to_id from dojo.tools.api_sonarqube.parser import SCAN_SONARQUBE_API @@ -31,8 +29,7 @@ def tool_issue_updater(finding, *args, **kwargs): @dojo_async_task @app.task def update_findings_from_source_issues(**kwargs): - from dojo.tools.api_sonarqube.updater_from_source import \ - SonarQubeApiUpdaterFromSource + from dojo.tools.api_sonarqube.updater_from_source import SonarQubeApiUpdaterFromSource findings = SonarQubeApiUpdaterFromSource().get_findings_to_update() diff --git a/dojo/tools/trivy_operator/parser.py b/dojo/tools/trivy_operator/parser.py index e11d5cbb2d..7bd3a3d1da 100644 --- a/dojo/tools/trivy_operator/parser.py +++ b/dojo/tools/trivy_operator/parser.py @@ -3,10 +3,11 @@ """ import json -from dojo.tools.trivy_operator.vulnerability_handler import TrivyVulnerabilityHandler + from dojo.tools.trivy_operator.checks_handler import TrivyChecksHandler -from dojo.tools.trivy_operator.secrets_handler import TrivySecretsHandler from dojo.tools.trivy_operator.compliance_handler import TrivyComplianceHandler +from dojo.tools.trivy_operator.secrets_handler import TrivySecretsHandler +from dojo.tools.trivy_operator.vulnerability_handler import TrivyVulnerabilityHandler class TrivyOperatorParser: diff --git a/dojo/tools/trustwave_fusion_api/parser.py b/dojo/tools/trustwave_fusion_api/parser.py index 57c93024bd..6b6bf2a27a 100644 --- a/dojo/tools/trustwave_fusion_api/parser.py +++ b/dojo/tools/trustwave_fusion_api/parser.py @@ -1,9 +1,11 @@ -import json import hashlib +import json from datetime import datetime -from dojo.models import Finding, Endpoint + from cpe import CPE +from dojo.models import Endpoint, Finding + class TrustwaveFusionAPIParser: """ diff --git a/dojo/tools/veracode/json_parser.py b/dojo/tools/veracode/json_parser.py index 991f365a70..7f2111eff0 100644 --- a/dojo/tools/veracode/json_parser.py +++ b/dojo/tools/veracode/json_parser.py @@ -1,10 +1,11 @@ import json import re + from cvss import CVSS3 from dateutil import parser from django.conf import settings -from dojo.models import Finding, Endpoint +from dojo.models import Endpoint, Finding class VeracodeJSONParser: diff --git a/dojo/tools/veracode/xml_parser.py b/dojo/tools/veracode/xml_parser.py index e7d64f8df1..ce08e14f45 100644 --- a/dojo/tools/veracode/xml_parser.py +++ b/dojo/tools/veracode/xml_parser.py @@ -1,11 +1,11 @@ import re import uuid from datetime import datetime -from django.conf import settings from defusedxml import ElementTree +from django.conf import settings -from dojo.models import Finding, Endpoint +from dojo.models import Endpoint, Finding XML_NAMESPACE = {"x": "https://www.veracode.com/schema/reports/export/1.0"} diff --git a/dojo/tools/veracode_sca/parser.py b/dojo/tools/veracode_sca/parser.py index c660a66ca2..7cb730801b 100644 --- a/dojo/tools/veracode_sca/parser.py +++ b/dojo/tools/veracode_sca/parser.py @@ -1,12 +1,11 @@ import csv -import json import io +import json +from datetime import datetime from cvss import parser as cvss_parser -from datetime import datetime from dateutil import parser from django.conf import settings - from django.utils import timezone from dojo.models import Finding diff --git a/dojo/tools/wapiti/parser.py b/dojo/tools/wapiti/parser.py index d4c9b9dccc..4245e72f1a 100644 --- a/dojo/tools/wapiti/parser.py +++ b/dojo/tools/wapiti/parser.py @@ -1,12 +1,11 @@ -import re import hashlib import logging +import re from defusedxml.ElementTree import parse from dojo.models import Endpoint, Finding - logger = logging.getLogger(__name__) diff --git a/dojo/tools/wazuh/parser.py b/dojo/tools/wazuh/parser.py index e7ec473eb6..dcdf42effa 100644 --- a/dojo/tools/wazuh/parser.py +++ b/dojo/tools/wazuh/parser.py @@ -1,6 +1,7 @@ import hashlib import json -from dojo.models import Finding, Endpoint + +from dojo.models import Endpoint, Finding class WazuhParser: diff --git a/dojo/tools/wfuzz/parser.py b/dojo/tools/wfuzz/parser.py index 6fcbf62b1f..2ac1dfbb27 100644 --- a/dojo/tools/wfuzz/parser.py +++ b/dojo/tools/wfuzz/parser.py @@ -1,8 +1,9 @@ -import json import hashlib +import json + import hyperlink -from dojo.models import Finding, Endpoint +from dojo.models import Endpoint, Finding class WFuzzParser: diff --git a/dojo/tools/whitehat_sentinel/parser.py b/dojo/tools/whitehat_sentinel/parser.py index 0952f188d9..77428939ec 100644 --- a/dojo/tools/whitehat_sentinel/parser.py +++ b/dojo/tools/whitehat_sentinel/parser.py @@ -2,9 +2,10 @@ import json import logging import re -from typing import Union, List from datetime import datetime -from dojo.models import Finding, Endpoint +from typing import List, Union + +from dojo.models import Endpoint, Finding class WhiteHatSentinelParser: diff --git a/dojo/tools/wiz/parser.py b/dojo/tools/wiz/parser.py index 07fbf8e2d1..722a7d2dec 100644 --- a/dojo/tools/wiz/parser.py +++ b/dojo/tools/wiz/parser.py @@ -1,6 +1,7 @@ import csv import io import sys + from dojo.models import Finding diff --git a/dojo/urls.py b/dojo/urls.py index 3b5c335ada..0c5320711e 100644 --- a/dojo/urls.py +++ b/dojo/urls.py @@ -1,66 +1,111 @@ +import logging + from django.conf import settings -from django.urls import re_path from django.conf.urls import include from django.contrib import admin -from rest_framework.routers import DefaultRouter -from rest_framework.authtoken import views as tokenviews from django.http import HttpResponse -from dojo import views -from dojo.api_v2.views import EndPointViewSet, EngagementViewSet, \ - FindingTemplatesViewSet, FindingViewSet, JiraInstanceViewSet, \ - JiraIssuesViewSet, JiraProjectViewSet, ProductViewSet, CredentialsViewSet, CredentialsMappingViewSet, \ - SLAConfigurationViewset, StubFindingsViewSet, TestImportViewSet, TestsViewSet, TestTypesViewSet, \ - ToolConfigurationsViewSet, ToolProductSettingsViewSet, ToolTypesViewSet, \ - UsersViewSet, ImportScanView, ReImportScanView, ProductTypeViewSet, DojoMetaViewSet, \ - DevelopmentEnvironmentViewSet, NotesViewSet, NoteTypeViewSet, SystemSettingsViewSet, \ - AppAnalysisViewSet, EndpointStatusViewSet, SonarqubeIssueViewSet, SonarqubeIssueTransitionViewSet, \ - RegulationsViewSet, ProductTypeMemberViewSet, ProductMemberViewSet, RiskAcceptanceViewSet, \ - DojoGroupViewSet, ProductGroupViewSet, ProductTypeGroupViewSet, RoleViewSet, GlobalRoleViewSet, \ - DojoGroupMemberViewSet, ImportLanguagesView, LanguageTypeViewSet, LanguageViewSet, \ - NotificationsViewSet, EngagementPresetsViewset, NetworkLocationsViewset, UserContactInfoViewSet, \ - ProductAPIScanConfigurationViewSet, UserProfileView, EndpointMetaImporterView, \ - ConfigurationPermissionViewSet, QuestionnaireQuestionViewSet, QuestionnaireAnswerViewSet, \ - QuestionnaireGeneralSurveyViewSet, QuestionnaireEngagementSurveyViewSet, QuestionnaireAnsweredSurveyViewSet, \ - AnnouncementViewSet +from django.urls import re_path +from drf_spectacular.views import SpectacularSwaggerView +from rest_framework.authtoken import views as tokenviews +from rest_framework.routers import DefaultRouter -from dojo.utils import get_system_setting +from dojo import views +from dojo.announcement.urls import urlpatterns as announcement_urls +from dojo.api_v2.views import ( + AnnouncementViewSet, + AppAnalysisViewSet, + ConfigurationPermissionViewSet, + CredentialsMappingViewSet, + CredentialsViewSet, + DevelopmentEnvironmentViewSet, + DojoGroupMemberViewSet, + DojoGroupViewSet, + DojoMetaViewSet, + EndpointMetaImporterView, + EndpointStatusViewSet, + EndPointViewSet, + EngagementPresetsViewset, + EngagementViewSet, + FindingTemplatesViewSet, + FindingViewSet, + GlobalRoleViewSet, + ImportLanguagesView, + ImportScanView, + JiraInstanceViewSet, + JiraIssuesViewSet, + JiraProjectViewSet, + LanguageTypeViewSet, + LanguageViewSet, + NetworkLocationsViewset, + NotesViewSet, + NoteTypeViewSet, + NotificationsViewSet, + ProductAPIScanConfigurationViewSet, + ProductGroupViewSet, + ProductMemberViewSet, + ProductTypeGroupViewSet, + ProductTypeMemberViewSet, + ProductTypeViewSet, + ProductViewSet, + QuestionnaireAnsweredSurveyViewSet, + QuestionnaireAnswerViewSet, + QuestionnaireEngagementSurveyViewSet, + QuestionnaireGeneralSurveyViewSet, + QuestionnaireQuestionViewSet, + RegulationsViewSet, + ReImportScanView, + RiskAcceptanceViewSet, + RoleViewSet, + SLAConfigurationViewset, + SonarqubeIssueTransitionViewSet, + SonarqubeIssueViewSet, + StubFindingsViewSet, + SystemSettingsViewSet, + TestImportViewSet, + TestsViewSet, + TestTypesViewSet, + ToolConfigurationsViewSet, + ToolProductSettingsViewSet, + ToolTypesViewSet, + UserContactInfoViewSet, + UserProfileView, + UsersViewSet, +) +from dojo.api_v2.views import DojoSpectacularAPIView as SpectacularAPIView +from dojo.banner.urls import urlpatterns as banner_urls +from dojo.benchmark.urls import urlpatterns as benchmark_urls +from dojo.components.urls import urlpatterns as component_urls +from dojo.cred.urls import urlpatterns as cred_urls from dojo.development_environment.urls import urlpatterns as dev_env_urls from dojo.endpoint.urls import urlpatterns as endpoint_urls from dojo.engagement.urls import urlpatterns as eng_urls from dojo.finding.urls import urlpatterns as finding_urls from dojo.finding_group.urls import urlpatterns as finding_group_urls +from dojo.github_issue_link.urls import urlpatterns as github_urls +from dojo.group.urls import urlpatterns as group_urls from dojo.home.urls import urlpatterns as home_urls +from dojo.jira_link.urls import urlpatterns as jira_urls from dojo.metrics.urls import urlpatterns as metrics_urls +from dojo.note_type.urls import urlpatterns as note_type_urls +from dojo.notes.urls import urlpatterns as notes_urls +from dojo.notifications.urls import urlpatterns as notifications_urls +from dojo.object.urls import urlpatterns as object_urls from dojo.product.urls import urlpatterns as prod_urls from dojo.product_type.urls import urlpatterns as pt_urls +from dojo.regulations.urls import urlpatterns as regulations from dojo.reports.urls import urlpatterns as reports_urls from dojo.search.urls import urlpatterns as search_urls +from dojo.sla_config.urls import urlpatterns as sla_urls +from dojo.survey.urls import urlpatterns as survey_urls +from dojo.system_settings.urls import urlpatterns as system_settings_urls from dojo.test.urls import urlpatterns as test_urls from dojo.test_type.urls import urlpatterns as test_type_urls -from dojo.user.urls import urlpatterns as user_urls -from dojo.group.urls import urlpatterns as group_urls -from dojo.jira_link.urls import urlpatterns as jira_urls -from dojo.github_issue_link.urls import urlpatterns as github_urls -from dojo.tool_type.urls import urlpatterns as tool_type_urls from dojo.tool_config.urls import urlpatterns as tool_config_urls from dojo.tool_product.urls import urlpatterns as tool_product_urls -from dojo.cred.urls import urlpatterns as cred_urls -from dojo.sla_config.urls import urlpatterns as sla_urls -from dojo.system_settings.urls import urlpatterns as system_settings_urls -from dojo.notifications.urls import urlpatterns as notifications_urls -from dojo.object.urls import urlpatterns as object_urls -from dojo.benchmark.urls import urlpatterns as benchmark_urls -from dojo.notes.urls import urlpatterns as notes_urls -from dojo.note_type.urls import urlpatterns as note_type_urls -from dojo.banner.urls import urlpatterns as banner_urls -from dojo.survey.urls import urlpatterns as survey_urls -from dojo.components.urls import urlpatterns as component_urls -from dojo.regulations.urls import urlpatterns as regulations -from dojo.announcement.urls import urlpatterns as announcement_urls -from drf_spectacular.views import SpectacularSwaggerView -from dojo.api_v2.views import DojoSpectacularAPIView as SpectacularAPIView +from dojo.tool_type.urls import urlpatterns as tool_type_urls +from dojo.user.urls import urlpatterns as user_urls +from dojo.utils import get_system_setting -import logging logger = logging.getLogger(__name__) admin.autodiscover() diff --git a/dojo/user/queries.py b/dojo/user/queries.py index 163c0e1565..1242dbb7dd 100644 --- a/dojo/user/queries.py +++ b/dojo/user/queries.py @@ -1,8 +1,15 @@ from crum import get_current_user from django.db.models import Q -from dojo.models import Dojo_Group_Member, Product_Member, Product_Type_Member, \ - Product_Group, Product_Type_Group, Dojo_User + from dojo.authorization.authorization import get_roles_for_permission, user_has_global_permission +from dojo.models import ( + Dojo_Group_Member, + Dojo_User, + Product_Group, + Product_Member, + Product_Type_Group, + Product_Type_Member, +) from dojo.product.queries import get_authorized_products from dojo.product_type.queries import get_authorized_product_types from dojo.request_cache import cache_for_request diff --git a/dojo/user/urls.py b/dojo/user/urls.py index a11a2c4956..22fb861e22 100644 --- a/dojo/user/urls.py +++ b/dojo/user/urls.py @@ -1,7 +1,7 @@ +from django.conf import settings from django.conf.urls import include -from django.urls import re_path, reverse_lazy from django.contrib.auth import views as auth_views -from django.conf import settings +from django.urls import re_path, reverse_lazy from dojo.user import views diff --git a/dojo/user/validators.py b/dojo/user/validators.py index 767bc560b5..b84f171797 100644 --- a/dojo/user/validators.py +++ b/dojo/user/validators.py @@ -1,8 +1,9 @@ import re +from django.contrib.auth.password_validation import CommonPasswordValidator from django.core.exceptions import ValidationError from django.utils.translation import gettext -from django.contrib.auth.password_validation import CommonPasswordValidator + from dojo.utils import get_system_setting diff --git a/dojo/user/views.py b/dojo/user/views.py index 94f07668ba..c971d932c1 100644 --- a/dojo/user/views.py +++ b/dojo/user/views.py @@ -1,45 +1,55 @@ import contextlib import logging -from crum import get_current_user from datetime import timedelta +import hyperlink +from crum import get_current_user from django.conf import settings from django.contrib import messages from django.contrib.admin.utils import NestedObjects from django.contrib.auth import logout -from django.contrib.auth.decorators import user_passes_test, login_required +from django.contrib.auth.decorators import login_required, user_passes_test from django.contrib.auth.forms import AuthenticationForm, PasswordResetForm from django.contrib.auth.views import LoginView, PasswordResetView from django.contrib.humanize.templatetags.humanize import naturaltime -from django.core.mail import get_connection -from django.core.mail.backends.smtp import EmailBackend from django.core import serializers from django.core.exceptions import PermissionDenied, ValidationError +from django.core.mail import get_connection +from django.core.mail.backends.smtp import EmailBackend from django.db import DEFAULT_DB_ALIAS from django.db.models import Q from django.db.models.deletion import RestrictedError -from django.http import HttpResponseRedirect, HttpResponse, JsonResponse -from django.shortcuts import render, get_object_or_404 +from django.http import HttpResponse, HttpResponseRedirect, JsonResponse +from django.shortcuts import get_object_or_404, render from django.urls import reverse from django.utils.http import urlencode -from django.utils.translation import gettext as _ from django.utils.timezone import now - +from django.utils.translation import gettext as _ from rest_framework.authtoken.models import Token +from dojo.authorization.authorization_decorators import user_is_configuration_authorized +from dojo.authorization.roles_permissions import Permissions +from dojo.decorators import dojo_ratelimit from dojo.filters import UserFilter -from dojo.forms import DojoUserForm, ChangePasswordForm, AddDojoUserForm, EditDojoUserForm, DeleteUserForm, APIKeyForm, UserContactInfoForm, \ - Add_Product_Type_Member_UserForm, Add_Product_Member_UserForm, GlobalRoleForm, Add_Group_Member_UserForm, ConfigurationPermissionsForm -from dojo.models import Dojo_User, Alerts, Product_Member, Product_Type_Member, Dojo_Group_Member -from dojo.utils import get_page_items, add_breadcrumb, get_system_setting -from dojo.product.queries import get_authorized_product_members_for_user +from dojo.forms import ( + Add_Group_Member_UserForm, + Add_Product_Member_UserForm, + Add_Product_Type_Member_UserForm, + AddDojoUserForm, + APIKeyForm, + ChangePasswordForm, + ConfigurationPermissionsForm, + DeleteUserForm, + DojoUserForm, + EditDojoUserForm, + GlobalRoleForm, + UserContactInfoForm, +) from dojo.group.queries import get_authorized_group_members_for_user +from dojo.models import Alerts, Dojo_Group_Member, Dojo_User, Product_Member, Product_Type_Member +from dojo.product.queries import get_authorized_product_members_for_user from dojo.product_type.queries import get_authorized_product_type_members_for_user -from dojo.authorization.roles_permissions import Permissions -from dojo.decorators import dojo_ratelimit -from dojo.authorization.authorization_decorators import user_is_configuration_authorized - -import hyperlink +from dojo.utils import add_breadcrumb, get_page_items, get_system_setting logger = logging.getLogger(__name__) diff --git a/dojo/utils.py b/dojo/utils.py index 22d737a974..4e01297393 100644 --- a/dojo/utils.py +++ b/dojo/utils.py @@ -1,44 +1,65 @@ -from dojo.authorization.roles_permissions import Permissions -from dojo.finding.queries import get_authorized_findings -import re import binascii -import os +import calendar as tcalendar import hashlib -import bleach +import logging import mimetypes -import hyperlink -from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes -from cryptography.hazmat.backends import default_backend +import os +import re from calendar import monthrange from datetime import date, datetime, timedelta from math import pi, sqrt + +import bleach +import crum +import hyperlink import vobject -from dateutil.relativedelta import relativedelta, MO, SU +from asteval import Interpreter +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from dateutil.parser import parse +from dateutil.relativedelta import MO, SU, relativedelta from django.conf import settings +from django.contrib import messages +from django.contrib.auth.signals import user_logged_in, user_logged_out, user_login_failed from django.core.paginator import Paginator -from django.urls import get_resolver, reverse, get_script_prefix -from django.db.models import Q, Sum, Case, When, IntegerField, Value, Count -from django.utils import timezone -from django.utils.translation import gettext as _ -from django.dispatch import receiver -from django.db.models.signals import post_save +from django.db.models import Case, Count, IntegerField, Q, Sum, Value, When from django.db.models.query import QuerySet -import calendar as tcalendar -from dojo.github import add_external_issue_github, update_external_issue_github, close_external_issue_github, reopen_external_issue_github -from dojo.models import Finding, Engagement, Finding_Group, Finding_Template, Product, \ - Test, User, Dojo_User, System_Settings, Notifications, Endpoint, Benchmark_Type, \ - Language_Type, Languages, Dojo_Group_Member, NOTIFICATION_CHOICES -from asteval import Interpreter -from dojo.notifications.helper import create_notification -import logging -from django.contrib import messages +from django.db.models.signals import post_save +from django.dispatch import receiver from django.http import HttpResponseRedirect -import crum +from django.urls import get_resolver, get_script_prefix, reverse +from django.utils import timezone +from django.utils.translation import gettext as _ + +from dojo.authorization.roles_permissions import Permissions from dojo.celery import app from dojo.decorators import dojo_async_task, dojo_model_from_id, dojo_model_to_id -from django.contrib.auth.signals import user_logged_in, user_logged_out, user_login_failed - +from dojo.finding.queries import get_authorized_findings +from dojo.github import ( + add_external_issue_github, + close_external_issue_github, + reopen_external_issue_github, + update_external_issue_github, +) +from dojo.models import ( + NOTIFICATION_CHOICES, + Benchmark_Type, + Dojo_Group_Member, + Dojo_User, + Endpoint, + Engagement, + Finding, + Finding_Group, + Finding_Template, + Language_Type, + Languages, + Notifications, + Product, + System_Settings, + Test, + User, +) +from dojo.notifications.helper import create_notification logger = logging.getLogger(__name__) deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") @@ -1757,8 +1778,7 @@ def is_safe_url(url): from django.utils.http import url_has_allowed_host_and_scheme except ImportError: # django < 3 - from django.utils.http import \ - is_safe_url as url_has_allowed_host_and_scheme + from django.utils.http import is_safe_url as url_has_allowed_host_and_scheme return url_has_allowed_host_and_scheme(url, allowed_hosts=None) diff --git a/dojo/views.py b/dojo/views.py index f6df1bdac5..db90c1f944 100644 --- a/dojo/views.py +++ b/dojo/views.py @@ -1,22 +1,27 @@ import logging import os + from auditlog.models import LogEntry -from django.contrib.contenttypes.models import ContentType -from django.contrib import messages -from django.core.exceptions import PermissionDenied, ObjectDoesNotExist -from django.http import Http404, HttpResponseRedirect, FileResponse from django.conf import settings -from django.urls import reverse +from django.contrib import messages from django.contrib.auth.decorators import login_required +from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import ObjectDoesNotExist, PermissionDenied +from django.http import FileResponse, Http404, HttpResponseRedirect +from django.shortcuts import get_object_or_404, render +from django.urls import reverse from django.views.static import serve -from django.shortcuts import render, get_object_or_404 -from dojo.models import Engagement, Test, Finding, Endpoint, Product, FileUpload + +from dojo.authorization.authorization import ( + user_has_configuration_permission_or_403, + user_has_permission, + user_has_permission_or_403, +) +from dojo.authorization.roles_permissions import Permissions from dojo.filters import LogEntryFilter from dojo.forms import ManageFileFormSet -from dojo.utils import get_page_items, Product_Tab -from dojo.authorization.authorization import user_has_permission, user_has_permission_or_403, user_has_configuration_permission_or_403 -from dojo.authorization.roles_permissions import Permissions - +from dojo.models import Endpoint, Engagement, FileUpload, Finding, Product, Test +from dojo.utils import Product_Tab, get_page_items logger = logging.getLogger(__name__) diff --git a/dojo/widgets.py b/dojo/widgets.py index 1cbaf939af..0d0b245e41 100644 --- a/dojo/widgets.py +++ b/dojo/widgets.py @@ -1,6 +1,6 @@ +from django import forms from django.core.paginator import Paginator from django.template.loader import render_to_string -from django import forms # agrega los imports necesarios diff --git a/dojo/wsgi.py b/dojo/wsgi.py index 83f57ec172..8f6a14863f 100644 --- a/dojo/wsgi.py +++ b/dojo/wsgi.py @@ -13,11 +13,11 @@ framework. """ +import logging import os import socket -import logging -from django.core.wsgi import get_wsgi_application +from django.core.wsgi import get_wsgi_application logger = logging.getLogger(__name__) diff --git a/manage.py b/manage.py index 89b3e2169b..61bc69ff52 100755 --- a/manage.py +++ b/manage.py @@ -2,7 +2,6 @@ import os import sys - if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dojo.settings.settings") diff --git a/ruff.toml b/ruff.toml index 484b0b505b..31963485ed 100644 --- a/ruff.toml +++ b/ruff.toml @@ -35,6 +35,7 @@ select = [ "F", "E", "W", + "I", "UP", "YTT", "ASYNC", diff --git a/tests/Import_scanner_test.py b/tests/Import_scanner_test.py index fd5ee3af0b..2a9f170119 100644 --- a/tests/Import_scanner_test.py +++ b/tests/Import_scanner_test.py @@ -1,13 +1,14 @@ -from selenium.webdriver.support.ui import Select -import unittest +import os import re +import shutil import sys -import os +import unittest + import git -import shutil from base_test_class import BaseTestCase from product_test import ProductTest from selenium.webdriver.common.by import By +from selenium.webdriver.support.ui import Select class ScannerTest(BaseTestCase): diff --git a/tests/announcement_banner_test.py b/tests/announcement_banner_test.py index d2b6bd6c53..5206be7ffd 100644 --- a/tests/announcement_banner_test.py +++ b/tests/announcement_banner_test.py @@ -1,11 +1,11 @@ -import unittest import sys - +import unittest from operator import xor + from base_test_class import BaseTestCase -from user_test import UserTest from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import Select +from user_test import UserTest class AnnouncementBannerTest(BaseTestCase): diff --git a/tests/base_test_class.py b/tests/base_test_class.py index a418a5b464..8f27bed85b 100644 --- a/tests/base_test_class.py +++ b/tests/base_test_class.py @@ -1,12 +1,13 @@ +import os +import re +import unittest + from selenium import webdriver +from selenium.common.exceptions import NoAlertPresentException, NoSuchElementException from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait -from selenium.common.exceptions import NoAlertPresentException, NoSuchElementException -import unittest -import os -import re # import time diff --git a/tests/check_various_pages.py b/tests/check_various_pages.py index 0e2275d61a..35d9079e93 100644 --- a/tests/check_various_pages.py +++ b/tests/check_various_pages.py @@ -1,7 +1,8 @@ +import sys import unittest + from base_test_class import BaseTestCase from selenium.webdriver.common.by import By -import sys class VariousPagesTest(BaseTestCase): diff --git a/tests/close_old_findings_dedupe_test.py b/tests/close_old_findings_dedupe_test.py index 121c9d1896..26b39f39e1 100644 --- a/tests/close_old_findings_dedupe_test.py +++ b/tests/close_old_findings_dedupe_test.py @@ -4,15 +4,13 @@ import time import unittest +from base_test_class import BaseTestCase, on_exception_html_source_logger, set_suite_settings +from product_test import ProductTest from selenium.common.exceptions import TimeoutException from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import Select, WebDriverWait -from base_test_class import (BaseTestCase, on_exception_html_source_logger, - set_suite_settings) -from product_test import ProductTest - logger = logging.getLogger(__name__) dir_path = os.path.dirname(os.path.realpath(__file__)) diff --git a/tests/close_old_findings_test.py b/tests/close_old_findings_test.py index b8ee84836c..f8ccc7fad7 100644 --- a/tests/close_old_findings_test.py +++ b/tests/close_old_findings_test.py @@ -3,15 +3,13 @@ import sys import unittest +from base_test_class import BaseTestCase, on_exception_html_source_logger, set_suite_settings +from product_test import ProductTest from selenium.common.exceptions import TimeoutException from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import Select, WebDriverWait -from base_test_class import (BaseTestCase, on_exception_html_source_logger, - set_suite_settings) -from product_test import ProductTest - logger = logging.getLogger(__name__) dir_path = os.path.dirname(os.path.realpath(__file__)) diff --git a/tests/dedupe_test.py b/tests/dedupe_test.py index ba45793020..5a58edf064 100644 --- a/tests/dedupe_test.py +++ b/tests/dedupe_test.py @@ -4,15 +4,13 @@ import time import unittest +from base_test_class import BaseTestCase, on_exception_html_source_logger, set_suite_settings +from product_test import ProductTest from selenium.common.exceptions import TimeoutException from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import Select, WebDriverWait -from base_test_class import (BaseTestCase, on_exception_html_source_logger, - set_suite_settings) -from product_test import ProductTest - logger = logging.getLogger(__name__) dir_path = os.path.dirname(os.path.realpath(__file__)) diff --git a/tests/endpoint_test.py b/tests/endpoint_test.py index d5e265bf3e..7306e309ea 100644 --- a/tests/endpoint_test.py +++ b/tests/endpoint_test.py @@ -1,9 +1,10 @@ -from selenium.webdriver.common.by import By -from selenium.webdriver.support.ui import Select -import unittest import sys +import unittest + from base_test_class import BaseTestCase from product_test import ProductTest +from selenium.webdriver.common.by import By +from selenium.webdriver.support.ui import Select class EndpointTest(BaseTestCase): diff --git a/tests/engagement_test.py b/tests/engagement_test.py index 1d89a287e3..6dde9962be 100644 --- a/tests/engagement_test.py +++ b/tests/engagement_test.py @@ -1,9 +1,10 @@ -from selenium.webdriver.common.by import By -from selenium.webdriver.support.ui import Select -import unittest import sys +import unittest + from base_test_class import BaseTestCase from product_test import ProductTest +from selenium.webdriver.common.by import By +from selenium.webdriver.support.ui import Select class EngagementTest(BaseTestCase): diff --git a/tests/environment_test.py b/tests/environment_test.py index ab8bec1367..7b496ccc41 100644 --- a/tests/environment_test.py +++ b/tests/environment_test.py @@ -1,6 +1,7 @@ -import unittest -import sys import os +import sys +import unittest + from base_test_class import BaseTestCase from selenium.webdriver.common.by import By diff --git a/tests/false_positive_history_test.py b/tests/false_positive_history_test.py index 5e37022b73..5d4c4c91f4 100644 --- a/tests/false_positive_history_test.py +++ b/tests/false_positive_history_test.py @@ -1,10 +1,11 @@ -import unittest import sys -from selenium.webdriver.support.ui import Select -from selenium.webdriver.common.by import By -from selenium.webdriver.common.keys import Keys +import unittest + from base_test_class import BaseTestCase from product_test import ProductTest, WaitForPageLoad +from selenium.webdriver.common.by import By +from selenium.webdriver.common.keys import Keys +from selenium.webdriver.support.ui import Select class FalsePositiveHistoryTest(BaseTestCase): diff --git a/tests/file_test.py b/tests/file_test.py index a97dbdc390..dce9d43894 100644 --- a/tests/file_test.py +++ b/tests/file_test.py @@ -1,7 +1,8 @@ -import unittest -import sys import os +import sys import time +import unittest + from base_test_class import BaseTestCase from product_test import ProductTest, WaitForPageLoad from selenium.webdriver.common.by import By diff --git a/tests/finding_test.py b/tests/finding_test.py index d9e305b8b3..7643e013ff 100644 --- a/tests/finding_test.py +++ b/tests/finding_test.py @@ -1,16 +1,16 @@ -from selenium.webdriver.support import expected_conditions as EC -from selenium.webdriver.support.ui import Select, WebDriverWait -from selenium.webdriver.common.by import By -from selenium.common.exceptions import TimeoutException - -import unittest -import sys import os +import sys +import time +import unittest +from pathlib import Path + from base_test_class import BaseTestCase, on_exception_html_source_logger, set_suite_settings from product_test import ProductTest, WaitForPageLoad +from selenium.common.exceptions import TimeoutException +from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.ui import Select, WebDriverWait from user_test import UserTest -from pathlib import Path -import time dir_path = os.path.dirname(os.path.realpath(__file__)) diff --git a/tests/group_test.py b/tests/group_test.py index e380e26dad..5694293fbf 100644 --- a/tests/group_test.py +++ b/tests/group_test.py @@ -1,10 +1,11 @@ -import unittest import sys +import unittest + +from base_test_class import BaseTestCase +from selenium.common.exceptions import NoSuchElementException, TimeoutException +from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import Select, WebDriverWait -from selenium.webdriver.common.by import By -from selenium.common.exceptions import TimeoutException, NoSuchElementException -from base_test_class import BaseTestCase from user_test import UserTest diff --git a/tests/ibm_appscan_test.py b/tests/ibm_appscan_test.py index 4d3d945d90..cfb500d112 100644 --- a/tests/ibm_appscan_test.py +++ b/tests/ibm_appscan_test.py @@ -1,11 +1,11 @@ -from selenium.webdriver.support.ui import Select -import unittest -import sys import os +import sys +import unittest + from base_test_class import BaseTestCase from product_test import ProductTest from selenium.webdriver.common.by import By - +from selenium.webdriver.support.ui import Select dir_path = os.path.dirname(os.path.realpath(__file__)) diff --git a/tests/note_type_test.py b/tests/note_type_test.py index 8e79f62b83..c1801e17b4 100644 --- a/tests/note_type_test.py +++ b/tests/note_type_test.py @@ -1,5 +1,6 @@ -import unittest import sys +import unittest + from base_test_class import BaseTestCase from selenium.webdriver.common.by import By diff --git a/tests/notes_test.py b/tests/notes_test.py index 5bff7de0d7..ff2619d6ef 100644 --- a/tests/notes_test.py +++ b/tests/notes_test.py @@ -1,6 +1,7 @@ -import unittest import sys import time +import unittest + from base_test_class import BaseTestCase from product_test import ProductTest from selenium.webdriver.common.by import By diff --git a/tests/notifications_test.py b/tests/notifications_test.py index 24069547f3..d6f0b46382 100644 --- a/tests/notifications_test.py +++ b/tests/notifications_test.py @@ -1,12 +1,12 @@ -import unittest import sys +import unittest from base_test_class import BaseTestCase +from selenium.common.exceptions import NoSuchElementException +from selenium.webdriver import ActionChains from selenium.webdriver.common.by import By -from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC -from selenium.webdriver import ActionChains -from selenium.common.exceptions import NoSuchElementException +from selenium.webdriver.support.ui import WebDriverWait class NotificationTest(BaseTestCase): diff --git a/tests/product_group_test.py b/tests/product_group_test.py index ebf22e4e33..f7f4559c8c 100644 --- a/tests/product_group_test.py +++ b/tests/product_group_test.py @@ -1,12 +1,13 @@ -import unittest import sys +import unittest + from base_test_class import BaseTestCase -from selenium.webdriver.support import expected_conditions as EC -from selenium.webdriver.support.ui import Select, WebDriverWait -from selenium.webdriver.common.by import By -from selenium.common.exceptions import TimeoutException from group_test import GroupTest from product_test import ProductTest +from selenium.common.exceptions import TimeoutException +from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.ui import Select, WebDriverWait class ProductGroupTest(BaseTestCase): diff --git a/tests/product_member_test.py b/tests/product_member_test.py index 23fd700eed..8e45a4a9cc 100644 --- a/tests/product_member_test.py +++ b/tests/product_member_test.py @@ -1,12 +1,13 @@ -import unittest import sys +import unittest + from base_test_class import BaseTestCase +from product_test import ProductTest +from selenium.common.exceptions import TimeoutException +from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import Select, WebDriverWait -from selenium.webdriver.common.by import By -from selenium.common.exceptions import TimeoutException from user_test import UserTest -from product_test import ProductTest class ProductMemberTest(BaseTestCase): diff --git a/tests/product_test.py b/tests/product_test.py index 1c858c5231..79ac3ac3c7 100644 --- a/tests/product_test.py +++ b/tests/product_test.py @@ -1,11 +1,12 @@ -from selenium.webdriver.common.by import By -from selenium.webdriver.support.ui import Select -from selenium.webdriver.common.keys import Keys -import unittest import sys import time +import unittest + from base_test_class import BaseTestCase, on_exception_html_source_logger, set_suite_settings from notifications_test import NotificationTest +from selenium.webdriver.common.by import By +from selenium.webdriver.common.keys import Keys +from selenium.webdriver.support.ui import Select class WaitForPageLoad: diff --git a/tests/product_type_group_test.py b/tests/product_type_group_test.py index 2fb3781419..3e8a05cb27 100644 --- a/tests/product_type_group_test.py +++ b/tests/product_type_group_test.py @@ -1,11 +1,12 @@ -import unittest import sys +import unittest + from base_test_class import BaseTestCase +from group_test import GroupTest +from selenium.common.exceptions import TimeoutException +from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import Select, WebDriverWait -from selenium.webdriver.common.by import By -from selenium.common.exceptions import TimeoutException -from group_test import GroupTest class ProductTypeGroupTest(BaseTestCase): diff --git a/tests/product_type_member_test.py b/tests/product_type_member_test.py index f09f4c12d9..03664664d4 100644 --- a/tests/product_type_member_test.py +++ b/tests/product_type_member_test.py @@ -1,10 +1,11 @@ -import unittest import sys +import unittest + from base_test_class import BaseTestCase +from selenium.common.exceptions import TimeoutException +from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import Select, WebDriverWait -from selenium.webdriver.common.by import By -from selenium.common.exceptions import TimeoutException from user_test import UserTest diff --git a/tests/product_type_test.py b/tests/product_type_test.py index 8f87229a14..f8854899a2 100644 --- a/tests/product_type_test.py +++ b/tests/product_type_test.py @@ -1,5 +1,6 @@ -import unittest import sys +import unittest + from base_test_class import BaseTestCase, on_exception_html_source_logger from selenium.webdriver.common.by import By diff --git a/tests/regulations_test.py b/tests/regulations_test.py index 2f055efb0e..912272bbae 100644 --- a/tests/regulations_test.py +++ b/tests/regulations_test.py @@ -1,6 +1,7 @@ -import unittest -import sys import os +import sys +import unittest + from base_test_class import BaseTestCase from selenium.webdriver.common.by import By diff --git a/tests/report_builder_test.py b/tests/report_builder_test.py index c7eca1dc3b..6025d1c0a4 100644 --- a/tests/report_builder_test.py +++ b/tests/report_builder_test.py @@ -1,13 +1,13 @@ -from selenium.webdriver.support.ui import Select -from selenium.webdriver.common.action_chains import ActionChains -from selenium.webdriver.common.by import By -from selenium.webdriver.support.ui import WebDriverWait -from selenium.webdriver.support import expected_conditions as EC -import unittest -import sys import os +import sys +import unittest + from base_test_class import BaseTestCase from product_test import ProductTest +from selenium.webdriver.common.action_chains import ActionChains +from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.ui import Select, WebDriverWait dir_path = os.path.dirname(os.path.realpath(__file__)) diff --git a/tests/search_test.py b/tests/search_test.py index c48a2fa71a..3da6465380 100644 --- a/tests/search_test.py +++ b/tests/search_test.py @@ -1,5 +1,6 @@ -import unittest import sys +import unittest + from base_test_class import BaseTestCase from selenium.webdriver.common.by import By diff --git a/tests/sla_configuration_test.py b/tests/sla_configuration_test.py index 6203f6cfb2..a388cd436d 100644 --- a/tests/sla_configuration_test.py +++ b/tests/sla_configuration_test.py @@ -2,9 +2,8 @@ import sys import unittest -from selenium.webdriver.common.by import By - from base_test_class import BaseTestCase +from selenium.webdriver.common.by import By class SLAConfigurationTest(BaseTestCase): diff --git a/tests/test_test.py b/tests/test_test.py index 38306bf8a7..a78e99889a 100644 --- a/tests/test_test.py +++ b/tests/test_test.py @@ -1,10 +1,11 @@ -from selenium.webdriver.support.ui import Select -from selenium.webdriver.common.keys import Keys -import unittest import sys +import unittest + from base_test_class import BaseTestCase, on_exception_html_source_logger from product_test import ProductTest, WaitForPageLoad from selenium.webdriver.common.by import By +from selenium.webdriver.common.keys import Keys +from selenium.webdriver.support.ui import Select class TestUnitTest(BaseTestCase): diff --git a/tests/tool_config.py b/tests/tool_config.py index 6305ded880..13db275955 100644 --- a/tests/tool_config.py +++ b/tests/tool_config.py @@ -1,9 +1,10 @@ -from selenium.webdriver.common.by import By -from selenium.webdriver.support.ui import Select -import unittest import sys +import unittest + from base_test_class import BaseTestCase, on_exception_html_source_logger from product_test import ProductTest +from selenium.webdriver.common.by import By +from selenium.webdriver.support.ui import Select class ToolConfigTest(BaseTestCase): diff --git a/tests/user_test.py b/tests/user_test.py index d5a933dd50..14fa6b37d7 100644 --- a/tests/user_test.py +++ b/tests/user_test.py @@ -1,10 +1,10 @@ -import unittest import sys +import unittest from base_test_class import BaseTestCase +from selenium.common.exceptions import NoSuchElementException from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import Select -from selenium.common.exceptions import NoSuchElementException class UserTest(BaseTestCase): diff --git a/tests/zap.py b/tests/zap.py index a62aa54691..3516779342 100755 --- a/tests/zap.py +++ b/tests/zap.py @@ -1,11 +1,12 @@ #!/usr/bin/python3 -import time import collections +import re import socket -from zapv2 import ZAPv2 +import time from urllib.parse import urlparse + from prettytable import PrettyTable -import re +from zapv2 import ZAPv2 class Main: diff --git a/unittests/authorization/test_authorization.py b/unittests/authorization/test_authorization.py index cacd3009b5..0240171152 100644 --- a/unittests/authorization/test_authorization.py +++ b/unittests/authorization/test_authorization.py @@ -1,15 +1,42 @@ +from unittest.mock import patch + from django.contrib.auth.models import User from django.core.exceptions import PermissionDenied -from ..dojo_test_case import DojoTestCase -from unittest.mock import patch -from dojo.models import Dojo_User, Product_Type, Product_Type_Member, Product, Product_Member, Engagement, \ - Test, Finding, Endpoint, Dojo_Group, Product_Group, Product_Type_Group, Role, Global_Role, Dojo_Group_Member, \ - Languages, App_Analysis, Stub_Finding + import dojo.authorization.authorization -from dojo.authorization.authorization import role_has_permission, get_roles_for_permission, user_has_global_permission, \ - user_has_permission_or_403, user_has_permission, user_has_configuration_permission, \ - RoleDoesNotExistError, PermissionDoesNotExistError +from dojo.authorization.authorization import ( + PermissionDoesNotExistError, + RoleDoesNotExistError, + get_roles_for_permission, + role_has_permission, + user_has_configuration_permission, + user_has_global_permission, + user_has_permission, + user_has_permission_or_403, +) from dojo.authorization.roles_permissions import Permissions, Roles +from dojo.models import ( + App_Analysis, + Dojo_Group, + Dojo_Group_Member, + Dojo_User, + Endpoint, + Engagement, + Finding, + Global_Role, + Languages, + Product, + Product_Group, + Product_Member, + Product_Type, + Product_Type_Group, + Product_Type_Member, + Role, + Stub_Finding, + Test, +) + +from ..dojo_test_case import DojoTestCase class TestAuthorization(DojoTestCase): diff --git a/unittests/authorization/test_authorization_decorators.py b/unittests/authorization/test_authorization_decorators.py index d1bbc1962d..ea5d76eee8 100644 --- a/unittests/authorization/test_authorization_decorators.py +++ b/unittests/authorization/test_authorization_decorators.py @@ -1,12 +1,15 @@ +from unittest.mock import Mock, patch + from django.contrib.auth.models import User from django.core.exceptions import PermissionDenied from django.http import Http404 -from ..dojo_test_case import DojoTestCase -from unittest.mock import patch, Mock -from dojo.models import Product_Type from django.test import RequestFactory + from dojo.authorization.authorization_decorators import user_is_authorized, user_is_configuration_authorized from dojo.authorization.roles_permissions import Permissions +from dojo.models import Product_Type + +from ..dojo_test_case import DojoTestCase class TestAuthorizationDecorators(DojoTestCase): diff --git a/unittests/authorization/test_authorization_tags.py b/unittests/authorization/test_authorization_tags.py index 0ee3a31f3c..6a31ca5666 100644 --- a/unittests/authorization/test_authorization_tags.py +++ b/unittests/authorization/test_authorization_tags.py @@ -1,10 +1,17 @@ -from ..dojo_test_case import DojoTestCase from unittest.mock import patch -from django.contrib.auth.models import Permission, Group -from dojo.models import Product_Type, Dojo_User + +from django.contrib.auth.models import Group, Permission + from dojo.authorization.roles_permissions import Permissions -from dojo.templatetags.authorization_tags import has_object_permission, has_configuration_permission, \ - user_has_configuration_permission_without_group, group_has_configuration_permission +from dojo.models import Dojo_User, Product_Type +from dojo.templatetags.authorization_tags import ( + group_has_configuration_permission, + has_configuration_permission, + has_object_permission, + user_has_configuration_permission_without_group, +) + +from ..dojo_test_case import DojoTestCase class TestAuthorizationTags(DojoTestCase): diff --git a/unittests/dojo_test_case.py b/unittests/dojo_test_case.py index 62f2d9a7a6..32aaa4dec5 100644 --- a/unittests/dojo_test_case.py +++ b/unittests/dojo_test_case.py @@ -15,10 +15,24 @@ from dojo.jira_link import helper as jira_helper from dojo.jira_link.views import get_custom_field -from dojo.models import (SEVERITIES, DojoMeta, Endpoint, Endpoint_Status, - Engagement, Finding, JIRA_Issue, JIRA_Project, Notes, - Product, Product_Type, System_Settings, Test, - SLA_Configuration, Test_Type, User) +from dojo.models import ( + SEVERITIES, + DojoMeta, + Endpoint, + Endpoint_Status, + Engagement, + Finding, + JIRA_Issue, + JIRA_Project, + Notes, + Product, + Product_Type, + SLA_Configuration, + System_Settings, + Test, + Test_Type, + User, +) logger = logging.getLogger(__name__) diff --git a/unittests/test_adminsite.py b/unittests/test_adminsite.py index eb639f279e..3f8bc8ce69 100644 --- a/unittests/test_adminsite.py +++ b/unittests/test_adminsite.py @@ -1,6 +1,7 @@ -from .dojo_test_case import DojoTestCase -from django.contrib import admin import django.apps +from django.contrib import admin + +from .dojo_test_case import DojoTestCase class AdminSite(DojoTestCase): diff --git a/unittests/test_api_sonarqube_updater.py b/unittests/test_api_sonarqube_updater.py index 097d23e745..56d341093f 100644 --- a/unittests/test_api_sonarqube_updater.py +++ b/unittests/test_api_sonarqube_updater.py @@ -1,7 +1,8 @@ -from .dojo_test_case import DojoTestCase from dojo.models import Tool_Configuration, Tool_Type from dojo.tools.api_sonarqube.updater import SonarQubeApiUpdater +from .dojo_test_case import DojoTestCase + class TestSonarQubeApiUpdater(DojoTestCase): diff --git a/unittests/test_apiv2_endpoint.py b/unittests/test_apiv2_endpoint.py index 14efbad53a..26342298d4 100644 --- a/unittests/test_apiv2_endpoint.py +++ b/unittests/test_apiv2_endpoint.py @@ -1,6 +1,6 @@ -from rest_framework.test import APITestCase, APIClient from django.urls import reverse from rest_framework.authtoken.models import Token +from rest_framework.test import APIClient, APITestCase class EndpointTest(APITestCase): diff --git a/unittests/test_apiv2_limit_reqresp.py b/unittests/test_apiv2_limit_reqresp.py index 0701b39b14..06e5ad2f4c 100644 --- a/unittests/test_apiv2_limit_reqresp.py +++ b/unittests/test_apiv2_limit_reqresp.py @@ -1,7 +1,7 @@ -from rest_framework.test import APITestCase, APIClient +from django.conf import settings from django.urls import reverse from rest_framework.authtoken.models import Token -from django.conf import settings +from rest_framework.test import APIClient, APITestCase class APILimitReqRespPairsTest(APITestCase): diff --git a/unittests/test_apiv2_metadata.py b/unittests/test_apiv2_metadata.py index ae24b07adc..177b3f0852 100644 --- a/unittests/test_apiv2_metadata.py +++ b/unittests/test_apiv2_metadata.py @@ -1,6 +1,6 @@ -from rest_framework.test import APITestCase, APIClient from django.urls import reverse from rest_framework.authtoken.models import Token +from rest_framework.test import APIClient, APITestCase class MetadataTest(APITestCase): diff --git a/unittests/test_apiv2_methods_and_endpoints.py b/unittests/test_apiv2_methods_and_endpoints.py index 408dd7cc06..a3508f9880 100644 --- a/unittests/test_apiv2_methods_and_endpoints.py +++ b/unittests/test_apiv2_methods_and_endpoints.py @@ -1,34 +1,36 @@ -from dojo.urls import v2_api -from .dojo_test_case import DojoTestCase -from .test_rest_framework import get_open_api3_json_schema, BASE_API_URL import django.apps + from dojo.api_v2 import serializers from dojo.models import ( - Contact, - Product_Line, - Report_Type, CWE, + BannerConf, + Benchmark_Category, + Benchmark_Product, + Benchmark_Product_Summary, + Benchmark_Requirement, + Benchmark_Type, BurpRawRequestResponse, + Choice, + Contact, FileAccessToken, - UserAnnouncement, - BannerConf, - GITHUB_Conf, - GITHUB_Issue, GITHUB_Clone, + GITHUB_Conf, GITHUB_Details_Cache, + GITHUB_Issue, GITHUB_PKey, - Tool_Product_History, - Objects_Review, Objects_Product, - Testing_Guide_Category, + Objects_Review, + Product_Line, + Report_Type, Testing_Guide, - Benchmark_Type, - Benchmark_Category, - Benchmark_Requirement, - Benchmark_Product, - Benchmark_Product_Summary, - Choice, + Testing_Guide_Category, + Tool_Product_History, + UserAnnouncement, ) +from dojo.urls import v2_api + +from .dojo_test_case import DojoTestCase +from .test_rest_framework import BASE_API_URL, get_open_api3_json_schema class ApiEndpointMethods(DojoTestCase): diff --git a/unittests/test_apiv2_notifications.py b/unittests/test_apiv2_notifications.py index a847df2dc0..06aa7413c6 100644 --- a/unittests/test_apiv2_notifications.py +++ b/unittests/test_apiv2_notifications.py @@ -1,6 +1,6 @@ -from rest_framework.test import APITestCase, APIClient from django.urls import reverse from rest_framework.authtoken.models import Token +from rest_framework.test import APIClient, APITestCase class NotificationsTest(APITestCase): diff --git a/unittests/test_apiv2_scan_import_options.py b/unittests/test_apiv2_scan_import_options.py index 5a16a7887e..78200e48fd 100644 --- a/unittests/test_apiv2_scan_import_options.py +++ b/unittests/test_apiv2_scan_import_options.py @@ -1,8 +1,9 @@ -from rest_framework.test import APITestCase, APIClient +from django.core.files.uploadedfile import SimpleUploadedFile from django.urls import reverse -from dojo.models import Finding, Test, Test_Type from rest_framework.authtoken.models import Token -from django.core.files.uploadedfile import SimpleUploadedFile +from rest_framework.test import APIClient, APITestCase + +from dojo.models import Finding, Test, Test_Type class ScanImportOptionsTest(APITestCase): diff --git a/unittests/test_apiv2_user.py b/unittests/test_apiv2_user.py index 54f7e391c1..8bdac8b813 100644 --- a/unittests/test_apiv2_user.py +++ b/unittests/test_apiv2_user.py @@ -1,6 +1,6 @@ -from rest_framework.test import APITestCase, APIClient from django.urls import reverse from rest_framework.authtoken.models import Token +from rest_framework.test import APIClient, APITestCase class UserTest(APITestCase): diff --git a/unittests/test_apply_finding_template.py b/unittests/test_apply_finding_template.py index 763200b55b..3042098b41 100644 --- a/unittests/test_apply_finding_template.py +++ b/unittests/test_apply_finding_template.py @@ -1,19 +1,16 @@ import datetime -from django.http import Http404 -from dojo.models import Product, Product_Type -from dojo.models import Engagement -from dojo.models import Test_Type -from dojo.models import Test -from dojo.models import Finding -from dojo.models import Finding_Template -from dojo.models import System_Settings -from dojo.finding import views -from .dojo_test_case import DojoTestCase -from django.test.client import RequestFactory +from unittest import skip + from django.contrib.auth.models import User from django.contrib.messages.storage.fallback import FallbackStorage +from django.http import Http404 +from django.test.client import RequestFactory from django.utils import timezone -from unittest import skip + +from dojo.finding import views +from dojo.models import Engagement, Finding, Finding_Template, Product, Product_Type, System_Settings, Test, Test_Type + +from .dojo_test_case import DojoTestCase class FindingMother: diff --git a/unittests/test_bulk_risk_acceptance_api.py b/unittests/test_bulk_risk_acceptance_api.py index 96309fcb4b..ba0bf56a57 100644 --- a/unittests/test_bulk_risk_acceptance_api.py +++ b/unittests/test_bulk_risk_acceptance_api.py @@ -2,10 +2,21 @@ from rest_framework.authtoken.models import Token from rest_framework.reverse import reverse -from rest_framework.test import APITestCase, APIClient +from rest_framework.test import APIClient, APITestCase -from dojo.models import Product_Type, Product, Engagement, Product_Type_Member, Test, Finding, User, Test_Type, Role, Vulnerability_Id from dojo.authorization.roles_permissions import Roles +from dojo.models import ( + Engagement, + Finding, + Product, + Product_Type, + Product_Type_Member, + Role, + Test, + Test_Type, + User, + Vulnerability_Id, +) class TestBulkRiskAcceptanceApi(APITestCase): diff --git a/unittests/test_cleanup_alerts.py b/unittests/test_cleanup_alerts.py index c35bd65b21..d2f4af56d3 100644 --- a/unittests/test_cleanup_alerts.py +++ b/unittests/test_cleanup_alerts.py @@ -1,8 +1,12 @@ +import logging + +from django.conf import settings + +from dojo.models import Alerts, User from dojo.tasks import cleanup_alerts + from .dojo_test_case import DojoTestCase -from django.conf import settings -from dojo.models import User, Alerts -import logging + logger = logging.getLogger(__name__) diff --git a/unittests/test_copy_model.py b/unittests/test_copy_model.py index c3952a239e..04f39a293b 100644 --- a/unittests/test_copy_model.py +++ b/unittests/test_copy_model.py @@ -1,5 +1,6 @@ +from dojo.models import Endpoint, Endpoint_Status, Engagement, Finding, Product, Test, User + from .dojo_test_case import DojoTestCase -from dojo.models import Endpoint, Endpoint_Status, Finding, Test, Engagement, Product, User class TestCopyFindingModel(DojoTestCase): diff --git a/unittests/test_dashboard.py b/unittests/test_dashboard.py index e1ade37c0e..8d853c46a9 100644 --- a/unittests/test_dashboard.py +++ b/unittests/test_dashboard.py @@ -4,11 +4,12 @@ from dateutil.relativedelta import relativedelta from django.contrib.auth import get_user_model -from .dojo_test_case import DojoTestCase from django.urls import reverse from django.utils import timezone -from dojo.models import Finding, Test, Engagement, Risk_Acceptance, System_Settings +from dojo.models import Engagement, Finding, Risk_Acceptance, System_Settings, Test + +from .dojo_test_case import DojoTestCase User = get_user_model() diff --git a/unittests/test_deduplication_logic.py b/unittests/test_deduplication_logic.py index 5b7ae6bdd3..6369d26d3a 100644 --- a/unittests/test_deduplication_logic.py +++ b/unittests/test_deduplication_logic.py @@ -1,10 +1,13 @@ -from .dojo_test_case import DojoTestCase -from dojo.models import Finding, User, Product, Endpoint, Endpoint_Status, Test, Engagement -from dojo.models import System_Settings -from django.conf import settings -from crum import impersonate -import unittest import logging +import unittest + +from crum import impersonate +from django.conf import settings + +from dojo.models import Endpoint, Endpoint_Status, Engagement, Finding, Product, System_Settings, Test, User + +from .dojo_test_case import DojoTestCase + logger = logging.getLogger(__name__) deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") diff --git a/unittests/test_duplication_loops.py b/unittests/test_duplication_loops.py index 1ce4553336..e7a4d843bc 100644 --- a/unittests/test_duplication_loops.py +++ b/unittests/test_duplication_loops.py @@ -1,11 +1,13 @@ +import logging + from crum import impersonate from django.test.utils import override_settings -from .dojo_test_case import DojoTestCase -from dojo.utils import set_duplicate + from dojo.management.commands.fix_loop_duplicates import fix_loop_duplicates from dojo.models import Engagement, Finding, Product, User -import logging +from dojo.utils import set_duplicate +from .dojo_test_case import DojoTestCase logger = logging.getLogger(__name__) diff --git a/unittests/test_endpoint_meta_import.py b/unittests/test_endpoint_meta_import.py index 118ceefa80..a639999f16 100644 --- a/unittests/test_endpoint_meta_import.py +++ b/unittests/test_endpoint_meta_import.py @@ -1,12 +1,14 @@ +import logging + +from django.test.client import Client from django.urls import reverse -from dojo.models import User from rest_framework.authtoken.models import Token from rest_framework.test import APIClient -from django.test.client import Client + +from dojo.models import User + from .dojo_test_case import DojoAPITestCase, get_unit_tests_path from .test_utils import assertImportModelsCreated -import logging - logger = logging.getLogger(__name__) diff --git a/unittests/test_endpoint_model.py b/unittests/test_endpoint_model.py index 634130bb3a..72b0e1843e 100644 --- a/unittests/test_endpoint_model.py +++ b/unittests/test_endpoint_model.py @@ -1,13 +1,14 @@ import datetime -from .dojo_test_case import DojoTestCase from unittest import skip -from dojo.endpoint.utils import endpoint_get_or_create -from dojo.models import Product_Type, Product, Engagement, Test, Finding, Endpoint, Endpoint_Status -from django.core.exceptions import ValidationError from django.apps import apps +from django.core.exceptions import ValidationError from django.utils import timezone -from dojo.endpoint.utils import remove_broken_endpoint_statuses + +from dojo.endpoint.utils import endpoint_get_or_create, remove_broken_endpoint_statuses +from dojo.models import Endpoint, Endpoint_Status, Engagement, Finding, Product, Product_Type, Test + +from .dojo_test_case import DojoTestCase class TestEndpointModel(DojoTestCase): diff --git a/unittests/test_factory.py b/unittests/test_factory.py index f820d3d73d..0b77643ad8 100644 --- a/unittests/test_factory.py +++ b/unittests/test_factory.py @@ -1,5 +1,6 @@ -from dojo.tools.factory import get_parser from dojo.models import Test, Test_Type +from dojo.tools.factory import get_parser + from .dojo_test_case import DojoTestCase, get_unit_tests_path diff --git a/unittests/test_false_positive_history_logic.py b/unittests/test_false_positive_history_logic.py index 808af00f74..29cb18f947 100644 --- a/unittests/test_false_positive_history_logic.py +++ b/unittests/test_false_positive_history_logic.py @@ -1,9 +1,12 @@ -from .dojo_test_case import DojoTestCase -from dojo.models import Finding, User, Product, Endpoint, Endpoint_Status, Test, Engagement -from dojo.models import System_Settings -from crum import impersonate import logging from datetime import datetime + +from crum import impersonate + +from dojo.models import Endpoint, Endpoint_Status, Engagement, Finding, Product, System_Settings, Test, User + +from .dojo_test_case import DojoTestCase + logger = logging.getLogger(__name__) deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") diff --git a/unittests/test_finding_helper.py b/unittests/test_finding_helper.py index d3e6bf7129..a3491a423c 100644 --- a/unittests/test_finding_helper.py +++ b/unittests/test_finding_helper.py @@ -1,13 +1,16 @@ -from .dojo_test_case import DojoTestCase -from dojo.models import Finding, Test, Vulnerability_Id, Finding_Template, Vulnerability_Id_Template -from django.contrib.auth.models import User +import datetime +import logging from unittest import mock from unittest.mock import patch + from crum import impersonate -import datetime +from django.contrib.auth.models import User from django.utils import timezone -import logging + from dojo.finding.helper import save_vulnerability_ids, save_vulnerability_ids_template +from dojo.models import Finding, Finding_Template, Test, Vulnerability_Id, Vulnerability_Id_Template + +from .dojo_test_case import DojoTestCase logger = logging.getLogger(__name__) diff --git a/unittests/test_finding_model.py b/unittests/test_finding_model.py index e6053dcd91..6531cd3eec 100644 --- a/unittests/test_finding_model.py +++ b/unittests/test_finding_model.py @@ -1,8 +1,11 @@ -from .dojo_test_case import DojoTestCase -from dojo.models import User, Finding, Test, Engagement, DojoMeta from datetime import datetime, timedelta + from crum import impersonate +from dojo.models import DojoMeta, Engagement, Finding, Test, User + +from .dojo_test_case import DojoTestCase + class TestFindingModel(DojoTestCase): diff --git a/unittests/test_flush_auditlog.py b/unittests/test_flush_auditlog.py index 1cbdb4ff62..2116d537c9 100644 --- a/unittests/test_flush_auditlog.py +++ b/unittests/test_flush_auditlog.py @@ -1,11 +1,15 @@ -from dojo.tasks import flush_auditlog -from .dojo_test_case import DojoTestCase -from django.test import override_settings -from auditlog.models import LogEntry +import logging from datetime import date, datetime, timezone -from dojo.models import Finding + +from auditlog.models import LogEntry from dateutil.relativedelta import relativedelta -import logging +from django.test import override_settings + +from dojo.models import Finding +from dojo.tasks import flush_auditlog + +from .dojo_test_case import DojoTestCase + logger = logging.getLogger(__name__) diff --git a/unittests/test_import_reimport.py b/unittests/test_import_reimport.py index a3a9b72d30..342e771c65 100644 --- a/unittests/test_import_reimport.py +++ b/unittests/test_import_reimport.py @@ -1,17 +1,19 @@ import datetime + +# from unittest import skip +import logging + +from django.test import override_settings +from django.test.client import Client from django.urls import reverse -from dojo.models import Test_Type, User, Test, Finding +from django.utils import timezone from rest_framework.authtoken.models import Token from rest_framework.test import APIClient -from django.test.client import Client -from django.utils import timezone + +from dojo.models import Finding, Test, Test_Type, User from .dojo_test_case import DojoAPITestCase, get_unit_tests_path from .test_utils import assertTestImportModelsCreated -from django.test import override_settings -# from unittest import skip -import logging - logger = logging.getLogger(__name__) diff --git a/unittests/test_importers_closeold.py b/unittests/test_importers_closeold.py index 2792ec025c..1b16cde9ba 100644 --- a/unittests/test_importers_closeold.py +++ b/unittests/test_importers_closeold.py @@ -1,9 +1,11 @@ -from .dojo_test_case import DojoTestCase, get_unit_tests_path +import logging + from django.utils import timezone + from dojo.importers.importer.importer import DojoDefaultImporter as Importer from dojo.models import Development_Environment, Engagement, Product, Product_Type, User -import logging +from .dojo_test_case import DojoTestCase, get_unit_tests_path logger = logging.getLogger(__name__) diff --git a/unittests/test_importers_importer.py b/unittests/test_importers_importer.py index c997327a9f..486088c77e 100644 --- a/unittests/test_importers_importer.py +++ b/unittests/test_importers_importer.py @@ -1,21 +1,21 @@ -from unittest.mock import patch +import logging import uuid -from .dojo_test_case import DojoTestCase, get_unit_tests_path +from unittest.mock import patch + from django.utils import timezone from rest_framework.authtoken.models import Token from rest_framework.test import APIClient + from dojo.importers.importer.importer import DojoDefaultImporter as Importer +from dojo.importers.utils import handle_vulnerability_ids from dojo.models import Development_Environment, Engagement, Finding, Product, Product_Type, Test, User from dojo.tools.factory import get_parser -from dojo.tools.sarif.parser import SarifParser from dojo.tools.gitlab_sast.parser import GitlabSastParser -from .dojo_test_case import DojoAPITestCase -from .test_utils import assertImportModelsCreated -import logging -from dojo.importers.utils import handle_vulnerability_ids - +from dojo.tools.sarif.parser import SarifParser from dojo.utils import get_object_or_none +from .dojo_test_case import DojoAPITestCase, DojoTestCase, get_unit_tests_path +from .test_utils import assertImportModelsCreated logger = logging.getLogger(__name__) diff --git a/unittests/test_jira_config_engagement.py b/unittests/test_jira_config_engagement.py index 0fede4ca68..cf952b6068 100644 --- a/unittests/test_jira_config_engagement.py +++ b/unittests/test_jira_config_engagement.py @@ -1,12 +1,16 @@ +# from unittest import skip +import logging +from unittest.mock import patch + from django.urls import reverse -from .dojo_test_case import DojoTestCase -from dojo.models import Engagement, Product + # from dojo.models import JIRA_Project from django.utils.http import urlencode -from unittest.mock import patch + from dojo.jira_link import helper as jira_helper -# from unittest import skip -import logging +from dojo.models import Engagement, Product + +from .dojo_test_case import DojoTestCase logger = logging.getLogger(__name__) diff --git a/unittests/test_jira_config_engagement_epic.py b/unittests/test_jira_config_engagement_epic.py index 51989a3829..ba14b310de 100644 --- a/unittests/test_jira_config_engagement_epic.py +++ b/unittests/test_jira_config_engagement_epic.py @@ -1,9 +1,11 @@ -from .test_jira_config_engagement import JIRAConfigEngagementBase -from vcr import VCR -from .dojo_test_case import DojoVCRTestCase, get_unit_tests_path # from unittest import skip import logging +from vcr import VCR + +from .dojo_test_case import DojoVCRTestCase, get_unit_tests_path +from .test_jira_config_engagement import JIRAConfigEngagementBase + logger = logging.getLogger(__name__) diff --git a/unittests/test_jira_config_product.py b/unittests/test_jira_config_product.py index 545c1ccad3..818127c5bf 100644 --- a/unittests/test_jira_config_product.py +++ b/unittests/test_jira_config_product.py @@ -1,13 +1,16 @@ +# from unittest import skip +import logging +from unittest.mock import call, patch + +import requests from django.urls import reverse -from .dojo_test_case import DojoTestCase -from dojo.models import JIRA_Instance, Product from django.utils.http import urlencode -from unittest.mock import patch, call from jira.exceptions import JIRAError -import requests + import dojo.jira_link.helper as jira_helper -# from unittest import skip -import logging +from dojo.models import JIRA_Instance, Product + +from .dojo_test_case import DojoTestCase logger = logging.getLogger(__name__) diff --git a/unittests/test_jira_import_and_pushing_api.py b/unittests/test_jira_import_and_pushing_api.py index 76593c1967..2f0c1050bd 100644 --- a/unittests/test_jira_import_and_pushing_api.py +++ b/unittests/test_jira_import_and_pushing_api.py @@ -1,13 +1,15 @@ -from dojo.models import Finding_Group, User, Finding, JIRA_Instance -from dojo.jira_link import helper as jira_helper -from rest_framework.authtoken.models import Token -from rest_framework.test import APIClient -from .dojo_test_case import DojoVCRAPITestCase, get_unit_tests_path -from crum import impersonate # from unittest import skip import logging + +from crum import impersonate +from rest_framework.authtoken.models import Token +from rest_framework.test import APIClient from vcr import VCR +from dojo.jira_link import helper as jira_helper +from dojo.models import Finding, Finding_Group, JIRA_Instance, User + +from .dojo_test_case import DojoVCRAPITestCase, get_unit_tests_path logger = logging.getLogger(__name__) diff --git a/unittests/test_jira_template.py b/unittests/test_jira_template.py index ff8d167d3f..a0a2fc562a 100644 --- a/unittests/test_jira_template.py +++ b/unittests/test_jira_template.py @@ -1,9 +1,11 @@ -from .dojo_test_case import DojoTestCase -from dojo.models import Product -from dojo.jira_link import helper as jira_helper # from unittest import skip import logging +from dojo.jira_link import helper as jira_helper +from dojo.models import Product + +from .dojo_test_case import DojoTestCase + logger = logging.getLogger(__name__) diff --git a/unittests/test_jira_webhook.py b/unittests/test_jira_webhook.py index 3d1a9f14e9..a07458d72c 100644 --- a/unittests/test_jira_webhook.py +++ b/unittests/test_jira_webhook.py @@ -1,10 +1,14 @@ -from django.urls import reverse -from .dojo_test_case import DojoTestCase -from dojo.models import JIRA_Issue import json + # from unittest import skip import logging + +from django.urls import reverse + import dojo.jira_link.helper as jira_helper +from dojo.models import JIRA_Issue + +from .dojo_test_case import DojoTestCase logger = logging.getLogger(__name__) diff --git a/unittests/test_metrics_queries.py b/unittests/test_metrics_queries.py index 503714ac56..d65fc49f79 100644 --- a/unittests/test_metrics_queries.py +++ b/unittests/test_metrics_queries.py @@ -4,13 +4,14 @@ from datetime import date, datetime, timezone from unittest.mock import patch -import pytz +import pytz from django.test import RequestFactory from django.urls import reverse from dojo.metrics import views from dojo.models import User + from .dojo_test_case import DojoTestCase diff --git a/unittests/test_migrations.py b/unittests/test_migrations.py index d8bf5f77b8..6800f3346e 100644 --- a/unittests/test_migrations.py +++ b/unittests/test_migrations.py @@ -1,8 +1,8 @@ import datetime from unittest import skip -from django_test_migrations.contrib.unittest_case import MigratorTestCase from django.utils import timezone +from django_test_migrations.contrib.unittest_case import MigratorTestCase @skip("Outdated - this class was testing some version of migration; it is not needed anymore") diff --git a/unittests/test_notifications.py b/unittests/test_notifications.py index 202d289a2c..cad7106cfb 100644 --- a/unittests/test_notifications.py +++ b/unittests/test_notifications.py @@ -1,9 +1,10 @@ -from .dojo_test_case import DojoTestCase -from dojo.models import Product, User, Notifications -from dojo.models import DEFAULT_NOTIFICATION -from dojo.notifications.helper import create_notification, send_alert_notification from unittest.mock import patch +from dojo.models import DEFAULT_NOTIFICATION, Notifications, Product, User +from dojo.notifications.helper import create_notification, send_alert_notification + +from .dojo_test_case import DojoTestCase + class TestNotifications(DojoTestCase): fixtures = ['dojo_testdata.json'] diff --git a/unittests/test_parsers.py b/unittests/test_parsers.py index 57ef61fa1d..43ee4e2419 100644 --- a/unittests/test_parsers.py +++ b/unittests/test_parsers.py @@ -1,7 +1,8 @@ -from .dojo_test_case import DojoTestCase, get_unit_tests_path import os import re +from .dojo_test_case import DojoTestCase, get_unit_tests_path + basedir = os.path.join(get_unit_tests_path(), '..') diff --git a/unittests/test_remote_user.py b/unittests/test_remote_user.py index 5d09cac922..718c4913e3 100644 --- a/unittests/test_remote_user.py +++ b/unittests/test_remote_user.py @@ -1,7 +1,9 @@ from django.test import Client, override_settings from netaddr import IPSet -from dojo.models import User, Dojo_Group, Dojo_Group_Member + +from dojo.models import Dojo_Group, Dojo_Group_Member, User from dojo.remote_user import RemoteUserScheme + from .dojo_test_case import DojoTestCase diff --git a/unittests/test_rest_framework.py b/unittests/test_rest_framework.py index 757e8b35e6..710766428a 100644 --- a/unittests/test_rest_framework.py +++ b/unittests/test_rest_framework.py @@ -1,53 +1,135 @@ +import json +import logging +import pathlib from collections import OrderedDict -from drf_spectacular.drainage import GENERATOR_STATS -# from drf_spectacular.renderers import OpenApiJsonRenderer -from unittest.mock import MagicMock, call, patch, ANY -from dojo.models import Development_Environment, Product, Engagement, Test, Finding, \ - JIRA_Issue, Test_Type, Tool_Product_Settings, Tool_Configuration, Tool_Type, \ - User, Stub_Finding, Endpoint, JIRA_Project, JIRA_Instance, \ - Finding_Template, Note_Type, App_Analysis, Endpoint_Status, \ - Sonarqube_Issue, Sonarqube_Issue_Transition, Product_API_Scan_Configuration, Notes, \ - BurpRawRequestResponse, DojoMeta, FileUpload, Product_Type, Dojo_Group, \ - Role, Product_Type_Member, Product_Member, Product_Type_Group, Risk_Acceptance, \ - Product_Group, Global_Role, Dojo_Group_Member, Language_Type, Languages, \ - Notifications, UserContactInfo, Cred_Mapping, Cred_User, \ - TextQuestion, ChoiceQuestion, TextAnswer, ChoiceAnswer, Engagement_Survey, \ - Answered_Survey, General_Survey, Announcement -from dojo.api_v2.views import DevelopmentEnvironmentViewSet, EndPointViewSet, EngagementViewSet, \ - FindingTemplatesViewSet, FindingViewSet, JiraInstanceViewSet, \ - JiraIssuesViewSet, JiraProjectViewSet, ProductViewSet, \ - StubFindingsViewSet, TestTypesViewSet, TestsViewSet, \ - ToolConfigurationsViewSet, ToolProductSettingsViewSet, ToolTypesViewSet, \ - UsersViewSet, ImportScanView, NoteTypeViewSet, AppAnalysisViewSet, \ - EndpointStatusViewSet, SonarqubeIssueViewSet, NotesViewSet, ProductTypeViewSet, \ - DojoGroupViewSet, RoleViewSet, ProductTypeMemberViewSet, ProductMemberViewSet, \ - ProductTypeGroupViewSet, ProductGroupViewSet, GlobalRoleViewSet, RiskAcceptanceViewSet, \ - DojoGroupMemberViewSet, LanguageTypeViewSet, LanguageViewSet, ImportLanguagesView, \ - NotificationsViewSet, UserContactInfoViewSet, ProductAPIScanConfigurationViewSet, \ - ConfigurationPermissionViewSet, CredentialsMappingViewSet, \ - CredentialsViewSet, QuestionnaireQuestionViewSet, QuestionnaireAnswerViewSet, \ - QuestionnaireGeneralSurveyViewSet, QuestionnaireEngagementSurveyViewSet, QuestionnaireAnsweredSurveyViewSet, \ - AnnouncementViewSet -from json import dumps from enum import Enum -from django.urls import reverse +from json import dumps + +# from drf_spectacular.renderers import OpenApiJsonRenderer +from unittest.mock import ANY, MagicMock, call, patch + from django.contrib.auth.models import Permission +from django.urls import reverse +from drf_spectacular.drainage import GENERATOR_STATS +from drf_spectacular.settings import spectacular_settings from rest_framework import status from rest_framework.authtoken.models import Token +from rest_framework.mixins import ( + CreateModelMixin, + DestroyModelMixin, + ListModelMixin, + RetrieveModelMixin, + UpdateModelMixin, +) from rest_framework.test import APIClient -from .dojo_test_case import DojoAPITestCase -from dojo.api_v2.prefetch.utils import _get_prefetchable_fields -from rest_framework.mixins import \ - ListModelMixin, RetrieveModelMixin, CreateModelMixin, \ - DestroyModelMixin, UpdateModelMixin + from dojo.api_v2.mixins import DeletePreviewModelMixin from dojo.api_v2.prefetch import PrefetchListMixin, PrefetchRetrieveMixin -from drf_spectacular.settings import spectacular_settings -import logging -import pathlib -import json +from dojo.api_v2.prefetch.utils import _get_prefetchable_fields +from dojo.api_v2.views import ( + AnnouncementViewSet, + AppAnalysisViewSet, + ConfigurationPermissionViewSet, + CredentialsMappingViewSet, + CredentialsViewSet, + DevelopmentEnvironmentViewSet, + DojoGroupMemberViewSet, + DojoGroupViewSet, + EndpointStatusViewSet, + EndPointViewSet, + EngagementViewSet, + FindingTemplatesViewSet, + FindingViewSet, + GlobalRoleViewSet, + ImportLanguagesView, + ImportScanView, + JiraInstanceViewSet, + JiraIssuesViewSet, + JiraProjectViewSet, + LanguageTypeViewSet, + LanguageViewSet, + NotesViewSet, + NoteTypeViewSet, + NotificationsViewSet, + ProductAPIScanConfigurationViewSet, + ProductGroupViewSet, + ProductMemberViewSet, + ProductTypeGroupViewSet, + ProductTypeMemberViewSet, + ProductTypeViewSet, + ProductViewSet, + QuestionnaireAnsweredSurveyViewSet, + QuestionnaireAnswerViewSet, + QuestionnaireEngagementSurveyViewSet, + QuestionnaireGeneralSurveyViewSet, + QuestionnaireQuestionViewSet, + RiskAcceptanceViewSet, + RoleViewSet, + SonarqubeIssueViewSet, + StubFindingsViewSet, + TestsViewSet, + TestTypesViewSet, + ToolConfigurationsViewSet, + ToolProductSettingsViewSet, + ToolTypesViewSet, + UserContactInfoViewSet, + UsersViewSet, +) from dojo.authorization.roles_permissions import Permissions +from dojo.models import ( + Announcement, + Answered_Survey, + App_Analysis, + BurpRawRequestResponse, + ChoiceAnswer, + ChoiceQuestion, + Cred_Mapping, + Cred_User, + Development_Environment, + Dojo_Group, + Dojo_Group_Member, + DojoMeta, + Endpoint, + Endpoint_Status, + Engagement, + Engagement_Survey, + FileUpload, + Finding, + Finding_Template, + General_Survey, + Global_Role, + JIRA_Instance, + JIRA_Issue, + JIRA_Project, + Language_Type, + Languages, + Note_Type, + Notes, + Notifications, + Product, + Product_API_Scan_Configuration, + Product_Group, + Product_Member, + Product_Type, + Product_Type_Group, + Product_Type_Member, + Risk_Acceptance, + Role, + Sonarqube_Issue, + Sonarqube_Issue_Transition, + Stub_Finding, + Test, + Test_Type, + TextAnswer, + TextQuestion, + Tool_Configuration, + Tool_Product_Settings, + Tool_Type, + User, + UserContactInfo, +) +from .dojo_test_case import DojoAPITestCase logger = logging.getLogger(__name__) diff --git a/unittests/test_risk_acceptance.py b/unittests/test_risk_acceptance.py index e677ff4286..43a0bd578a 100644 --- a/unittests/test_risk_acceptance.py +++ b/unittests/test_risk_acceptance.py @@ -1,18 +1,22 @@ +import copy +import datetime +import logging + from dateutil.relativedelta import relativedelta -from dojo.utils import get_system_setting -from django.utils import timezone -from django.utils.http import urlencode +from django.db.models import Q from django.urls import reverse -from .dojo_test_case import DojoTestCase -from dojo.models import Risk_Acceptance, Finding, System_Settings +from django.utils import timezone + # from unittest.mock import patch from django.utils.datastructures import MultiValueDict -from django.db.models import Q -import copy +from django.utils.http import urlencode + # from unittest import skip import dojo.risk_acceptance.helper as ra_helper -import logging -import datetime +from dojo.models import Finding, Risk_Acceptance, System_Settings +from dojo.utils import get_system_setting + +from .dojo_test_case import DojoTestCase logger = logging.getLogger(__name__) diff --git a/unittests/test_sample_data.py b/unittests/test_sample_data.py index 7c8abe3f5c..481782bbcf 100644 --- a/unittests/test_sample_data.py +++ b/unittests/test_sample_data.py @@ -1,4 +1,5 @@ from django.core.management import call_command + from .dojo_test_case import DojoTestCase diff --git a/unittests/test_search_parser.py b/unittests/test_search_parser.py index 335e9cb993..06115c7e07 100644 --- a/unittests/test_search_parser.py +++ b/unittests/test_search_parser.py @@ -1,6 +1,7 @@ -from .dojo_test_case import DojoTestCase from dojo.search.views import parse_search_query +from .dojo_test_case import DojoTestCase + class TestSearch(DojoTestCase): def test_parse_query(self): diff --git a/unittests/test_system_settings.py b/unittests/test_system_settings.py index d643831fde..a735ca03f9 100644 --- a/unittests/test_system_settings.py +++ b/unittests/test_system_settings.py @@ -1,6 +1,7 @@ -from .dojo_test_case import DojoTestCase from dojo.models import System_Settings +from .dojo_test_case import DojoTestCase + class TestSystemSettings(DojoTestCase): diff --git a/unittests/test_tags.py b/unittests/test_tags.py index ee1230b6e2..0e471d67ed 100644 --- a/unittests/test_tags.py +++ b/unittests/test_tags.py @@ -1,9 +1,11 @@ -from dojo.models import Test, Finding -from .dojo_test_case import DojoAPITestCase -from dojo.product.helpers import propagate_tags_on_product_sync import logging import random +from dojo.models import Finding, Test +from dojo.product.helpers import propagate_tags_on_product_sync + +from .dojo_test_case import DojoAPITestCase + logger = logging.getLogger(__name__) diff --git a/unittests/test_tool_config.py b/unittests/test_tool_config.py index 8ddacc6726..f807e61cf5 100644 --- a/unittests/test_tool_config.py +++ b/unittests/test_tool_config.py @@ -1,7 +1,8 @@ -from .dojo_test_case import DojoTestCase -from dojo.tools.factory import get_api_scan_configuration_hints, PARSERS -from dojo.tool_config.factory import SCAN_APIS from dojo.models import Tool_Configuration, Tool_Type +from dojo.tool_config.factory import SCAN_APIS +from dojo.tools.factory import PARSERS, get_api_scan_configuration_hints + +from .dojo_test_case import DojoTestCase class TestApiScanConfigEntry(DojoTestCase): diff --git a/unittests/test_user_queries.py b/unittests/test_user_queries.py index 08dfb6468f..3028f04ee8 100644 --- a/unittests/test_user_queries.py +++ b/unittests/test_user_queries.py @@ -1,9 +1,11 @@ from unittest.mock import patch -from .dojo_test_case import DojoTestCase + from dojo.authorization.roles_permissions import Permissions -from dojo.models import Dojo_User, Global_Role, Role, Product_Type, Product, Product_Type_Member, Product_Member +from dojo.models import Dojo_User, Global_Role, Product, Product_Member, Product_Type, Product_Type_Member, Role from dojo.user.queries import get_authorized_users +from .dojo_test_case import DojoTestCase + class TestUserQueries(DojoTestCase): diff --git a/unittests/test_user_validators.py b/unittests/test_user_validators.py index 06bdf953b5..4751cacc87 100644 --- a/unittests/test_user_validators.py +++ b/unittests/test_user_validators.py @@ -1,6 +1,7 @@ from dojo.forms import ChangePasswordForm +from dojo.models import Dojo_User, System_Settings + from .dojo_test_case import DojoTestCase -from dojo.models import System_Settings, Dojo_User class TestUserValidators(DojoTestCase): diff --git a/unittests/test_utils.py b/unittests/test_utils.py index 3cad8f7e00..5f08a3a75f 100644 --- a/unittests/test_utils.py +++ b/unittests/test_utils.py @@ -1,14 +1,30 @@ -from dojo.models import IMPORT_CLOSED_FINDING, IMPORT_CREATED_FINDING, IMPORT_REACTIVATED_FINDING, IMPORT_UNTOUCHED_FINDING, \ - Engagement, Product, Test, Test_Import, Test_Import_Finding_Action, \ - Dojo_User, Dojo_Group, Dojo_Group_Member, Role, System_Settings, Notifications, \ - Product_Type, Endpoint +import logging from contextlib import contextmanager -from .dojo_test_case import DojoTestCase -from unittest.mock import patch, Mock -from dojo.utils import dojo_crypto_encrypt, prepare_for_view, user_post_save +from unittest.mock import Mock, patch + from dojo.authorization.roles_permissions import Roles -import logging +from dojo.models import ( + IMPORT_CLOSED_FINDING, + IMPORT_CREATED_FINDING, + IMPORT_REACTIVATED_FINDING, + IMPORT_UNTOUCHED_FINDING, + Dojo_Group, + Dojo_Group_Member, + Dojo_User, + Endpoint, + Engagement, + Notifications, + Product, + Product_Type, + Role, + System_Settings, + Test, + Test_Import, + Test_Import_Finding_Action, +) +from dojo.utils import dojo_crypto_encrypt, prepare_for_view, user_post_save +from .dojo_test_case import DojoTestCase logger = logging.getLogger(__name__) diff --git a/unittests/test_utils_deduplication_reopen.py b/unittests/test_utils_deduplication_reopen.py index 50ff0832e0..47f7a8c3f4 100644 --- a/unittests/test_utils_deduplication_reopen.py +++ b/unittests/test_utils_deduplication_reopen.py @@ -1,9 +1,12 @@ -from .dojo_test_case import DojoTestCase import datetime -from dojo.utils import set_duplicate +import logging + from dojo.management.commands.fix_loop_duplicates import fix_loop_duplicates from dojo.models import Finding -import logging +from dojo.utils import set_duplicate + +from .dojo_test_case import DojoTestCase + logger = logging.getLogger(__name__) diff --git a/unittests/tools/test_acunetix_parser.py b/unittests/tools/test_acunetix_parser.py index 7238f5693a..bd94c2ac70 100644 --- a/unittests/tools/test_acunetix_parser.py +++ b/unittests/tools/test_acunetix_parser.py @@ -1,8 +1,10 @@ import datetime -from ..dojo_test_case import DojoTestCase +from datetime import datetime as date + from dojo.models import Test from dojo.tools.acunetix.parser import AcunetixParser -from datetime import datetime as date + +from ..dojo_test_case import DojoTestCase class TestAcunetixParser(DojoTestCase): diff --git a/unittests/tools/test_anchore_engine_parser.py b/unittests/tools/test_anchore_engine_parser.py index 9407ac2e8b..29946312a8 100644 --- a/unittests/tools/test_anchore_engine_parser.py +++ b/unittests/tools/test_anchore_engine_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.anchore_engine.parser import AnchoreEngineParser from dojo.models import Test +from dojo.tools.anchore_engine.parser import AnchoreEngineParser + +from ..dojo_test_case import DojoTestCase class TestAnchoreEngineParser(DojoTestCase): diff --git a/unittests/tools/test_anchore_enterprise_parser.py b/unittests/tools/test_anchore_enterprise_parser.py index 81a35caa95..3ea2286a4c 100644 --- a/unittests/tools/test_anchore_enterprise_parser.py +++ b/unittests/tools/test_anchore_enterprise_parser.py @@ -1,8 +1,9 @@ from os import path -from ..dojo_test_case import DojoTestCase -from dojo.tools.anchore_enterprise.parser import AnchoreEnterpriseParser -from dojo.tools.anchore_enterprise.parser import extract_vulnerability_id, search_filepath + from dojo.models import Test +from dojo.tools.anchore_enterprise.parser import AnchoreEnterpriseParser, extract_vulnerability_id, search_filepath + +from ..dojo_test_case import DojoTestCase class TestAnchoreEnterpriseParser(DojoTestCase): diff --git a/unittests/tools/test_anchore_grype_parser.py b/unittests/tools/test_anchore_grype_parser.py index 67f1072d5b..0b41180de1 100644 --- a/unittests/tools/test_anchore_grype_parser.py +++ b/unittests/tools/test_anchore_grype_parser.py @@ -1,8 +1,8 @@ -from ..dojo_test_case import DojoTestCase - from dojo.models import Finding, Test from dojo.tools.anchore_grype.parser import AnchoreGrypeParser +from ..dojo_test_case import DojoTestCase + class TestAnchoreGrypeParser(DojoTestCase): diff --git a/unittests/tools/test_anchorectl_policies_parser.py b/unittests/tools/test_anchorectl_policies_parser.py index 570656aad2..87968ea792 100644 --- a/unittests/tools/test_anchorectl_policies_parser.py +++ b/unittests/tools/test_anchorectl_policies_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.anchorectl_policies.parser import AnchoreCTLPoliciesParser from dojo.models import Test +from dojo.tools.anchorectl_policies.parser import AnchoreCTLPoliciesParser + +from ..dojo_test_case import DojoTestCase class TestAnchoreCTLPoliciesParser(DojoTestCase): diff --git a/unittests/tools/test_anchorectl_vulns_parser.py b/unittests/tools/test_anchorectl_vulns_parser.py index 19e28cbd3a..40295ec027 100644 --- a/unittests/tools/test_anchorectl_vulns_parser.py +++ b/unittests/tools/test_anchorectl_vulns_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.anchorectl_vulns.parser import AnchoreCTLVulnsParser from dojo.models import Test +from dojo.tools.anchorectl_vulns.parser import AnchoreCTLVulnsParser + +from ..dojo_test_case import DojoTestCase class TestAnchoreCTLVulnsParser(DojoTestCase): diff --git a/unittests/tools/test_api_blackduck_parser.py b/unittests/tools/test_api_blackduck_parser.py index fc3c548d53..d97b301f13 100644 --- a/unittests/tools/test_api_blackduck_parser.py +++ b/unittests/tools/test_api_blackduck_parser.py @@ -1,5 +1,5 @@ -from dojo.models import Test, SEVERITIES +from dojo.models import SEVERITIES, Test from dojo.tools.api_blackduck.parser import ApiBlackduckParser from ..dojo_test_case import DojoTestCase diff --git a/unittests/tools/test_api_bugcrowd_importer.py b/unittests/tools/test_api_bugcrowd_importer.py index 0a6e134473..e8fb4f784e 100644 --- a/unittests/tools/test_api_bugcrowd_importer.py +++ b/unittests/tools/test_api_bugcrowd_importer.py @@ -1,14 +1,15 @@ +from unittest.mock import patch + from django.core.exceptions import ValidationError from django.test import TestCase -from unittest.mock import patch from dojo.models import ( - Test, Engagement, Product, Product_API_Scan_Configuration, - Tool_Type, + Test, Tool_Configuration, + Tool_Type, ) from dojo.tools.api_bugcrowd.importer import BugcrowdApiImporter diff --git a/unittests/tools/test_api_bugcrowd_parser.py b/unittests/tools/test_api_bugcrowd_parser.py index f692797a19..2569fb16cc 100644 --- a/unittests/tools/test_api_bugcrowd_parser.py +++ b/unittests/tools/test_api_bugcrowd_parser.py @@ -1,8 +1,9 @@ import datetime from django.test import TestCase + +from dojo.models import Product_API_Scan_Configuration, Test from dojo.tools.api_bugcrowd.parser import ApiBugcrowdParser -from dojo.models import Test, Product_API_Scan_Configuration class TestApiBugcrowdParser(TestCase): diff --git a/unittests/tools/test_api_cobalt_importer.py b/unittests/tools/test_api_cobalt_importer.py index 28211b6c58..9eb78e373b 100644 --- a/unittests/tools/test_api_cobalt_importer.py +++ b/unittests/tools/test_api_cobalt_importer.py @@ -1,11 +1,13 @@ import json -from ..dojo_test_case import DojoTestCase from unittest.mock import patch + from django.core.exceptions import ValidationError -from dojo.models import Test, Engagement, Product, Product_API_Scan_Configuration, Tool_Type, Tool_Configuration +from dojo.models import Engagement, Product, Product_API_Scan_Configuration, Test, Tool_Configuration, Tool_Type from dojo.tools.api_cobalt.importer import CobaltApiImporter +from ..dojo_test_case import DojoTestCase + class TestCobaltApiImporter(DojoTestCase): diff --git a/unittests/tools/test_api_cobalt_parser.py b/unittests/tools/test_api_cobalt_parser.py index 6f4686ddc6..956bce388a 100644 --- a/unittests/tools/test_api_cobalt_parser.py +++ b/unittests/tools/test_api_cobalt_parser.py @@ -1,10 +1,10 @@ import json - -from ..dojo_test_case import DojoTestCase, get_unit_tests_path from unittest.mock import patch -from dojo.tools.api_cobalt.parser import ApiCobaltParser from dojo.models import Test, Test_Type +from dojo.tools.api_cobalt.parser import ApiCobaltParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestApiCobaltParser(DojoTestCase): diff --git a/unittests/tools/test_api_edgescan_importer.py b/unittests/tools/test_api_edgescan_importer.py index db23ea5709..2cd969affd 100644 --- a/unittests/tools/test_api_edgescan_importer.py +++ b/unittests/tools/test_api_edgescan_importer.py @@ -1,9 +1,10 @@ import json -from django.test import TestCase from unittest.mock import patch + from django.core.exceptions import ValidationError +from django.test import TestCase -from dojo.models import Test, Engagement, Product, Product_API_Scan_Configuration, Tool_Type, Tool_Configuration +from dojo.models import Engagement, Product, Product_API_Scan_Configuration, Test, Tool_Configuration, Tool_Type from dojo.tools.api_edgescan.importer import EdgescanImporter diff --git a/unittests/tools/test_api_edgescan_parser.py b/unittests/tools/test_api_edgescan_parser.py index cb8903a937..94d45fabf6 100644 --- a/unittests/tools/test_api_edgescan_parser.py +++ b/unittests/tools/test_api_edgescan_parser.py @@ -1,7 +1,7 @@ from django.test import TestCase -from dojo.tools.api_edgescan.parser import ApiEdgescanParser from dojo.models import Test +from dojo.tools.api_edgescan.parser import ApiEdgescanParser class TestApiEdgescanParser(TestCase): diff --git a/unittests/tools/test_api_sonarqube_importer.py b/unittests/tools/test_api_sonarqube_importer.py index 48b2053d4e..44e29f011b 100644 --- a/unittests/tools/test_api_sonarqube_importer.py +++ b/unittests/tools/test_api_sonarqube_importer.py @@ -1,10 +1,12 @@ import json from unittest import mock + from django.core.exceptions import ValidationError +from dojo.models import Engagement, Product, Product_API_Scan_Configuration, Test from dojo.tools.api_sonarqube.importer import SonarQubeApiImporter + from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.models import Test, Engagement, Product, Product_API_Scan_Configuration def dummy_product(self, *args, **kwargs): diff --git a/unittests/tools/test_api_sonarqube_parser.py b/unittests/tools/test_api_sonarqube_parser.py index abf18ab289..dd8de04c3b 100644 --- a/unittests/tools/test_api_sonarqube_parser.py +++ b/unittests/tools/test_api_sonarqube_parser.py @@ -1,9 +1,18 @@ import json from unittest import mock +from dojo.models import ( + Engagement, + Product, + Product_API_Scan_Configuration, + Product_Type, + Test, + Tool_Configuration, + Tool_Type, +) from dojo.tools.api_sonarqube.parser import ApiSonarQubeParser + from ..dojo_test_case import DojoTestCase -from dojo.models import Tool_Type, Tool_Configuration, Product_Type, Product, Engagement, Test, Product_API_Scan_Configuration def dummy_product(self, *args, **kwargs): diff --git a/unittests/tools/test_api_vulners_parser.py b/unittests/tools/test_api_vulners_parser.py index e555881be9..ea370389ba 100644 --- a/unittests/tools/test_api_vulners_parser.py +++ b/unittests/tools/test_api_vulners_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.api_vulners.parser import ApiVulnersParser from dojo.models import Test +from dojo.tools.api_vulners.parser import ApiVulnersParser + +from ..dojo_test_case import DojoTestCase class TestApiVulnersParser(DojoTestCase): diff --git a/unittests/tools/test_appspider_parser.py b/unittests/tools/test_appspider_parser.py index b309e9ac5f..094ca3e01e 100644 --- a/unittests/tools/test_appspider_parser.py +++ b/unittests/tools/test_appspider_parser.py @@ -1,7 +1,9 @@ from os import path -from ..dojo_test_case import DojoTestCase + +from dojo.models import Engagement, Finding, Product, Test from dojo.tools.appspider.parser import AppSpiderParser -from dojo.models import Product, Engagement, Test, Finding + +from ..dojo_test_case import DojoTestCase class TestAppSpiderParser(DojoTestCase): diff --git a/unittests/tools/test_aqua_parser.py b/unittests/tools/test_aqua_parser.py index 64656f459e..89f16334fa 100644 --- a/unittests/tools/test_aqua_parser.py +++ b/unittests/tools/test_aqua_parser.py @@ -1,8 +1,10 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.aqua.parser import AquaParser -from dojo.models import Test from collections import Counter +from dojo.models import Test +from dojo.tools.aqua.parser import AquaParser + +from ..dojo_test_case import DojoTestCase + class TestAquaParser(DojoTestCase): def test_aqua_parser_has_no_finding(self): diff --git a/unittests/tools/test_arachni_parser.py b/unittests/tools/test_arachni_parser.py index ea647fff38..ca28de74b4 100644 --- a/unittests/tools/test_arachni_parser.py +++ b/unittests/tools/test_arachni_parser.py @@ -1,7 +1,9 @@ import datetime -from ..dojo_test_case import DojoTestCase -from dojo.tools.arachni.parser import ArachniParser + from dojo.models import Test +from dojo.tools.arachni.parser import ArachniParser + +from ..dojo_test_case import DojoTestCase class TestArachniParser(DojoTestCase): diff --git a/unittests/tools/test_asff_parser.py b/unittests/tools/test_asff_parser.py index df8c38cd35..666e7bf8e7 100644 --- a/unittests/tools/test_asff_parser.py +++ b/unittests/tools/test_asff_parser.py @@ -1,8 +1,10 @@ -import os.path import json +import os.path from datetime import datetime -from dojo.models import Test, Endpoint + +from dojo.models import Endpoint, Test from dojo.tools.asff.parser import AsffParser + from ..dojo_test_case import DojoTestCase, get_unit_tests_path diff --git a/unittests/tools/test_auditjs_parser.py b/unittests/tools/test_auditjs_parser.py index fc95250276..629a6c9012 100644 --- a/unittests/tools/test_auditjs_parser.py +++ b/unittests/tools/test_auditjs_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.auditjs.parser import AuditJSParser from dojo.models import Test +from dojo.tools.auditjs.parser import AuditJSParser + +from ..dojo_test_case import DojoTestCase class TestAuditJSParser(DojoTestCase): diff --git a/unittests/tools/test_aws_prowler_parser.py b/unittests/tools/test_aws_prowler_parser.py index 9acb28481d..e4e1ee8392 100644 --- a/unittests/tools/test_aws_prowler_parser.py +++ b/unittests/tools/test_aws_prowler_parser.py @@ -1,7 +1,9 @@ import datetime -from ..dojo_test_case import DojoTestCase -from dojo.tools.aws_prowler.parser import AWSProwlerParser + from dojo.models import Test +from dojo.tools.aws_prowler.parser import AWSProwlerParser + +from ..dojo_test_case import DojoTestCase class TestAwsProwlerParser(DojoTestCase): diff --git a/unittests/tools/test_aws_prowler_v3_parser.py b/unittests/tools/test_aws_prowler_v3_parser.py index 9d155367c9..abbecc578e 100644 --- a/unittests/tools/test_aws_prowler_v3_parser.py +++ b/unittests/tools/test_aws_prowler_v3_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.aws_prowler_v3.parser import AWSProwlerV3Parser from dojo.models import Test +from dojo.tools.aws_prowler_v3.parser import AWSProwlerV3Parser + +from ..dojo_test_case import DojoTestCase class TestAwsProwlerV3Parser(DojoTestCase): diff --git a/unittests/tools/test_aws_scout2_parser.py b/unittests/tools/test_aws_scout2_parser.py index 4309554346..309f0eb853 100644 --- a/unittests/tools/test_aws_scout2_parser.py +++ b/unittests/tools/test_aws_scout2_parser.py @@ -1,7 +1,9 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.aws_scout2.parser import AWSScout2Parser from django.utils import timezone -from dojo.models import Test, Engagement, Product, Product_Type, Test_Type + +from dojo.models import Engagement, Product, Product_Type, Test, Test_Type +from dojo.tools.aws_scout2.parser import AWSScout2Parser + +from ..dojo_test_case import DojoTestCase class TestAwsProwlerParser(DojoTestCase): diff --git a/unittests/tools/test_awssecurityhub_parser.py b/unittests/tools/test_awssecurityhub_parser.py index 5f3621a609..d954bb66c3 100644 --- a/unittests/tools/test_awssecurityhub_parser.py +++ b/unittests/tools/test_awssecurityhub_parser.py @@ -1,8 +1,9 @@ import os.path -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.awssecurityhub.parser import AwsSecurityHubParser from dojo.models import Test +from dojo.tools.awssecurityhub.parser import AwsSecurityHubParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path def sample_path(file_name: str): diff --git a/unittests/tools/test_azure_security_center_recommendations_parser.py b/unittests/tools/test_azure_security_center_recommendations_parser.py index 5b863009f0..5ce988dfed 100644 --- a/unittests/tools/test_azure_security_center_recommendations_parser.py +++ b/unittests/tools/test_azure_security_center_recommendations_parser.py @@ -1,7 +1,9 @@ from datetime import date -from ..dojo_test_case import DojoTestCase -from dojo.tools.azure_security_center_recommendations.parser import AzureSecurityCenterRecommendationsParser + from dojo.models import Test +from dojo.tools.azure_security_center_recommendations.parser import AzureSecurityCenterRecommendationsParser + +from ..dojo_test_case import DojoTestCase class TestAzureSecurityCenterRecommendationsParser(DojoTestCase): diff --git a/unittests/tools/test_bandit_parser.py b/unittests/tools/test_bandit_parser.py index 4249d7beb9..f52a318738 100644 --- a/unittests/tools/test_bandit_parser.py +++ b/unittests/tools/test_bandit_parser.py @@ -1,10 +1,12 @@ import datetime from dateutil.tz import tzlocal -from ..dojo_test_case import DojoTestCase + from dojo.models import Test from dojo.tools.bandit.parser import BanditParser +from ..dojo_test_case import DojoTestCase + class TestBanditParser(DojoTestCase): def test_bandit_parser_has_no_finding(self): diff --git a/unittests/tools/test_bearer_cli_parser.py b/unittests/tools/test_bearer_cli_parser.py index 9f557757e9..c3e7581931 100644 --- a/unittests/tools/test_bearer_cli_parser.py +++ b/unittests/tools/test_bearer_cli_parser.py @@ -1,6 +1,7 @@ from django.test import TestCase -from dojo.tools.bearer_cli.parser import BearerParser + from dojo.models import Test +from dojo.tools.bearer_cli.parser import BearerParser class TestBearerParser(TestCase): diff --git a/unittests/tools/test_blackduck_binary_analysis_parser.py b/unittests/tools/test_blackduck_binary_analysis_parser.py index cb4af869ac..89d237c872 100644 --- a/unittests/tools/test_blackduck_binary_analysis_parser.py +++ b/unittests/tools/test_blackduck_binary_analysis_parser.py @@ -1,8 +1,10 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.blackduck_binary_analysis.parser import BlackduckBinaryAnalysisParser -from dojo.models import Test from pathlib import Path +from dojo.models import Test +from dojo.tools.blackduck_binary_analysis.parser import BlackduckBinaryAnalysisParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path + class TestBlackduckBinaryAnalysisParser(DojoTestCase): def test_parse_no_vulns(self): diff --git a/unittests/tools/test_blackduck_component_risk_parser.py b/unittests/tools/test_blackduck_component_risk_parser.py index 204ec42c5a..7ad8db6230 100644 --- a/unittests/tools/test_blackduck_component_risk_parser.py +++ b/unittests/tools/test_blackduck_component_risk_parser.py @@ -1,8 +1,10 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.blackduck_component_risk.parser import BlackduckComponentRiskParser -from dojo.models import Test from pathlib import Path +from dojo.models import Test +from dojo.tools.blackduck_component_risk.parser import BlackduckComponentRiskParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path + class TestBlackduckComponentRiskParser(DojoTestCase): def test_blackduck_enhanced_zip_upload(self): diff --git a/unittests/tools/test_blackduck_parser.py b/unittests/tools/test_blackduck_parser.py index 522b6f0bfd..1eaacd157a 100644 --- a/unittests/tools/test_blackduck_parser.py +++ b/unittests/tools/test_blackduck_parser.py @@ -1,8 +1,10 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.blackduck.parser import BlackduckParser -from dojo.models import Test from pathlib import Path +from dojo.models import Test +from dojo.tools.blackduck.parser import BlackduckParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path + class TestBlackduckHubParser(DojoTestCase): def test_blackduck_csv_parser_has_no_finding(self): diff --git a/unittests/tools/test_brakeman_parser.py b/unittests/tools/test_brakeman_parser.py index ca07945656..c8e3f195b6 100644 --- a/unittests/tools/test_brakeman_parser.py +++ b/unittests/tools/test_brakeman_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.brakeman.parser import BrakemanParser from dojo.models import Test +from dojo.tools.brakeman.parser import BrakemanParser + +from ..dojo_test_case import DojoTestCase class TestBrakemanParser(DojoTestCase): diff --git a/unittests/tools/test_bugcrowd_parser.py b/unittests/tools/test_bugcrowd_parser.py index ab5fce2027..f21451e7c2 100644 --- a/unittests/tools/test_bugcrowd_parser.py +++ b/unittests/tools/test_bugcrowd_parser.py @@ -1,8 +1,10 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.bugcrowd.parser import BugCrowdParser -from dojo.models import Test from datetime import datetime, timezone +from dojo.models import Test +from dojo.tools.bugcrowd.parser import BugCrowdParser + +from ..dojo_test_case import DojoTestCase + class TestBugCrowdParser(DojoTestCase): diff --git a/unittests/tools/test_bundler_audit_parser.py b/unittests/tools/test_bundler_audit_parser.py index 5e82252605..612f48007e 100644 --- a/unittests/tools/test_bundler_audit_parser.py +++ b/unittests/tools/test_bundler_audit_parser.py @@ -1,7 +1,9 @@ from os import path -from ..dojo_test_case import DojoTestCase -from dojo.tools.bundler_audit.parser import BundlerAuditParser + from dojo.models import Test +from dojo.tools.bundler_audit.parser import BundlerAuditParser + +from ..dojo_test_case import DojoTestCase class TestBundlerAuditParser(DojoTestCase): diff --git a/unittests/tools/test_burp_api_parser.py b/unittests/tools/test_burp_api_parser.py index 7006de7b7f..3217261faa 100644 --- a/unittests/tools/test_burp_api_parser.py +++ b/unittests/tools/test_burp_api_parser.py @@ -1,7 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path from dojo.models import Test -from dojo.tools.burp_api.parser import BurpApiParser -from dojo.tools.burp_api.parser import convert_severity, convert_confidence +from dojo.tools.burp_api.parser import BurpApiParser, convert_confidence, convert_severity + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestParser(DojoTestCase): diff --git a/unittests/tools/test_burp_dastardly_parser.py b/unittests/tools/test_burp_dastardly_parser.py index 9db996a5f2..d7e16b48ab 100644 --- a/unittests/tools/test_burp_dastardly_parser.py +++ b/unittests/tools/test_burp_dastardly_parser.py @@ -1,9 +1,10 @@ from os import path -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.burp_dastardly.parser import BurpDastardlyParser +from ..dojo_test_case import DojoTestCase + class TestBurpParser(DojoTestCase): diff --git a/unittests/tools/test_burp_enterprise_parser.py b/unittests/tools/test_burp_enterprise_parser.py index c180ca5ce2..0aeb7c0302 100644 --- a/unittests/tools/test_burp_enterprise_parser.py +++ b/unittests/tools/test_burp_enterprise_parser.py @@ -1,9 +1,10 @@ from os import path -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.burp_enterprise.parser import BurpEnterpriseParser +from ..dojo_test_case import DojoTestCase + class TestBurpEnterpriseParser(DojoTestCase): diff --git a/unittests/tools/test_burp_graphql_parser.py b/unittests/tools/test_burp_graphql_parser.py index 7c5dbb5307..cbc1ca8d5a 100644 --- a/unittests/tools/test_burp_graphql_parser.py +++ b/unittests/tools/test_burp_graphql_parser.py @@ -1,9 +1,10 @@ from os import path -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.burp_graphql.parser import BurpGraphQLParser +from ..dojo_test_case import DojoTestCase + class TestBurpGraphQLParser(DojoTestCase): diff --git a/unittests/tools/test_burp_parser.py b/unittests/tools/test_burp_parser.py index 27a952f6d8..f29aea11ad 100644 --- a/unittests/tools/test_burp_parser.py +++ b/unittests/tools/test_burp_parser.py @@ -1,9 +1,10 @@ from os import path -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.burp.parser import BurpParser +from ..dojo_test_case import DojoTestCase + class TestBurpParser(DojoTestCase): diff --git a/unittests/tools/test_cargo_audit_parser.py b/unittests/tools/test_cargo_audit_parser.py index 2b4fc2119a..5a1bb6aceb 100644 --- a/unittests/tools/test_cargo_audit_parser.py +++ b/unittests/tools/test_cargo_audit_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.cargo_audit.parser import CargoAuditParser from dojo.models import Test +from dojo.tools.cargo_audit.parser import CargoAuditParser + +from ..dojo_test_case import DojoTestCase class TestCargoAuditParser(DojoTestCase): diff --git a/unittests/tools/test_checkmarx_one_parser.py b/unittests/tools/test_checkmarx_one_parser.py index 4cda49a26e..398ea9aff5 100644 --- a/unittests/tools/test_checkmarx_one_parser.py +++ b/unittests/tools/test_checkmarx_one_parser.py @@ -1,5 +1,6 @@ from dojo.models import Test from dojo.tools.checkmarx_one.parser import CheckmarxOneParser + from ..dojo_test_case import DojoTestCase diff --git a/unittests/tools/test_checkmarx_osa_parser.py b/unittests/tools/test_checkmarx_osa_parser.py index 6002e8da16..afefb96821 100644 --- a/unittests/tools/test_checkmarx_osa_parser.py +++ b/unittests/tools/test_checkmarx_osa_parser.py @@ -1,8 +1,9 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path +from datetime import datetime -from dojo.models import Test, Engagement, Product +from dojo.models import Engagement, Product, Test from dojo.tools.checkmarx_osa.parser import CheckmarxOsaParser -from datetime import datetime + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestCheckmarxOsaParser(DojoTestCase): diff --git a/unittests/tools/test_checkov_parser.py b/unittests/tools/test_checkov_parser.py index 9cfdbf91e5..ef9f67dc1c 100644 --- a/unittests/tools/test_checkov_parser.py +++ b/unittests/tools/test_checkov_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.checkov.parser import CheckovParser from dojo.models import Test +from dojo.tools.checkov.parser import CheckovParser + +from ..dojo_test_case import DojoTestCase class TestCheckovParser(DojoTestCase): diff --git a/unittests/tools/test_chefinspect_parser.py b/unittests/tools/test_chefinspect_parser.py index 1dde5af4d9..9455020257 100644 --- a/unittests/tools/test_chefinspect_parser.py +++ b/unittests/tools/test_chefinspect_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.chefinspect.parser import ChefInspectParser from dojo.models import Test +from dojo.tools.chefinspect.parser import ChefInspectParser + +from ..dojo_test_case import DojoTestCase class TestChefInspectParser(DojoTestCase): diff --git a/unittests/tools/test_clair_parser.py b/unittests/tools/test_clair_parser.py index 31297c4df7..745b92003d 100644 --- a/unittests/tools/test_clair_parser.py +++ b/unittests/tools/test_clair_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase from dojo.tools.clair.parser import ClairParser +from ..dojo_test_case import DojoTestCase + class TestClairParser(DojoTestCase): diff --git a/unittests/tools/test_cloudsploit_parser.py b/unittests/tools/test_cloudsploit_parser.py index b307308f9f..a054848a1b 100644 --- a/unittests/tools/test_cloudsploit_parser.py +++ b/unittests/tools/test_cloudsploit_parser.py @@ -1,7 +1,8 @@ -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.cloudsploit.parser import CloudsploitParser +from ..dojo_test_case import DojoTestCase + class TestCloudsploitParser(DojoTestCase): diff --git a/unittests/tools/test_cobalt_parser.py b/unittests/tools/test_cobalt_parser.py index 1a5235fada..d3bca067c1 100644 --- a/unittests/tools/test_cobalt_parser.py +++ b/unittests/tools/test_cobalt_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.cobalt.parser import CobaltParser from dojo.models import Test +from dojo.tools.cobalt.parser import CobaltParser + +from ..dojo_test_case import DojoTestCase class TestCobaltParser(DojoTestCase): diff --git a/unittests/tools/test_codechecker_parser.py b/unittests/tools/test_codechecker_parser.py index 2aa53c51ae..fb118215c7 100644 --- a/unittests/tools/test_codechecker_parser.py +++ b/unittests/tools/test_codechecker_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.codechecker.parser import CodeCheckerParser from dojo.models import Test +from dojo.tools.codechecker.parser import CodeCheckerParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestCodeCheckerParser(DojoTestCase): diff --git a/unittests/tools/test_contrast_parser.py b/unittests/tools/test_contrast_parser.py index 4e31c09e37..70821628b4 100644 --- a/unittests/tools/test_contrast_parser.py +++ b/unittests/tools/test_contrast_parser.py @@ -1,10 +1,10 @@ import datetime -from ..dojo_test_case import DojoTestCase - -from dojo.models import Test, Engagement, Product +from dojo.models import Engagement, Product, Test from dojo.tools.contrast.parser import ContrastParser +from ..dojo_test_case import DojoTestCase + class TestContrastParser(DojoTestCase): diff --git a/unittests/tools/test_coverity_api_parser.py b/unittests/tools/test_coverity_api_parser.py index 2a2c148819..8a480a230d 100644 --- a/unittests/tools/test_coverity_api_parser.py +++ b/unittests/tools/test_coverity_api_parser.py @@ -1,9 +1,10 @@ import datetime -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.coverity_api.parser import CoverityApiParser +from ..dojo_test_case import DojoTestCase + class TestZapParser(DojoTestCase): def test_parse_wrong_file(self): diff --git a/unittests/tools/test_crashtest_security_parser.py b/unittests/tools/test_crashtest_security_parser.py index 07fa57affd..da05803f97 100644 --- a/unittests/tools/test_crashtest_security_parser.py +++ b/unittests/tools/test_crashtest_security_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.crashtest_security.parser import CrashtestSecurityParser from dojo.models import Test +from dojo.tools.crashtest_security.parser import CrashtestSecurityParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestCrashtestSecurityParser(DojoTestCase): diff --git a/unittests/tools/test_cred_scan_parser.py b/unittests/tools/test_cred_scan_parser.py index 2bff8c559b..c8aebcbdca 100644 --- a/unittests/tools/test_cred_scan_parser.py +++ b/unittests/tools/test_cred_scan_parser.py @@ -1,8 +1,10 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.cred_scan.parser import CredScanParser -from dojo.models import Test import datetime +from dojo.models import Test +from dojo.tools.cred_scan.parser import CredScanParser + +from ..dojo_test_case import DojoTestCase + class TestCredScanParser(DojoTestCase): diff --git a/unittests/tools/test_crunch42_parser.py b/unittests/tools/test_crunch42_parser.py index 512521808a..3f203bd3c5 100644 --- a/unittests/tools/test_crunch42_parser.py +++ b/unittests/tools/test_crunch42_parser.py @@ -1,7 +1,8 @@ -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.crunch42.parser import Crunch42Parser +from ..dojo_test_case import DojoTestCase + class TestCrunch42Parser(DojoTestCase): diff --git a/unittests/tools/test_cyclonedx_parser.py b/unittests/tools/test_cyclonedx_parser.py index ef0371bf09..5aa5cd218b 100644 --- a/unittests/tools/test_cyclonedx_parser.py +++ b/unittests/tools/test_cyclonedx_parser.py @@ -1,9 +1,10 @@ import datetime -from ..dojo_test_case import DojoTestCase -from dojo.models import Test, Finding +from dojo.models import Finding, Test from dojo.tools.cyclonedx.parser import CycloneDXParser +from ..dojo_test_case import DojoTestCase + class TestCyclonedxParser(DojoTestCase): def test_grype_report(self): diff --git a/unittests/tools/test_dawnscanner_parser.py b/unittests/tools/test_dawnscanner_parser.py index db83cdac1a..f0833b61fd 100644 --- a/unittests/tools/test_dawnscanner_parser.py +++ b/unittests/tools/test_dawnscanner_parser.py @@ -1,10 +1,11 @@ import datetime from os import path -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.dawnscanner.parser import DawnScannerParser +from ..dojo_test_case import DojoTestCase + class TestDawnScannerParser(DojoTestCase): def test_burp_with_one_vuln_has_one_finding(self): diff --git a/unittests/tools/test_dependency_check_parser.py b/unittests/tools/test_dependency_check_parser.py index 0f6f9c4d96..c6a26d1e78 100644 --- a/unittests/tools/test_dependency_check_parser.py +++ b/unittests/tools/test_dependency_check_parser.py @@ -1,7 +1,8 @@ from datetime import datetime, timezone from os import path -from dateutil.tz import tzoffset, tzlocal +from dateutil.tz import tzlocal, tzoffset + from dojo.models import Test from dojo.tools.dependency_check.parser import DependencyCheckParser diff --git a/unittests/tools/test_dependency_track_parser.py b/unittests/tools/test_dependency_track_parser.py index 57b7c23530..f2783229d9 100644 --- a/unittests/tools/test_dependency_track_parser.py +++ b/unittests/tools/test_dependency_track_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.dependency_track.parser import DependencyTrackParser from dojo.models import Test +from dojo.tools.dependency_track.parser import DependencyTrackParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestDependencyTrackParser(DojoTestCase): diff --git a/unittests/tools/test_detect_secrets_parser.py b/unittests/tools/test_detect_secrets_parser.py index 6d3f6dff0f..0c11f06b8f 100644 --- a/unittests/tools/test_detect_secrets_parser.py +++ b/unittests/tools/test_detect_secrets_parser.py @@ -1,8 +1,11 @@ import datetime + from dateutil.tz import tzlocal -from ..dojo_test_case import DojoTestCase -from dojo.tools.detect_secrets.parser import DetectSecretsParser + from dojo.models import Test +from dojo.tools.detect_secrets.parser import DetectSecretsParser + +from ..dojo_test_case import DojoTestCase class TestDetectSecretsParser(DojoTestCase): diff --git a/unittests/tools/test_dockerbench_parser.py b/unittests/tools/test_dockerbench_parser.py index 0f10d41b46..6a52066172 100644 --- a/unittests/tools/test_dockerbench_parser.py +++ b/unittests/tools/test_dockerbench_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.dockerbench.parser import DockerBenchParser from dojo.models import Test +from dojo.tools.dockerbench.parser import DockerBenchParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestDockerBenchParser(DojoTestCase): diff --git a/unittests/tools/test_dockle_parser.py b/unittests/tools/test_dockle_parser.py index 77f9096594..5baed6455c 100644 --- a/unittests/tools/test_dockle_parser.py +++ b/unittests/tools/test_dockle_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.dockle.parser import DockleParser from dojo.models import Test +from dojo.tools.dockle.parser import DockleParser + +from ..dojo_test_case import DojoTestCase class TestDockleParser(DojoTestCase): diff --git a/unittests/tools/test_drheader_parser.py b/unittests/tools/test_drheader_parser.py index 30dad246fd..9ae187497c 100644 --- a/unittests/tools/test_drheader_parser.py +++ b/unittests/tools/test_drheader_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.drheader.parser import DrHeaderParser from dojo.models import Test +from dojo.tools.drheader.parser import DrHeaderParser + +from ..dojo_test_case import DojoTestCase class TestDrHeaderParser(DojoTestCase): diff --git a/unittests/tools/test_dsop_parser.py b/unittests/tools/test_dsop_parser.py index 4a89113cd8..d4ffd6ff5f 100644 --- a/unittests/tools/test_dsop_parser.py +++ b/unittests/tools/test_dsop_parser.py @@ -1,7 +1,7 @@ -from ..dojo_test_case import DojoTestCase +from dojo.models import Test from dojo.tools.dsop.parser import DsopParser -from dojo.models import Test +from ..dojo_test_case import DojoTestCase class TestDsopParser(DojoTestCase): diff --git a/unittests/tools/test_eslint_parser.py b/unittests/tools/test_eslint_parser.py index 5953f0b816..f04d446496 100644 --- a/unittests/tools/test_eslint_parser.py +++ b/unittests/tools/test_eslint_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.eslint.parser import ESLintParser from dojo.models import Test +from dojo.tools.eslint.parser import ESLintParser + +from ..dojo_test_case import DojoTestCase class TestESLintParser(DojoTestCase): diff --git a/unittests/tools/test_fortify_parser.py b/unittests/tools/test_fortify_parser.py index a9527fa6ee..52140f66a5 100644 --- a/unittests/tools/test_fortify_parser.py +++ b/unittests/tools/test_fortify_parser.py @@ -1,5 +1,6 @@ from dojo.models import Test from dojo.tools.fortify.parser import FortifyParser + from ..dojo_test_case import DojoTestCase diff --git a/unittests/tools/test_gcloud_artifact_scan_parser.py b/unittests/tools/test_gcloud_artifact_scan_parser.py index 6da293f348..762fbbb3b9 100644 --- a/unittests/tools/test_gcloud_artifact_scan_parser.py +++ b/unittests/tools/test_gcloud_artifact_scan_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.gcloud_artifact_scan.parser import GCloudArtifactScanParser from dojo.models import Test +from dojo.tools.gcloud_artifact_scan.parser import GCloudArtifactScanParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestGCloudArtifactScanParser(DojoTestCase): diff --git a/unittests/tools/test_generic_parser.py b/unittests/tools/test_generic_parser.py index 677b5bf13b..5951f9a413 100644 --- a/unittests/tools/test_generic_parser.py +++ b/unittests/tools/test_generic_parser.py @@ -1,8 +1,10 @@ import datetime -from ..dojo_test_case import DojoTestCase -from dojo.models import Test, Engagement, Product, Finding + +from dojo.models import Engagement, Finding, Product, Test from dojo.tools.generic.parser import GenericParser +from ..dojo_test_case import DojoTestCase + class TestFile: diff --git a/unittests/tools/test_ggshield_parser.py b/unittests/tools/test_ggshield_parser.py index 53797b77ba..c95a70b8d0 100644 --- a/unittests/tools/test_ggshield_parser.py +++ b/unittests/tools/test_ggshield_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.ggshield.parser import GgshieldParser from dojo.models import Test +from dojo.tools.ggshield.parser import GgshieldParser + +from ..dojo_test_case import DojoTestCase class TestGgshieldParser(DojoTestCase): diff --git a/unittests/tools/test_github_vulnerability_parser.py b/unittests/tools/test_github_vulnerability_parser.py index df22540824..cff3956675 100644 --- a/unittests/tools/test_github_vulnerability_parser.py +++ b/unittests/tools/test_github_vulnerability_parser.py @@ -2,10 +2,11 @@ from dateutil.tz import tzlocal -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.github_vulnerability.parser import GithubVulnerabilityParser +from ..dojo_test_case import DojoTestCase + class TestGithubVulnerabilityParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): diff --git a/unittests/tools/test_gitlab_api_fuzzing_parser.py b/unittests/tools/test_gitlab_api_fuzzing_parser.py index 311d3acf4f..33698d5d4a 100644 --- a/unittests/tools/test_gitlab_api_fuzzing_parser.py +++ b/unittests/tools/test_gitlab_api_fuzzing_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.gitlab_api_fuzzing.parser import GitlabAPIFuzzingParser from dojo.models import Test +from dojo.tools.gitlab_api_fuzzing.parser import GitlabAPIFuzzingParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestGitlabAPIFuzzingParser(DojoTestCase): diff --git a/unittests/tools/test_gitlab_container_scan_parser.py b/unittests/tools/test_gitlab_container_scan_parser.py index 9ba4910bb8..8aaaca7f18 100644 --- a/unittests/tools/test_gitlab_container_scan_parser.py +++ b/unittests/tools/test_gitlab_container_scan_parser.py @@ -1,7 +1,9 @@ from datetime import datetime -from ..dojo_test_case import DojoTestCase -from dojo.tools.gitlab_container_scan.parser import GitlabContainerScanParser + from dojo.models import Test +from dojo.tools.gitlab_container_scan.parser import GitlabContainerScanParser + +from ..dojo_test_case import DojoTestCase class TestGitlabContainerScanParser(DojoTestCase): diff --git a/unittests/tools/test_gitlab_dast_parser.py b/unittests/tools/test_gitlab_dast_parser.py index 8e6a9a0817..7d778adc40 100644 --- a/unittests/tools/test_gitlab_dast_parser.py +++ b/unittests/tools/test_gitlab_dast_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.gitlab_dast.parser import GitlabDastParser from dojo.models import Test +from dojo.tools.gitlab_dast.parser import GitlabDastParser + +from ..dojo_test_case import DojoTestCase class TestGitlabDastParser(DojoTestCase): diff --git a/unittests/tools/test_gitlab_dep_scan_parser.py b/unittests/tools/test_gitlab_dep_scan_parser.py index a4e691260e..7601438490 100644 --- a/unittests/tools/test_gitlab_dep_scan_parser.py +++ b/unittests/tools/test_gitlab_dep_scan_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.gitlab_dep_scan.parser import GitlabDepScanParser from dojo.models import Test +from dojo.tools.gitlab_dep_scan.parser import GitlabDepScanParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestGitlabDepScanParser(DojoTestCase): diff --git a/unittests/tools/test_gitlab_sast_parser.py b/unittests/tools/test_gitlab_sast_parser.py index 779675592c..b0acbe3421 100644 --- a/unittests/tools/test_gitlab_sast_parser.py +++ b/unittests/tools/test_gitlab_sast_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.gitlab_sast.parser import GitlabSastParser from dojo.models import Test +from dojo.tools.gitlab_sast.parser import GitlabSastParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestGitlabSastParser(DojoTestCase): diff --git a/unittests/tools/test_gitlab_secret_detection_report_parser.py b/unittests/tools/test_gitlab_secret_detection_report_parser.py index a9adff4412..4c1d60922d 100644 --- a/unittests/tools/test_gitlab_secret_detection_report_parser.py +++ b/unittests/tools/test_gitlab_secret_detection_report_parser.py @@ -1,9 +1,11 @@ from datetime import datetime -from ..dojo_test_case import DojoTestCase, get_unit_tests_path + +from dojo.models import Test from dojo.tools.gitlab_secret_detection_report.parser import ( GitlabSecretDetectionReportParser, ) -from dojo.models import Test + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestGitlabSecretDetectionReportParser(DojoTestCase): diff --git a/unittests/tools/test_gitleaks_parser.py b/unittests/tools/test_gitleaks_parser.py index 23b9878d83..f3ba72907b 100644 --- a/unittests/tools/test_gitleaks_parser.py +++ b/unittests/tools/test_gitleaks_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.gitleaks.parser import GitleaksParser from dojo.models import Test +from dojo.tools.gitleaks.parser import GitleaksParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestGitleaksParser(DojoTestCase): diff --git a/unittests/tools/test_gosec_parser.py b/unittests/tools/test_gosec_parser.py index 104b9c19a2..a4274301da 100644 --- a/unittests/tools/test_gosec_parser.py +++ b/unittests/tools/test_gosec_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.gosec.parser import GosecParser from dojo.models import Test +from dojo.tools.gosec.parser import GosecParser + +from ..dojo_test_case import DojoTestCase class TestGosecParser(DojoTestCase): diff --git a/unittests/tools/test_govulncheck_parser.py b/unittests/tools/test_govulncheck_parser.py index 99dd19108a..f90a699fb1 100644 --- a/unittests/tools/test_govulncheck_parser.py +++ b/unittests/tools/test_govulncheck_parser.py @@ -1,6 +1,6 @@ -from unittests.dojo_test_case import DojoTestCase -from dojo.tools.govulncheck.parser import GovulncheckParser from dojo.models import Test +from dojo.tools.govulncheck.parser import GovulncheckParser +from unittests.dojo_test_case import DojoTestCase class TestGovulncheckParser(DojoTestCase): diff --git a/unittests/tools/test_h1_parser.py b/unittests/tools/test_h1_parser.py index 74325261e9..d216c0498e 100644 --- a/unittests/tools/test_h1_parser.py +++ b/unittests/tools/test_h1_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.h1.parser import H1Parser from dojo.models import Test +from dojo.tools.h1.parser import H1Parser + +from ..dojo_test_case import DojoTestCase class TestHackerOneParser(DojoTestCase): diff --git a/unittests/tools/test_hadolint_parser.py b/unittests/tools/test_hadolint_parser.py index a5afe5dfc3..48cafebb9d 100644 --- a/unittests/tools/test_hadolint_parser.py +++ b/unittests/tools/test_hadolint_parser.py @@ -1,7 +1,8 @@ -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.hadolint.parser import HadolintParser +from ..dojo_test_case import DojoTestCase + class TesthadolintParser(DojoTestCase): diff --git a/unittests/tools/test_harbor_vulnerability_parser.py b/unittests/tools/test_harbor_vulnerability_parser.py index aad6137a8b..6a947d2d84 100644 --- a/unittests/tools/test_harbor_vulnerability_parser.py +++ b/unittests/tools/test_harbor_vulnerability_parser.py @@ -1,7 +1,8 @@ -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.harbor_vulnerability.parser import HarborVulnerabilityParser +from ..dojo_test_case import DojoTestCase + class TestHarborVulnerabilityParser(DojoTestCase): diff --git a/unittests/tools/test_hcl_appscan_parser.py b/unittests/tools/test_hcl_appscan_parser.py index daaf04f4a5..63d1b9e912 100644 --- a/unittests/tools/test_hcl_appscan_parser.py +++ b/unittests/tools/test_hcl_appscan_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase from dojo.tools.hcl_appscan.parser import HCLAppScanParser +from ..dojo_test_case import DojoTestCase + class TestHCLAppScanParser(DojoTestCase): diff --git a/unittests/tools/test_horusec_parser.py b/unittests/tools/test_horusec_parser.py index 806a25eee6..308738f779 100644 --- a/unittests/tools/test_horusec_parser.py +++ b/unittests/tools/test_horusec_parser.py @@ -1,10 +1,11 @@ import datetime from os import path -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.horusec.parser import HorusecParser +from ..dojo_test_case import DojoTestCase + class TestHorusecParser(DojoTestCase): def test_get_findings(self): diff --git a/unittests/tools/test_humble_parser.py b/unittests/tools/test_humble_parser.py index d057010638..2b0a85a2ca 100644 --- a/unittests/tools/test_humble_parser.py +++ b/unittests/tools/test_humble_parser.py @@ -1,5 +1,5 @@ -from dojo.tools.humble.parser import HumbleParser from dojo.models import Test +from dojo.tools.humble.parser import HumbleParser from unittests.dojo_test_case import DojoTestCase diff --git a/unittests/tools/test_huskyci_parser.py b/unittests/tools/test_huskyci_parser.py index 46f07433ad..76aad5a15c 100644 --- a/unittests/tools/test_huskyci_parser.py +++ b/unittests/tools/test_huskyci_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.huskyci.parser import HuskyCIParser from dojo.models import Test +from dojo.tools.huskyci.parser import HuskyCIParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestHuskyCIParser(DojoTestCase): diff --git a/unittests/tools/test_hydra_parser.py b/unittests/tools/test_hydra_parser.py index d475ce2de5..22beeccebe 100644 --- a/unittests/tools/test_hydra_parser.py +++ b/unittests/tools/test_hydra_parser.py @@ -1,7 +1,7 @@ -from datetime import datetime, date +from datetime import date, datetime +from dojo.models import Finding, Test from dojo.tools.hydra.parser import HydraParser -from dojo.models import Test, Finding from unittests.dojo_test_case import DojoTestCase diff --git a/unittests/tools/test_ibm_app_parser.py b/unittests/tools/test_ibm_app_parser.py index e738f292ac..6755d294c0 100644 --- a/unittests/tools/test_ibm_app_parser.py +++ b/unittests/tools/test_ibm_app_parser.py @@ -1,7 +1,8 @@ -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.ibm_app.parser import IbmAppParser +from ..dojo_test_case import DojoTestCase + class TestIbmAppParser(DojoTestCase): diff --git a/unittests/tools/test_immuniweb_parser.py b/unittests/tools/test_immuniweb_parser.py index 49e2c619de..ed79494c67 100644 --- a/unittests/tools/test_immuniweb_parser.py +++ b/unittests/tools/test_immuniweb_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.immuniweb.parser import ImmuniwebParser from dojo.models import Test +from dojo.tools.immuniweb.parser import ImmuniwebParser + +from ..dojo_test_case import DojoTestCase class TestImmuniwebParser(DojoTestCase): diff --git a/unittests/tools/test_intsights_parser.py b/unittests/tools/test_intsights_parser.py index b35e75de8c..7afd0e33dd 100644 --- a/unittests/tools/test_intsights_parser.py +++ b/unittests/tools/test_intsights_parser.py @@ -1,7 +1,8 @@ -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.intsights.parser import IntSightsParser +from ..dojo_test_case import DojoTestCase + class TestIntSightsParser(DojoTestCase): def test_intsights_parser_with_one_critical_vuln_has_one_findings_json( diff --git a/unittests/tools/test_jfrog_xray_api_summary_artifact_parser.py b/unittests/tools/test_jfrog_xray_api_summary_artifact_parser.py index c1ca0ec341..d191ca7b43 100644 --- a/unittests/tools/test_jfrog_xray_api_summary_artifact_parser.py +++ b/unittests/tools/test_jfrog_xray_api_summary_artifact_parser.py @@ -1,9 +1,11 @@ -from ..dojo_test_case import DojoTestCase +import hashlib + from dojo.models import Test from dojo.tools.jfrog_xray_api_summary_artifact.parser import ( JFrogXrayApiSummaryArtifactParser, ) -import hashlib + +from ..dojo_test_case import DojoTestCase class TestJFrogXrayApiSummaryArtifactParser(DojoTestCase): diff --git a/unittests/tools/test_jfrog_xray_on_demand_binary_scan_parser.py b/unittests/tools/test_jfrog_xray_on_demand_binary_scan_parser.py index 0fd6712f07..8109d7c48a 100644 --- a/unittests/tools/test_jfrog_xray_on_demand_binary_scan_parser.py +++ b/unittests/tools/test_jfrog_xray_on_demand_binary_scan_parser.py @@ -1,7 +1,11 @@ +from dojo.models import Finding, Test +from dojo.tools.jfrog_xray_on_demand_binary_scan.parser import ( + JFrogXrayOnDemandBinaryScanParser, + clean_title, + get_component_name_version, +) + from ..dojo_test_case import DojoTestCase -from dojo.models import Test, Finding -from dojo.tools.jfrog_xray_on_demand_binary_scan.parser import \ - JFrogXrayOnDemandBinaryScanParser, get_component_name_version, clean_title class TestJFrogXrayOnDemandBinaryScanParser(DojoTestCase): diff --git a/unittests/tools/test_jfrog_xray_unified_parser.py b/unittests/tools/test_jfrog_xray_unified_parser.py index d6dda8850b..9b8465e89a 100644 --- a/unittests/tools/test_jfrog_xray_unified_parser.py +++ b/unittests/tools/test_jfrog_xray_unified_parser.py @@ -1,8 +1,10 @@ import datetime -from ..dojo_test_case import DojoTestCase + from dojo.models import Test from dojo.tools.jfrog_xray_unified.parser import JFrogXrayUnifiedParser +from ..dojo_test_case import DojoTestCase + class TestJFrogXrayUnifiedParser(DojoTestCase): diff --git a/unittests/tools/test_jfrogxray_parser.py b/unittests/tools/test_jfrogxray_parser.py index fb88ec30eb..d48742b9ff 100644 --- a/unittests/tools/test_jfrogxray_parser.py +++ b/unittests/tools/test_jfrogxray_parser.py @@ -1,7 +1,8 @@ -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.jfrogxray.parser import JFrogXrayParser, decode_cwe_number +from ..dojo_test_case import DojoTestCase + class TestJfrogJFrogXrayParser(DojoTestCase): diff --git a/unittests/tools/test_kics_parser.py b/unittests/tools/test_kics_parser.py index 41b8efb9fe..3e814dc87f 100644 --- a/unittests/tools/test_kics_parser.py +++ b/unittests/tools/test_kics_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.kics.parser import KICSParser from dojo.models import Test +from dojo.tools.kics.parser import KICSParser + +from ..dojo_test_case import DojoTestCase class TestKICSParser(DojoTestCase): diff --git a/unittests/tools/test_kiuwan_parser.py b/unittests/tools/test_kiuwan_parser.py index ec10baf2c0..0d8a458719 100644 --- a/unittests/tools/test_kiuwan_parser.py +++ b/unittests/tools/test_kiuwan_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.kiuwan.parser import KiuwanParser from dojo.models import Test +from dojo.tools.kiuwan.parser import KiuwanParser + +from ..dojo_test_case import DojoTestCase class TestKiuwanParser(DojoTestCase): diff --git a/unittests/tools/test_kubeaudit_parser.py b/unittests/tools/test_kubeaudit_parser.py index b40db502d9..65b52378a2 100644 --- a/unittests/tools/test_kubeaudit_parser.py +++ b/unittests/tools/test_kubeaudit_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.kubeaudit.parser import KubeAuditParser from dojo.models import Test +from dojo.tools.kubeaudit.parser import KubeAuditParser + +from ..dojo_test_case import DojoTestCase class TestKubeAuditParser(DojoTestCase): diff --git a/unittests/tools/test_kubebench_parser.py b/unittests/tools/test_kubebench_parser.py index d5359e59bf..e0c7b6181a 100644 --- a/unittests/tools/test_kubebench_parser.py +++ b/unittests/tools/test_kubebench_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.kubebench.parser import KubeBenchParser from dojo.models import Test +from dojo.tools.kubebench.parser import KubeBenchParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestKubeBenchParser(DojoTestCase): diff --git a/unittests/tools/test_kubehunter_parser.py b/unittests/tools/test_kubehunter_parser.py index e1cc133af0..6912df0380 100644 --- a/unittests/tools/test_kubehunter_parser.py +++ b/unittests/tools/test_kubehunter_parser.py @@ -1,6 +1,7 @@ from django.test import TestCase -from dojo.tools.kubehunter.parser import KubeHunterParser + from dojo.models import Test +from dojo.tools.kubehunter.parser import KubeHunterParser class TestKubeHunterParser(TestCase): diff --git a/unittests/tools/test_kubescape_parser.py b/unittests/tools/test_kubescape_parser.py index c134f0c7ca..bccbed220a 100644 --- a/unittests/tools/test_kubescape_parser.py +++ b/unittests/tools/test_kubescape_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.kubescape.parser import KubescapeParser from dojo.models import Test +from dojo.tools.kubescape.parser import KubescapeParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestOrtParser(DojoTestCase): diff --git a/unittests/tools/test_mend_parser.py b/unittests/tools/test_mend_parser.py index d7a693aa3a..d30a35752a 100644 --- a/unittests/tools/test_mend_parser.py +++ b/unittests/tools/test_mend_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.mend.parser import MendParser from dojo.models import Test +from dojo.tools.mend.parser import MendParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestMendParser(DojoTestCase): diff --git a/unittests/tools/test_meterian_parser.py b/unittests/tools/test_meterian_parser.py index b2f74271b1..728c669020 100644 --- a/unittests/tools/test_meterian_parser.py +++ b/unittests/tools/test_meterian_parser.py @@ -1,7 +1,8 @@ -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.meterian.parser import MeterianParser +from ..dojo_test_case import DojoTestCase + class TestMeterianParser(DojoTestCase): diff --git a/unittests/tools/test_microfocus_webinspect_parser.py b/unittests/tools/test_microfocus_webinspect_parser.py index b7c2438c27..b44678cb4d 100644 --- a/unittests/tools/test_microfocus_webinspect_parser.py +++ b/unittests/tools/test_microfocus_webinspect_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path +from dojo.models import Engagement, Product, Test from dojo.tools.microfocus_webinspect.parser import MicrofocusWebinspectParser -from dojo.models import Test, Engagement, Product + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestMicrofocusWebinspectParser(DojoTestCase): diff --git a/unittests/tools/test_mobsf_parser.py b/unittests/tools/test_mobsf_parser.py index 64e38289a6..e5eb2a48e0 100644 --- a/unittests/tools/test_mobsf_parser.py +++ b/unittests/tools/test_mobsf_parser.py @@ -1,7 +1,8 @@ -from ..dojo_test_case import DojoTestCase -from dojo.models import Test, Engagement, Product +from dojo.models import Engagement, Product, Test from dojo.tools.mobsf.parser import MobSFParser +from ..dojo_test_case import DojoTestCase + class TestMobSFParser(DojoTestCase): diff --git a/unittests/tools/test_mobsfscan_parser.py b/unittests/tools/test_mobsfscan_parser.py index a65f3a61a6..038bc09091 100644 --- a/unittests/tools/test_mobsfscan_parser.py +++ b/unittests/tools/test_mobsfscan_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.mobsfscan.parser import MobsfscanParser from dojo.models import Test +from dojo.tools.mobsfscan.parser import MobsfscanParser + +from ..dojo_test_case import DojoTestCase class TestMobsfscanParser(DojoTestCase): diff --git a/unittests/tools/test_mozilla_observatory_parser.py b/unittests/tools/test_mozilla_observatory_parser.py index 0408f7cea1..147eff5f2b 100644 --- a/unittests/tools/test_mozilla_observatory_parser.py +++ b/unittests/tools/test_mozilla_observatory_parser.py @@ -1,7 +1,8 @@ -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.mozilla_observatory.parser import MozillaObservatoryParser +from ..dojo_test_case import DojoTestCase + class TestMozillaObservatoryParser(DojoTestCase): def test_parse_file_with_no_vuln_has_no_findings(self): diff --git a/unittests/tools/test_ms_defender_parser.py b/unittests/tools/test_ms_defender_parser.py index c4f899e3ab..f8365757fc 100644 --- a/unittests/tools/test_ms_defender_parser.py +++ b/unittests/tools/test_ms_defender_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.ms_defender.parser import MSDefenderParser from dojo.models import Test +from dojo.tools.ms_defender.parser import MSDefenderParser + +from ..dojo_test_case import DojoTestCase class TestSDefenderParser(DojoTestCase): diff --git a/unittests/tools/test_nancy_parser.py b/unittests/tools/test_nancy_parser.py index ae45c36239..5918f12ce9 100644 --- a/unittests/tools/test_nancy_parser.py +++ b/unittests/tools/test_nancy_parser.py @@ -1,7 +1,9 @@ from os import path -from ..dojo_test_case import DojoTestCase -from dojo.tools.nancy.parser import NancyParser + from dojo.models import Test +from dojo.tools.nancy.parser import NancyParser + +from ..dojo_test_case import DojoTestCase class TestNancyParser(DojoTestCase): diff --git a/unittests/tools/test_netsparker_parser.py b/unittests/tools/test_netsparker_parser.py index b675b04961..cf8b9837b8 100644 --- a/unittests/tools/test_netsparker_parser.py +++ b/unittests/tools/test_netsparker_parser.py @@ -1,7 +1,8 @@ -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.netsparker.parser import NetsparkerParser +from ..dojo_test_case import DojoTestCase + class TestNetsparkerParser(DojoTestCase): diff --git a/unittests/tools/test_neuvector_compliance_parser.py b/unittests/tools/test_neuvector_compliance_parser.py index d5d22e6f2f..0d41a19a99 100644 --- a/unittests/tools/test_neuvector_compliance_parser.py +++ b/unittests/tools/test_neuvector_compliance_parser.py @@ -1,8 +1,10 @@ from os import path -from ..dojo_test_case import DojoTestCase + from dojo.models import Test from dojo.tools.neuvector_compliance.parser import NeuVectorComplianceParser +from ..dojo_test_case import DojoTestCase + class TestNeuVectorComplianceParser(DojoTestCase): def test_parse_file_with_no_vuln(self): diff --git a/unittests/tools/test_neuvector_parser.py b/unittests/tools/test_neuvector_parser.py index ef7366d682..ecb2faba98 100644 --- a/unittests/tools/test_neuvector_parser.py +++ b/unittests/tools/test_neuvector_parser.py @@ -1,8 +1,10 @@ from os import path -from ..dojo_test_case import DojoTestCase + from dojo.models import Test from dojo.tools.neuvector.parser import NeuVectorParser +from ..dojo_test_case import DojoTestCase + class TestNeuVectorParser(DojoTestCase): def test_parse_file_with_no_vuln(self): diff --git a/unittests/tools/test_nexpose_parser.py b/unittests/tools/test_nexpose_parser.py index c7d6554cbe..7b5afc112e 100644 --- a/unittests/tools/test_nexpose_parser.py +++ b/unittests/tools/test_nexpose_parser.py @@ -1,9 +1,11 @@ import datetime + from django.test import override_settings -from ..dojo_test_case import DojoTestCase +from dojo.models import Engagement, Product, Test from dojo.tools.nexpose.parser import NexposeParser -from dojo.models import Test, Engagement, Product + +from ..dojo_test_case import DojoTestCase class TestNexposeParser(DojoTestCase): diff --git a/unittests/tools/test_nikto_parser.py b/unittests/tools/test_nikto_parser.py index 69be4b0b3a..9524fab549 100644 --- a/unittests/tools/test_nikto_parser.py +++ b/unittests/tools/test_nikto_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase +from dojo.models import Engagement, Product, Test from dojo.tools.nikto.parser import NiktoParser -from dojo.models import Test, Engagement, Product + +from ..dojo_test_case import DojoTestCase class TestNiktoParser(DojoTestCase): diff --git a/unittests/tools/test_nmap_parser.py b/unittests/tools/test_nmap_parser.py index 4cc6297642..a78474d89a 100644 --- a/unittests/tools/test_nmap_parser.py +++ b/unittests/tools/test_nmap_parser.py @@ -1,9 +1,10 @@ import datetime -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.nmap.parser import NmapParser +from ..dojo_test_case import DojoTestCase + class TestNmapParser(DojoTestCase): diff --git a/unittests/tools/test_noseyparker_parser.py b/unittests/tools/test_noseyparker_parser.py index 0e2c224b57..4e98bbc04f 100644 --- a/unittests/tools/test_noseyparker_parser.py +++ b/unittests/tools/test_noseyparker_parser.py @@ -1,6 +1,7 @@ from django.test import TestCase -from dojo.tools.noseyparker.parser import NoseyParkerParser + from dojo.models import Test +from dojo.tools.noseyparker.parser import NoseyParkerParser class TestNoseyParkerParser(TestCase): diff --git a/unittests/tools/test_npm_audit_7_plus_parser.py b/unittests/tools/test_npm_audit_7_plus_parser.py index cf1cb339e7..1c3c888edf 100644 --- a/unittests/tools/test_npm_audit_7_plus_parser.py +++ b/unittests/tools/test_npm_audit_7_plus_parser.py @@ -1,7 +1,9 @@ from os import path -from ..dojo_test_case import DojoTestCase -from dojo.tools.npm_audit_7_plus.parser import NpmAudit7PlusParser + from dojo.models import Test +from dojo.tools.npm_audit_7_plus.parser import NpmAudit7PlusParser + +from ..dojo_test_case import DojoTestCase class TestNpmAudit7PlusParser(DojoTestCase): diff --git a/unittests/tools/test_npm_audit_parser.py b/unittests/tools/test_npm_audit_parser.py index c716d53ad9..fac2473b51 100644 --- a/unittests/tools/test_npm_audit_parser.py +++ b/unittests/tools/test_npm_audit_parser.py @@ -1,7 +1,9 @@ from os import path -from ..dojo_test_case import DojoTestCase -from dojo.tools.npm_audit.parser import NpmAuditParser, censor_path_hashes + from dojo.models import Test +from dojo.tools.npm_audit.parser import NpmAuditParser, censor_path_hashes + +from ..dojo_test_case import DojoTestCase class TestNpmAuditParser(DojoTestCase): diff --git a/unittests/tools/test_nsp_parser.py b/unittests/tools/test_nsp_parser.py index 469b0b117d..0901681343 100644 --- a/unittests/tools/test_nsp_parser.py +++ b/unittests/tools/test_nsp_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.nsp.parser import NspParser from dojo.models import Test +from dojo.tools.nsp.parser import NspParser + +from ..dojo_test_case import DojoTestCase class TestNspParser(DojoTestCase): diff --git a/unittests/tools/test_nuclei_parser.py b/unittests/tools/test_nuclei_parser.py index 3ffdbd2915..2ffde1fb02 100644 --- a/unittests/tools/test_nuclei_parser.py +++ b/unittests/tools/test_nuclei_parser.py @@ -1,9 +1,12 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.nuclei.parser import NucleiParser -from dojo.models import Test from datetime import datetime + from dateutil.tz import tzoffset +from dojo.models import Test +from dojo.tools.nuclei.parser import NucleiParser + +from ..dojo_test_case import DojoTestCase + class TestNucleiParser(DojoTestCase): diff --git a/unittests/tools/test_openscap_parser.py b/unittests/tools/test_openscap_parser.py index 013ad9970e..5e765b6986 100644 --- a/unittests/tools/test_openscap_parser.py +++ b/unittests/tools/test_openscap_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.openscap.parser import OpenscapParser from dojo.models import Test +from dojo.tools.openscap.parser import OpenscapParser + +from ..dojo_test_case import DojoTestCase class TestOpenscapParser(DojoTestCase): diff --git a/unittests/tools/test_openvas_parser.py b/unittests/tools/test_openvas_parser.py index 6f266b87b0..edefaac12f 100644 --- a/unittests/tools/test_openvas_parser.py +++ b/unittests/tools/test_openvas_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase +from dojo.models import Engagement, Product, Test from dojo.tools.openvas.parser import OpenVASParser -from dojo.models import Test, Engagement, Product + +from ..dojo_test_case import DojoTestCase class TestOpenVASParser(DojoTestCase): diff --git a/unittests/tools/test_ort_parser.py b/unittests/tools/test_ort_parser.py index 1057c7deb8..823c611774 100644 --- a/unittests/tools/test_ort_parser.py +++ b/unittests/tools/test_ort_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.ort.parser import OrtParser from dojo.models import Test +from dojo.tools.ort.parser import OrtParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestOrtParser(DojoTestCase): diff --git a/unittests/tools/test_ossindex_devaudit_parser.py b/unittests/tools/test_ossindex_devaudit_parser.py index 841730dbf8..e6eb38f4de 100644 --- a/unittests/tools/test_ossindex_devaudit_parser.py +++ b/unittests/tools/test_ossindex_devaudit_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.ossindex_devaudit.parser import OssIndexDevauditParser from dojo.models import Test +from dojo.tools.ossindex_devaudit.parser import OssIndexDevauditParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestOssIndexDevauditParser(DojoTestCase): diff --git a/unittests/tools/test_osv_scanner_parser.py b/unittests/tools/test_osv_scanner_parser.py index bde834cc17..46ba8077dd 100644 --- a/unittests/tools/test_osv_scanner_parser.py +++ b/unittests/tools/test_osv_scanner_parser.py @@ -1,7 +1,9 @@ from os import path -from ..dojo_test_case import DojoTestCase -from dojo.tools.osv_scanner.parser import OSVScannerParser + from dojo.models import Test +from dojo.tools.osv_scanner.parser import OSVScannerParser + +from ..dojo_test_case import DojoTestCase class TestOSVScannerParser(DojoTestCase): diff --git a/unittests/tools/test_outpost24_parser.py b/unittests/tools/test_outpost24_parser.py index 994977460c..1e8ca61b91 100644 --- a/unittests/tools/test_outpost24_parser.py +++ b/unittests/tools/test_outpost24_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.outpost24.parser import Outpost24Parser from dojo.models import Test +from dojo.tools.outpost24.parser import Outpost24Parser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestOutpost24Parser(DojoTestCase): diff --git a/unittests/tools/test_php_security_audit_v2_parser.py b/unittests/tools/test_php_security_audit_v2_parser.py index c648acf741..e684fabcc9 100644 --- a/unittests/tools/test_php_security_audit_v2_parser.py +++ b/unittests/tools/test_php_security_audit_v2_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.php_security_audit_v2.parser import PhpSecurityAuditV2Parser from dojo.models import Test +from dojo.tools.php_security_audit_v2.parser import PhpSecurityAuditV2Parser + +from ..dojo_test_case import DojoTestCase class TestPhpSecurityAuditV2ParserParser(DojoTestCase): diff --git a/unittests/tools/test_php_symfony_security_check_parser.py b/unittests/tools/test_php_symfony_security_check_parser.py index e556d8144d..b191038d98 100644 --- a/unittests/tools/test_php_symfony_security_check_parser.py +++ b/unittests/tools/test_php_symfony_security_check_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.php_symfony_security_check.parser import PhpSymfonySecurityCheckParser from dojo.models import Test +from dojo.tools.php_symfony_security_check.parser import PhpSymfonySecurityCheckParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestPhpSymfonySecurityCheckerParser(DojoTestCase): diff --git a/unittests/tools/test_pip_audit_parser.py b/unittests/tools/test_pip_audit_parser.py index 237945cfc6..2f765ca9c3 100644 --- a/unittests/tools/test_pip_audit_parser.py +++ b/unittests/tools/test_pip_audit_parser.py @@ -1,8 +1,8 @@ -from ..dojo_test_case import DojoTestCase - from dojo.models import Test from dojo.tools.pip_audit.parser import PipAuditParser +from ..dojo_test_case import DojoTestCase + class TestPipAuditParser(DojoTestCase): diff --git a/unittests/tools/test_pmd_parser.py b/unittests/tools/test_pmd_parser.py index 75ecb05083..e876d2c700 100644 --- a/unittests/tools/test_pmd_parser.py +++ b/unittests/tools/test_pmd_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.pmd.parser import PmdParser from dojo.models import Test +from dojo.tools.pmd.parser import PmdParser + +from ..dojo_test_case import DojoTestCase class TestPMDParser(DojoTestCase): diff --git a/unittests/tools/test_popeye_parser.py b/unittests/tools/test_popeye_parser.py index df690532d4..ee029855df 100644 --- a/unittests/tools/test_popeye_parser.py +++ b/unittests/tools/test_popeye_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.popeye.parser import PopeyeParser from dojo.models import Test +from dojo.tools.popeye.parser import PopeyeParser + +from ..dojo_test_case import DojoTestCase class TestPopeyeParser(DojoTestCase): diff --git a/unittests/tools/test_pwn_sast_parser.py b/unittests/tools/test_pwn_sast_parser.py index 7183169bab..e24bdaaca3 100644 --- a/unittests/tools/test_pwn_sast_parser.py +++ b/unittests/tools/test_pwn_sast_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.pwn_sast.parser import PWNSASTParser from dojo.models import Test +from dojo.tools.pwn_sast.parser import PWNSASTParser + +from ..dojo_test_case import DojoTestCase class TestPWNSASTParser(DojoTestCase): diff --git a/unittests/tools/test_qualys_infrascan_webgui_parser.py b/unittests/tools/test_qualys_infrascan_webgui_parser.py index 15dfa12d76..9605e814c3 100644 --- a/unittests/tools/test_qualys_infrascan_webgui_parser.py +++ b/unittests/tools/test_qualys_infrascan_webgui_parser.py @@ -1,11 +1,11 @@ from datetime import datetime import pytz -from ..dojo_test_case import DojoTestCase, get_unit_tests_path from dojo.models import Test -from dojo.tools.qualys_infrascan_webgui.parser import \ - QualysInfrascanWebguiParser +from dojo.tools.qualys_infrascan_webgui.parser import QualysInfrascanWebguiParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestQualysInfrascanWebguiParser(DojoTestCase): diff --git a/unittests/tools/test_qualys_parser.py b/unittests/tools/test_qualys_parser.py index df22041ba1..4a691485b2 100644 --- a/unittests/tools/test_qualys_parser.py +++ b/unittests/tools/test_qualys_parser.py @@ -1,10 +1,12 @@ import datetime + from django.test import override_settings -from ..dojo_test_case import DojoTestCase, get_unit_tests_path from dojo.models import Test from dojo.tools.qualys.parser import QualysParser +from ..dojo_test_case import DojoTestCase, get_unit_tests_path + class TestQualysParser(DojoTestCase): diff --git a/unittests/tools/test_qualys_webapp_parser.py b/unittests/tools/test_qualys_webapp_parser.py index d14945ca52..2cee4ad4ae 100644 --- a/unittests/tools/test_qualys_webapp_parser.py +++ b/unittests/tools/test_qualys_webapp_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.qualys_webapp.parser import QualysWebAppParser from dojo.models import Test +from dojo.tools.qualys_webapp.parser import QualysWebAppParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestQualysWebAppParser(DojoTestCase): diff --git a/unittests/tools/test_redhatsatellite_parser.py b/unittests/tools/test_redhatsatellite_parser.py index 197dbad657..2de519f5ff 100644 --- a/unittests/tools/test_redhatsatellite_parser.py +++ b/unittests/tools/test_redhatsatellite_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.redhatsatellite.parser import RedHatSatelliteParser from dojo.models import Test +from dojo.tools.redhatsatellite.parser import RedHatSatelliteParser + +from ..dojo_test_case import DojoTestCase class TestRedHatSatelliteParser(DojoTestCase): diff --git a/unittests/tools/test_retirejs_parser.py b/unittests/tools/test_retirejs_parser.py index eb56ba0648..2802d3667a 100644 --- a/unittests/tools/test_retirejs_parser.py +++ b/unittests/tools/test_retirejs_parser.py @@ -1,7 +1,8 @@ -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.retirejs.parser import RetireJsParser +from ..dojo_test_case import DojoTestCase + class TestRetireJsParser(DojoTestCase): def test_parse(self): diff --git a/unittests/tools/test_risk_recon_parser.py b/unittests/tools/test_risk_recon_parser.py index 9c402b98af..839c6cf80d 100644 --- a/unittests/tools/test_risk_recon_parser.py +++ b/unittests/tools/test_risk_recon_parser.py @@ -1,9 +1,10 @@ import datetime -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.risk_recon.parser import RiskReconParser +from ..dojo_test_case import DojoTestCase + class TestRiskReconAPIParser(DojoTestCase): diff --git a/unittests/tools/test_rubocop_parser.py b/unittests/tools/test_rubocop_parser.py index bcd86468c8..1dba608f01 100644 --- a/unittests/tools/test_rubocop_parser.py +++ b/unittests/tools/test_rubocop_parser.py @@ -1,8 +1,8 @@ -from ..dojo_test_case import DojoTestCase - from dojo.models import Test from dojo.tools.rubocop.parser import RubocopParser +from ..dojo_test_case import DojoTestCase + class TestRubocopParser(DojoTestCase): def test_parser_empty(self): diff --git a/unittests/tools/test_rusty_hog_parser.py b/unittests/tools/test_rusty_hog_parser.py index 9d73d3e92b..472e15b822 100644 --- a/unittests/tools/test_rusty_hog_parser.py +++ b/unittests/tools/test_rusty_hog_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.rusty_hog.parser import RustyhogParser from dojo.models import Test +from dojo.tools.rusty_hog.parser import RustyhogParser + +from ..dojo_test_case import DojoTestCase class TestRustyhogParser(DojoTestCase): diff --git a/unittests/tools/test_scantist_parser.py b/unittests/tools/test_scantist_parser.py index 6656e09dd2..befdf404c8 100644 --- a/unittests/tools/test_scantist_parser.py +++ b/unittests/tools/test_scantist_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.scantist.parser import ScantistParser from dojo.models import Test +from dojo.tools.scantist.parser import ScantistParser + +from ..dojo_test_case import DojoTestCase class TestScantistParser(DojoTestCase): diff --git a/unittests/tools/test_scout_suite_parser.py b/unittests/tools/test_scout_suite_parser.py index 9ad71dfc2a..40e6761f84 100644 --- a/unittests/tools/test_scout_suite_parser.py +++ b/unittests/tools/test_scout_suite_parser.py @@ -1,9 +1,10 @@ import datetime -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.scout_suite.parser import ScoutSuiteParser +from ..dojo_test_case import DojoTestCase + class TestScoutSuiteParser(DojoTestCase): def test_scout_suite_parser_with_no_vuln_has_no_findings(self): diff --git a/unittests/tools/test_semgrep_parser.py b/unittests/tools/test_semgrep_parser.py index ed98b3a431..27a6d1b755 100644 --- a/unittests/tools/test_semgrep_parser.py +++ b/unittests/tools/test_semgrep_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.semgrep.parser import SemgrepParser from dojo.models import Test +from dojo.tools.semgrep.parser import SemgrepParser + +from ..dojo_test_case import DojoTestCase class TestSemgrepParser(DojoTestCase): diff --git a/unittests/tools/test_skf_parser.py b/unittests/tools/test_skf_parser.py index a9222893a8..b39ac83257 100644 --- a/unittests/tools/test_skf_parser.py +++ b/unittests/tools/test_skf_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.skf.parser import SKFParser from dojo.models import Test +from dojo.tools.skf.parser import SKFParser + +from ..dojo_test_case import DojoTestCase class TestSkfParser(DojoTestCase): diff --git a/unittests/tools/test_snyk_code_parser.py b/unittests/tools/test_snyk_code_parser.py index 4d636e72e9..37524acefa 100644 --- a/unittests/tools/test_snyk_code_parser.py +++ b/unittests/tools/test_snyk_code_parser.py @@ -1,7 +1,8 @@ -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.snyk_code.parser import SnykCodeParser +from ..dojo_test_case import DojoTestCase + class TestSnykCodeParser(DojoTestCase): diff --git a/unittests/tools/test_snyk_parser.py b/unittests/tools/test_snyk_parser.py index ef41469e81..d79dc0db0d 100644 --- a/unittests/tools/test_snyk_parser.py +++ b/unittests/tools/test_snyk_parser.py @@ -1,7 +1,8 @@ -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.snyk.parser import SnykParser +from ..dojo_test_case import DojoTestCase + class TestSnykParser(DojoTestCase): diff --git a/unittests/tools/test_solar_appscreener_parser.py b/unittests/tools/test_solar_appscreener_parser.py index 5268b3621e..1d4c38c7c0 100644 --- a/unittests/tools/test_solar_appscreener_parser.py +++ b/unittests/tools/test_solar_appscreener_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.solar_appscreener.parser import SolarAppscreenerParser from dojo.models import Test +from dojo.tools.solar_appscreener.parser import SolarAppscreenerParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestSolarAppscreenerParser(DojoTestCase): diff --git a/unittests/tools/test_sonarqube_parser.py b/unittests/tools/test_sonarqube_parser.py index 29111368cd..56f1c818a0 100644 --- a/unittests/tools/test_sonarqube_parser.py +++ b/unittests/tools/test_sonarqube_parser.py @@ -1,8 +1,8 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path - -from dojo.models import Test, Engagement, Product +from dojo.models import Engagement, Product, Test from dojo.tools.sonarqube.parser import SonarQubeParser +from ..dojo_test_case import DojoTestCase, get_unit_tests_path + class TestSonarQubeParser(DojoTestCase): # comment out to get full diff with big reports diff --git a/unittests/tools/test_sonatype_parser.py b/unittests/tools/test_sonatype_parser.py index 48e4b4b056..6bf57e041c 100644 --- a/unittests/tools/test_sonatype_parser.py +++ b/unittests/tools/test_sonatype_parser.py @@ -1,7 +1,8 @@ -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.sonatype.parser import SonatypeParser +from ..dojo_test_case import DojoTestCase + class TestSonatypeParser(DojoTestCase): def test_parse_file_with_two_vulns(self): diff --git a/unittests/tools/test_spotbugs_parser.py b/unittests/tools/test_spotbugs_parser.py index 153fca7666..b105ebb20a 100644 --- a/unittests/tools/test_spotbugs_parser.py +++ b/unittests/tools/test_spotbugs_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.spotbugs.parser import SpotbugsParser from dojo.models import Test +from dojo.tools.spotbugs.parser import SpotbugsParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestSpotbugsParser(DojoTestCase): diff --git a/unittests/tools/test_ssh_audit_parser.py b/unittests/tools/test_ssh_audit_parser.py index a211fa5423..a29d36c1a9 100644 --- a/unittests/tools/test_ssh_audit_parser.py +++ b/unittests/tools/test_ssh_audit_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.ssh_audit.parser import SSHAuditParser from dojo.models import Test +from dojo.tools.ssh_audit.parser import SSHAuditParser + +from ..dojo_test_case import DojoTestCase class TestSSHAuditParser(DojoTestCase): diff --git a/unittests/tools/test_ssl_labs_parser.py b/unittests/tools/test_ssl_labs_parser.py index 807dc04991..b28d647dd7 100644 --- a/unittests/tools/test_ssl_labs_parser.py +++ b/unittests/tools/test_ssl_labs_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.ssl_labs.parser import SslLabsParser from dojo.models import Test +from dojo.tools.ssl_labs.parser import SslLabsParser + +from ..dojo_test_case import DojoTestCase class TestSslLabsParser(DojoTestCase): diff --git a/unittests/tools/test_sslscan_parser.py b/unittests/tools/test_sslscan_parser.py index 4c42518f66..b685178247 100644 --- a/unittests/tools/test_sslscan_parser.py +++ b/unittests/tools/test_sslscan_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.sslscan.parser import SslscanParser from dojo.models import Test +from dojo.tools.sslscan.parser import SslscanParser + +from ..dojo_test_case import DojoTestCase class TestSslscanParser(DojoTestCase): diff --git a/unittests/tools/test_sslyze_parser.py b/unittests/tools/test_sslyze_parser.py index 7d8f3dcad2..4493d4d180 100644 --- a/unittests/tools/test_sslyze_parser.py +++ b/unittests/tools/test_sslyze_parser.py @@ -1,8 +1,9 @@ from os import path -from ..dojo_test_case import DojoTestCase -from dojo.tools.sslyze.parser import SslyzeParser from dojo.models import Test +from dojo.tools.sslyze.parser import SslyzeParser + +from ..dojo_test_case import DojoTestCase class TestSslyzeJSONParser(DojoTestCase): diff --git a/unittests/tools/test_stackhawk_parser.py b/unittests/tools/test_stackhawk_parser.py index 6a7b3af359..64151495da 100644 --- a/unittests/tools/test_stackhawk_parser.py +++ b/unittests/tools/test_stackhawk_parser.py @@ -1,7 +1,7 @@ import datetime +from dojo.models import Finding, Test from dojo.tools.stackhawk.parser import StackHawkParser -from dojo.models import Test, Finding from unittests.dojo_test_case import DojoTestCase diff --git a/unittests/tools/test_sysdig_reports_parser.py b/unittests/tools/test_sysdig_reports_parser.py index d0f9c9ae8e..00979f66e8 100644 --- a/unittests/tools/test_sysdig_reports_parser.py +++ b/unittests/tools/test_sysdig_reports_parser.py @@ -1,6 +1,7 @@ from django.test import TestCase -from dojo.tools.sysdig_reports.parser import SysdigReportsParser + from dojo.models import Test +from dojo.tools.sysdig_reports.parser import SysdigReportsParser class TestSysdigParser(TestCase): diff --git a/unittests/tools/test_tenable_parser.py b/unittests/tools/test_tenable_parser.py index 4d55d4bb78..c8468e3222 100644 --- a/unittests/tools/test_tenable_parser.py +++ b/unittests/tools/test_tenable_parser.py @@ -1,7 +1,9 @@ from os import path -from ..dojo_test_case import DojoTestCase + +from dojo.models import Engagement, Finding, Product, Test from dojo.tools.tenable.parser import TenableParser -from dojo.models import Finding, Test, Engagement, Product + +from ..dojo_test_case import DojoTestCase class TestTenableParser(DojoTestCase): diff --git a/unittests/tools/test_terrascan_parser.py b/unittests/tools/test_terrascan_parser.py index ee6605da6d..4fa717fccd 100644 --- a/unittests/tools/test_terrascan_parser.py +++ b/unittests/tools/test_terrascan_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.terrascan.parser import TerrascanParser from dojo.models import Test +from dojo.tools.terrascan.parser import TerrascanParser + +from ..dojo_test_case import DojoTestCase class TestTerrascanParser(DojoTestCase): diff --git a/unittests/tools/test_testssl_parser.py b/unittests/tools/test_testssl_parser.py index 9c302cf3f1..785c1b51f7 100644 --- a/unittests/tools/test_testssl_parser.py +++ b/unittests/tools/test_testssl_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.testssl.parser import TestsslParser from dojo.models import Test +from dojo.tools.testssl.parser import TestsslParser + +from ..dojo_test_case import DojoTestCase class TestTestsslParser(DojoTestCase): diff --git a/unittests/tools/test_tfsec_parser.py b/unittests/tools/test_tfsec_parser.py index 50d7992433..f3974c20d0 100644 --- a/unittests/tools/test_tfsec_parser.py +++ b/unittests/tools/test_tfsec_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.tfsec.parser import TFSecParser from dojo.models import Test +from dojo.tools.tfsec.parser import TFSecParser + +from ..dojo_test_case import DojoTestCase class TestTFSecParser(DojoTestCase): diff --git a/unittests/tools/test_trivy_operator_parser.py b/unittests/tools/test_trivy_operator_parser.py index 4307385dab..705a9bae29 100644 --- a/unittests/tools/test_trivy_operator_parser.py +++ b/unittests/tools/test_trivy_operator_parser.py @@ -1,8 +1,9 @@ import os.path -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.trivy_operator.parser import TrivyOperatorParser from dojo.models import Test +from dojo.tools.trivy_operator.parser import TrivyOperatorParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path def sample_path(file_name): diff --git a/unittests/tools/test_trivy_parser.py b/unittests/tools/test_trivy_parser.py index 914b72cddb..6e53d9b756 100644 --- a/unittests/tools/test_trivy_parser.py +++ b/unittests/tools/test_trivy_parser.py @@ -1,9 +1,10 @@ import os.path import re -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.trivy.parser import TrivyParser from dojo.models import Test +from dojo.tools.trivy.parser import TrivyParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path def sample_path(file_name): diff --git a/unittests/tools/test_trufflehog3_parser.py b/unittests/tools/test_trufflehog3_parser.py index f1b84feea9..25215ada85 100644 --- a/unittests/tools/test_trufflehog3_parser.py +++ b/unittests/tools/test_trufflehog3_parser.py @@ -1,8 +1,10 @@ -import os.path import datetime -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.trufflehog3.parser import TruffleHog3Parser +import os.path + from dojo.models import Test +from dojo.tools.trufflehog3.parser import TruffleHog3Parser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path def sample_path(file_name): diff --git a/unittests/tools/test_trufflehog_parser.py b/unittests/tools/test_trufflehog_parser.py index f9c4de2f3e..a3820ab458 100644 --- a/unittests/tools/test_trufflehog_parser.py +++ b/unittests/tools/test_trufflehog_parser.py @@ -1,8 +1,9 @@ import os.path -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.trufflehog.parser import TruffleHogParser from dojo.models import Test +from dojo.tools.trufflehog.parser import TruffleHogParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path def sample_path(file_name): diff --git a/unittests/tools/test_trustwave_fusion_api_parser.py b/unittests/tools/test_trustwave_fusion_api_parser.py index ebdd02156f..f09272e445 100644 --- a/unittests/tools/test_trustwave_fusion_api_parser.py +++ b/unittests/tools/test_trustwave_fusion_api_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.trustwave_fusion_api.parser import TrustwaveFusionAPIParser from dojo.models import Test +from dojo.tools.trustwave_fusion_api.parser import TrustwaveFusionAPIParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestTrustwaveFusionAPIParser(DojoTestCase): diff --git a/unittests/tools/test_trustwave_parser.py b/unittests/tools/test_trustwave_parser.py index 5ab1627088..328213743b 100644 --- a/unittests/tools/test_trustwave_parser.py +++ b/unittests/tools/test_trustwave_parser.py @@ -1,8 +1,9 @@ import os.path -from ..dojo_test_case import DojoTestCase, get_unit_tests_path +from dojo.models import Engagement, Product, Test from dojo.tools.trustwave.parser import TrustwaveParser -from dojo.models import Test, Engagement, Product + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path def sample_path(file_name): diff --git a/unittests/tools/test_twistlock_parser.py b/unittests/tools/test_twistlock_parser.py index f03b74f344..e972b0700f 100644 --- a/unittests/tools/test_twistlock_parser.py +++ b/unittests/tools/test_twistlock_parser.py @@ -1,8 +1,10 @@ from os import path -from ..dojo_test_case import DojoTestCase + from dojo.models import Test from dojo.tools.twistlock.parser import TwistlockParser +from ..dojo_test_case import DojoTestCase + class TestTwistlockParser(DojoTestCase): def test_parse_file_with_no_vuln(self): diff --git a/unittests/tools/test_vcg_parser.py b/unittests/tools/test_vcg_parser.py index 0051c4ff8e..59c5a7bc1e 100644 --- a/unittests/tools/test_vcg_parser.py +++ b/unittests/tools/test_vcg_parser.py @@ -1,13 +1,12 @@ -import io import csv +import io from defusedxml import ElementTree -from ..dojo_test_case import DojoTestCase from dojo.models import Test -from dojo.tools.vcg.parser import VCGCsvParser -from dojo.tools.vcg.parser import VCGParser -from dojo.tools.vcg.parser import VCGXmlParser +from dojo.tools.vcg.parser import VCGCsvParser, VCGParser, VCGXmlParser + +from ..dojo_test_case import DojoTestCase class TestFile: diff --git a/unittests/tools/test_veracode_parser.py b/unittests/tools/test_veracode_parser.py index 005cf3dbce..1149daddba 100644 --- a/unittests/tools/test_veracode_parser.py +++ b/unittests/tools/test_veracode_parser.py @@ -1,9 +1,11 @@ import datetime + from django.test import override_settings -from ..dojo_test_case import DojoTestCase +from dojo.models import Endpoint, Engagement, Product, Product_Type, Test from dojo.tools.veracode.parser import VeracodeParser -from dojo.models import Test, Product_Type, Product, Engagement, Endpoint + +from ..dojo_test_case import DojoTestCase class TestVeracodeScannerParser(DojoTestCase): diff --git a/unittests/tools/test_veracode_sca_parser.py b/unittests/tools/test_veracode_sca_parser.py index 6820cf0490..fdcfa0b60f 100644 --- a/unittests/tools/test_veracode_sca_parser.py +++ b/unittests/tools/test_veracode_sca_parser.py @@ -1,11 +1,12 @@ import datetime + +from dateutil.tz import UTC from django.test import override_settings -from ..dojo_test_case import DojoTestCase -from dojo.tools.veracode_sca.parser import VeracodeScaParser from dojo.models import Test +from dojo.tools.veracode_sca.parser import VeracodeScaParser -from dateutil.tz import UTC +from ..dojo_test_case import DojoTestCase class TestVeracodeScaScannerParser(DojoTestCase): diff --git a/unittests/tools/test_wapiti_parser.py b/unittests/tools/test_wapiti_parser.py index 5c4373aa7d..3b5bc74235 100644 --- a/unittests/tools/test_wapiti_parser.py +++ b/unittests/tools/test_wapiti_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.wapiti.parser import WapitiParser from dojo.models import Test +from dojo.tools.wapiti.parser import WapitiParser + +from ..dojo_test_case import DojoTestCase class TestWapitiParser(DojoTestCase): diff --git a/unittests/tools/test_wazuh_parser.py b/unittests/tools/test_wazuh_parser.py index 4f4bcfbb81..1e881e1d02 100644 --- a/unittests/tools/test_wazuh_parser.py +++ b/unittests/tools/test_wazuh_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.wazuh.parser import WazuhParser from dojo.models import Test +from dojo.tools.wazuh.parser import WazuhParser + +from ..dojo_test_case import DojoTestCase class TestWazuhParser(DojoTestCase): diff --git a/unittests/tools/test_wfuzz_parser.py b/unittests/tools/test_wfuzz_parser.py index 58f0b12dcb..e9f1e69411 100644 --- a/unittests/tools/test_wfuzz_parser.py +++ b/unittests/tools/test_wfuzz_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.wfuzz.parser import WFuzzParser from dojo.models import Test +from dojo.tools.wfuzz.parser import WFuzzParser + +from ..dojo_test_case import DojoTestCase class TestWFuzzParser(DojoTestCase): diff --git a/unittests/tools/test_whispers_parser.py b/unittests/tools/test_whispers_parser.py index 9a2da18dde..d158bf311c 100644 --- a/unittests/tools/test_whispers_parser.py +++ b/unittests/tools/test_whispers_parser.py @@ -1,6 +1,7 @@ from django.test import TestCase -from dojo.tools.whispers.parser import WhispersParser + from dojo.models import Test +from dojo.tools.whispers.parser import WhispersParser class TestWhispersParser(TestCase): diff --git a/unittests/tools/test_whitehat_sentinel_parser.py b/unittests/tools/test_whitehat_sentinel_parser.py index e5b6b68533..65e91fc23b 100644 --- a/unittests/tools/test_whitehat_sentinel_parser.py +++ b/unittests/tools/test_whitehat_sentinel_parser.py @@ -1,8 +1,8 @@ -from ..dojo_test_case import DojoTestCase - from dojo.models import Test from dojo.tools.whitehat_sentinel.parser import WhiteHatSentinelParser +from ..dojo_test_case import DojoTestCase + class TestWhiteHatSentinelParser(DojoTestCase): diff --git a/unittests/tools/test_wiz_parser.py b/unittests/tools/test_wiz_parser.py index 5b1c91f733..040d7791e1 100644 --- a/unittests/tools/test_wiz_parser.py +++ b/unittests/tools/test_wiz_parser.py @@ -1,7 +1,8 @@ -from ..dojo_test_case import DojoTestCase from dojo.models import Test from dojo.tools.wiz.parser import WizParser +from ..dojo_test_case import DojoTestCase + class TestWizParser(DojoTestCase): def test_no_findings(self): diff --git a/unittests/tools/test_wpscan_parser.py b/unittests/tools/test_wpscan_parser.py index e2dca4b5c8..c3932ebe75 100644 --- a/unittests/tools/test_wpscan_parser.py +++ b/unittests/tools/test_wpscan_parser.py @@ -1,10 +1,10 @@ import datetime -from ..dojo_test_case import DojoTestCase - from dojo.models import Test from dojo.tools.wpscan.parser import WpscanParser +from ..dojo_test_case import DojoTestCase + class TestWpscanParser(DojoTestCase): diff --git a/unittests/tools/test_xanitizer_parser.py b/unittests/tools/test_xanitizer_parser.py index 10a6135fd8..8b46a61dea 100644 --- a/unittests/tools/test_xanitizer_parser.py +++ b/unittests/tools/test_xanitizer_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase, get_unit_tests_path -from dojo.tools.xanitizer.parser import XanitizerParser from dojo.models import Test +from dojo.tools.xanitizer.parser import XanitizerParser + +from ..dojo_test_case import DojoTestCase, get_unit_tests_path class TestXanitizerParser(DojoTestCase): diff --git a/unittests/tools/test_yarn_audit_parser.py b/unittests/tools/test_yarn_audit_parser.py index b97b7daacf..3a3c587fdf 100644 --- a/unittests/tools/test_yarn_audit_parser.py +++ b/unittests/tools/test_yarn_audit_parser.py @@ -1,6 +1,7 @@ -from ..dojo_test_case import DojoTestCase -from dojo.tools.yarn_audit.parser import YarnAuditParser from dojo.models import Engagement, Product, Test +from dojo.tools.yarn_audit.parser import YarnAuditParser + +from ..dojo_test_case import DojoTestCase class TestYarnAuditParser(DojoTestCase): diff --git a/unittests/tools/test_zap_parser.py b/unittests/tools/test_zap_parser.py index b32ac22f46..c7b738155c 100644 --- a/unittests/tools/test_zap_parser.py +++ b/unittests/tools/test_zap_parser.py @@ -1,7 +1,8 @@ -from ..dojo_test_case import DojoTestCase -from dojo.models import Test, Finding +from dojo.models import Finding, Test from dojo.tools.zap.parser import ZapParser +from ..dojo_test_case import DojoTestCase + class TestZapParser(DojoTestCase): def test_parse_no_findings(self): diff --git a/wsgi.py b/wsgi.py index fb18848188..709fc9422f 100644 --- a/wsgi.py +++ b/wsgi.py @@ -14,6 +14,7 @@ """ import os + from django.core.wsgi import get_wsgi_application # We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks From 71811c7bff0b9aa65cad0c3811cfb02f4a3fb7ce Mon Sep 17 00:00:00 2001 From: eu-david <157360726+eu-david@users.noreply.github.com> Date: Tue, 30 Apr 2024 22:51:53 +0200 Subject: [PATCH 106/138] Add support for more GIT SCMs in finding view for the finding URL (#9710) * Add support for more GIT SCMs * fix flake8 issue * docs: added other supported SCM to the documentation --------- Co-authored-by: Eugeniu David --- .../integrations/source-code-repositories.md | 4 +- dojo/models.py | 53 +++++++------------ unittests/test_finding_model.py | 47 ++++++++++++++++ 3 files changed, 68 insertions(+), 36 deletions(-) diff --git a/docs/content/en/integrations/source-code-repositories.md b/docs/content/en/integrations/source-code-repositories.md index 7b7f5f0467..99f5d386b2 100644 --- a/docs/content/en/integrations/source-code-repositories.md +++ b/docs/content/en/integrations/source-code-repositories.md @@ -24,7 +24,7 @@ For Interactive Engagement it needs to be the URL including the branch: For CI/CD Engagement, where user could set commit hash, branch/tag and code line it should look like examples below: - for GitHub - like https://github.com/DefectDojo/django-DefectDojo - for GitLab - like https://gitlab.com/gitlab-org/gitlab -- for public BitBucket - like https://bitbucket.org/some-user/some-project.git (like git clone url) +- for public BitBucket, Gitea and Codeberg - like https://bitbucket.org/some-user/some-project.git (like git clone url) - for standalone/onpremise BitBucket https://bb.example.com/scm/some-project.git or https://bb.example.com/scm/some-user-name/some-repo.git for user public repo (like git clone url) If user does not set commit hash or branch/tag in appropriate fields of CI/CD Engagement edit form, the URL should look like in Interactive Engagement edit form. @@ -39,7 +39,7 @@ Product SCM type add: ![Product scm type](../../../static/images/product-scm-type_1.png) -Possible SCM types could be 'github', 'gitlab', 'bitbucket', 'bitbucket-standalone' or nothing (for default github). +Possible SCM types could be 'github', 'gitlab', 'bitbucket', 'bitbucket-standalone', 'gitea', 'codeberg' or nothing (for default github). ## Link in Finding diff --git a/dojo/models.py b/dojo/models.py index a5322c3313..7559e7a245 100644 --- a/dojo/models.py +++ b/dojo/models.py @@ -3159,33 +3159,34 @@ def get_scm_type(self): st = dojo_meta.value.strip() if st: return st.lower() - return 'github' + return '' - def bitbucket_public_prepare_scm_base_link(self, uri): - # bitbucket public (https://bitbucket.org) url template for browse is: - # https://bitbucket.org// + def scm_public_prepare_base_link(self, uri): + # scm public (https://scm-domain.org) url template for browse is: + # https://scm-domain.org// # but when you get repo url for git, its template is: - # https://bitbucket.org//.git + # https://scm-domain.org//.git # so to create browser url - git url should be recomposed like below: parts_uri = uri.split('.git') return parts_uri[0] - def bitbucket_public_prepare_scm_link(self, uri): + def git_public_prepare_scm_link(self, uri, scm_type): # if commit hash or branch/tag is set for engagement/test - # hash or branch/tag should be appended to base browser link + intermediate_path = '/blob/' if scm_type in ['github', 'gitlab'] else '/src/' - link = self.bitbucket_public_prepare_scm_base_link(uri) + link = self.scm_public_prepare_base_link(uri) if self.test.commit_hash: - link += '/src/' + self.test.commit_hash + '/' + self.file_path + link += intermediate_path + self.test.commit_hash + '/' + self.file_path elif self.test.engagement.commit_hash: - link += '/src/' + self.test.engagement.commit_hash + '/' + self.file_path + link += intermediate_path + self.test.engagement.commit_hash + '/' + self.file_path elif self.test.branch_tag: - link += '/src/' + self.test.branch_tag + '/' + self.file_path + link += intermediate_path + self.test.branch_tag + '/' + self.file_path elif self.test.engagement.branch_tag: - link += '/src/' + self.test.engagement.branch_tag + '/' + self.file_path + link += intermediate_path + self.test.engagement.branch_tag + '/' + self.file_path else: - link += '/src/master/' + self.file_path + link += intermediate_path + 'master/' + self.file_path return link @@ -3227,22 +3228,6 @@ def bitbucket_standalone_prepare_scm_link(self, uri): return link - def github_prepare_scm_link(self, uri): - link = uri - - if self.test.commit_hash: - link += '/blob/' + self.test.commit_hash + '/' + self.file_path - elif self.test.engagement.commit_hash: - link += '/blob/' + self.test.engagement.commit_hash + '/' + self.file_path - elif self.test.branch_tag: - link += '/blob/' + self.test.branch_tag + '/' + self.file_path - elif self.test.engagement.branch_tag: - link += '/blob/' + self.test.engagement.branch_tag + '/' + self.file_path - else: - link += '/' + self.file_path - - return link - def get_file_path_with_raw_link(self): if self.file_path is None: return None @@ -3250,12 +3235,12 @@ def get_file_path_with_raw_link(self): link = self.test.engagement.source_code_management_uri scm_type = self.get_scm_type() if (self.test.engagement.source_code_management_uri is not None): - if scm_type == 'github' or ("https://github.com/" in self.test.engagement.source_code_management_uri): - link = self.github_prepare_scm_link(link) - elif scm_type == 'bitbucket-standalone': + if scm_type == 'bitbucket-standalone': link = self.bitbucket_standalone_prepare_scm_link(link) - elif scm_type == 'bitbucket': - link = self.bitbucket_public_prepare_scm_link(link) + elif scm_type in ['github', 'gitlab', 'gitea', 'codeberg', 'bitbucket']: + link = self.git_public_prepare_scm_link(link, scm_type) + elif 'https://github.com/' in self.test.engagement.source_code_management_uri: + link = self.git_public_prepare_scm_link(link, 'github') else: link += '/' + self.file_path else: @@ -3263,7 +3248,7 @@ def get_file_path_with_raw_link(self): # than - add line part to browser url if self.line: - if scm_type == 'github' or scm_type == 'gitlab': + if scm_type in ['github', 'gitlab', 'gitea', 'codeberg'] or 'https://github.com/' in self.test.engagement.source_code_management_uri: link = link + '#L' + str(self.line) elif scm_type == 'bitbucket-standalone': link = link + '#' + str(self.line) diff --git a/unittests/test_finding_model.py b/unittests/test_finding_model.py index 6531cd3eec..9ab6936504 100644 --- a/unittests/test_finding_model.py +++ b/unittests/test_finding_model.py @@ -214,6 +214,53 @@ def test_get_file_path_with_link_and_source_code_management_uri_bitbucket_standa self.assertEqual('some-folder/some-file.ext', finding.get_file_path_with_link()) + def test_get_file_path_with_link_and_source_code_management_uri_gitea_or_codeberg_project_with_no_details_and_line(self): + # checks that for gitea and codeberg in custom field + # dojo makes correct url + + # create scm-type custom field with value "gitea" + product_type = self.create_product_type('test_product_type') + product = self.create_product(name='test_product', prod_type=product_type) + product_metadata = DojoMeta(product=product, name="scm-type", value="gitea") + product_metadata.save() + + # create finding with scm uri line + test = Test() + engagement = Engagement() + engagement.product = product + test.engagement = engagement + finding = Finding() + finding.test = test + finding.file_path = 'some-folder/some-file.ext' + finding.line = 5432 + + engagement.source_code_management_uri = 'https://bb.example.com/some-test-user/some-test-repo.git' + self.assertEqual('some-folder/some-file.ext', finding.get_file_path_with_link()) + + def test_get_file_path_with_link_and_source_code_management_uri_gitea_or_codeberg_project_with_commithash_and_line(self): + # checks that for gitea and codeberg in custom field and existing commit hash in finding + # dojo makes correct url + + # create scm-type custom field with value "gitea" + product_type = self.create_product_type('test_product_type') + product = self.create_product(name='test_product', prod_type=product_type) + product_metadata = DojoMeta(product=product, name="scm-type", value="gitea") + product_metadata.save() + + # create finding with scm uri and commit hash, branch and line + test = Test() + engagement = Engagement() + engagement.product = product + test.engagement = engagement + engagement.commit_hash = "some-commit-hash" + finding = Finding() + finding.test = test + finding.file_path = 'some-folder/some-file.ext' + finding.line = 5432 + + engagement.source_code_management_uri = 'https://bb.example.com/some-test-user/some-test-repo.git' + self.assertEqual('some-folder/some-file.ext', finding.get_file_path_with_link()) + def test_get_file_path_with_xss_attack(self): test = Test() engagement = Engagement() From e5c83b9ad95f5f846307013cf9c55043c624fc96 Mon Sep 17 00:00:00 2001 From: kiblik Date: Tue, 30 Apr 2024 23:29:54 +0200 Subject: [PATCH 107/138] Ruff: add and fix some of DJ rules (#9891) --- dojo/models.py | 512 ++++++++++++++++++++++++------------------------- ruff.toml | 1 + 2 files changed, 257 insertions(+), 256 deletions(-) diff --git a/dojo/models.py b/dojo/models.py index 7559e7a245..83ebef99c7 100644 --- a/dojo/models.py +++ b/dojo/models.py @@ -265,12 +265,12 @@ class Role(models.Model): name = models.CharField(max_length=255, unique=True) is_owner = models.BooleanField(default=False) - def __str__(self): - return self.name - class Meta: ordering = ('name',) + def __str__(self): + return self.name + class System_Settings(models.Model): enable_deduplication = models.BooleanField( @@ -741,6 +741,21 @@ class Product_Type(models.Model): members = models.ManyToManyField(Dojo_User, through='Product_Type_Member', related_name='prod_type_members', blank=True) authorization_groups = models.ManyToManyField(Dojo_Group, through='Product_Type_Group', related_name='product_type_groups', blank=True) + class Meta: + ordering = ('name',) + + def __str__(self): + return self.name + + def get_absolute_url(self): + from django.urls import reverse + return reverse('product_type', args=[str(self.id)]) + + def get_breadcrumbs(self): + bc = [{'title': str(self), + 'url': reverse('edit_product_type', args=(self.id,))}] + return bc + @cached_property def critical_present(self): c_findings = Finding.objects.filter( @@ -779,21 +794,6 @@ def calc_health(self): def unaccepted_open_findings(self): return Finding.objects.filter(risk_accepted=False, active=True, duplicate=False, test__engagement__product__prod_type=self) - class Meta: - ordering = ('name',) - - def __str__(self): - return self.name - - def get_breadcrumbs(self): - bc = [{'title': str(self), - 'url': reverse('edit_product_type', args=(self.id,))}] - return bc - - def get_absolute_url(self): - from django.urls import reverse - return reverse('product_type', args=[str(self.id)]) - class Product_Line(models.Model): name = models.CharField(max_length=300) @@ -813,12 +813,12 @@ class Test_Type(models.Model): dynamic_tool = models.BooleanField(default=False) active = models.BooleanField(default=True) - def __str__(self): - return self.name - class Meta: ordering = ('name',) + def __str__(self): + return self.name + def get_breadcrumbs(self): bc = [{'title': str(self), 'url': None}] @@ -844,6 +844,14 @@ class DojoMeta(models.Model): editable=False, related_name='finding_meta') + class Meta: + unique_together = (('product', 'name'), + ('endpoint', 'name'), + ('finding', 'name')) + + def __str__(self): + return f"{self.name}: {self.value}" + """ Verify that this metadata entry belongs only to one object. """ @@ -865,14 +873,6 @@ def clean(self): msg = 'Metadata entries may not have more than one relation, either a product, an endpoint either or a finding' raise ValidationError(msg) - def __str__(self): - return f"{self.name}: {self.value}" - - class Meta: - unique_together = (('product', 'name'), - ('endpoint', 'name'), - ('finding', 'name')) - class SLA_Configuration(models.Model): name = models.CharField(max_length=128, unique=True, blank=False, verbose_name=_('Custom SLA Name'), @@ -889,13 +889,11 @@ class SLA_Configuration(models.Model): async_updating = models.BooleanField(default=False, help_text=_('Findings under this SLA configuration are asynchronously being updated')) - def clean(self): - sla_days = [self.critical, self.high, self.medium, self.low] + class Meta: + ordering = ['name'] - for sla_day in sla_days: - if sla_day < 1: - msg = 'SLA Days must be at least 1' - raise ValidationError(msg) + def __str__(self): + return self.name def save(self, *args, **kwargs): # get the initial sla config before saving (if this is an existing sla config) @@ -937,11 +935,13 @@ def save(self, *args, **kwargs): from dojo.sla_config.helpers import update_sla_expiration_dates_sla_config_async update_sla_expiration_dates_sla_config_async(self, tuple(severities), products) - def __str__(self): - return self.name + def clean(self): + sla_days = [self.critical, self.high, self.medium, self.low] - class Meta: - ordering = ['name'] + for sla_day in sla_days: + if sla_day < 1: + msg = 'SLA Days must be at least 1' + raise ValidationError(msg) def delete(self, *args, **kwargs): logger.debug('%d sla configuration delete', self.id) @@ -1062,6 +1062,12 @@ class Product(models.Model): async_updating = models.BooleanField(default=False, help_text=_('Findings under this Product or SLA configuration are asynchronously being updated')) + class Meta: + ordering = ('name',) + + def __str__(self): + return self.name + def save(self, *args, **kwargs): # get the product's sla config before saving (if this is an existing product) initial_sla_config = None @@ -1091,11 +1097,9 @@ def save(self, *args, **kwargs): from dojo.product.helpers import update_sla_expiration_dates_product_async update_sla_expiration_dates_product_async(self, sla_config) - def __str__(self): - return self.name - - class Meta: - ordering = ('name',) + def get_absolute_url(self): + from django.urls import reverse + return reverse('view_product', args=[str(self.id)]) @cached_property def findings_count(self): @@ -1212,10 +1216,6 @@ def has_jira_configured(self): import dojo.jira_link.helper as jira_helper return jira_helper.has_jira_configured(self) - def get_absolute_url(self): - from django.urls import reverse - return reverse('view_product', args=[str(self.id)]) - def violates_sla(self): findings = Finding.objects.filter(test__engagement__product=self, active=True, @@ -1438,24 +1438,15 @@ class Meta: models.Index(fields=['product', 'active']), ] - def is_overdue(self): - if self.engagement_type == 'CI/CD': - overdue_grace_days = 10 - else: - overdue_grace_days = 0 - - max_end_date = timezone.now() - relativedelta(days=overdue_grace_days) - - if self.target_end < max_end_date.date(): - return True - - return False - def __str__(self): return "Engagement %i: %s (%s)" % (self.id if id else 0, self.name if self.name else '', self.target_start.strftime( "%b %d, %Y")) + def get_absolute_url(self): + from django.urls import reverse + return reverse('view_engagement', args=[str(self.id)]) + def copy(self): copy = self # Save the necessary ManyToMany relationships @@ -1486,6 +1477,19 @@ def copy(self): return copy + def is_overdue(self): + if self.engagement_type == 'CI/CD': + overdue_grace_days = 10 + else: + overdue_grace_days = 0 + + max_end_date = timezone.now() - relativedelta(days=overdue_grace_days) + + if self.target_end < max_end_date.date(): + return True + + return False + def get_breadcrumbs(self): bc = self.product.get_breadcrumbs() bc += [{'title': str(self), @@ -1505,10 +1509,6 @@ def has_jira_issue(self): import dojo.jira_link.helper as jira_helper return jira_helper.has_jira_issue(self) - def get_absolute_url(self): - from django.urls import reverse - return reverse('view_engagement', args=[str(self.id)]) - @property def is_ci_cd(self): return self.engagement_type == "CI/CD" @@ -1552,15 +1552,14 @@ class Endpoint_Status(models.Model): endpoint = models.ForeignKey('Endpoint', null=False, blank=False, on_delete=models.CASCADE, related_name='status_endpoint') finding = models.ForeignKey('Finding', null=False, blank=False, on_delete=models.CASCADE, related_name='status_finding') - @property - def age(self): - - if self.mitigated: - diff = self.mitigated_time.date() - self.date - else: - diff = get_current_date() - self.date - days = diff.days - return days if days > 0 else 0 + class Meta: + indexes = [ + models.Index(fields=['finding', 'mitigated']), + models.Index(fields=['endpoint', 'mitigated']), + ] + constraints = [ + models.UniqueConstraint(fields=['finding', 'endpoint'], name='endpoint-finding relation') + ] def __str__(self): return f"'{str(self.finding)}' on '{str(self.endpoint)}'" @@ -1577,14 +1576,15 @@ def copy(self, finding=None): return copy - class Meta: - indexes = [ - models.Index(fields=['finding', 'mitigated']), - models.Index(fields=['endpoint', 'mitigated']), - ] - constraints = [ - models.UniqueConstraint(fields=['finding', 'endpoint'], name='endpoint-finding relation') - ] + @property + def age(self): + + if self.mitigated: + diff = self.mitigated_time.date() - self.date + else: + diff = get_current_date() - self.date + days = diff.days + return days if days > 0 else 0 class Endpoint(models.Model): @@ -1622,6 +1622,62 @@ class Meta: models.Index(fields=['product']), ] + def __str__(self): + try: + if self.host: + dummy_scheme = 'dummy-scheme' # workaround for https://github.com/python-hyper/hyperlink/blob/b8c9152cd826bbe8e6cc125648f3738235019705/src/hyperlink/_url.py#L988 + url = hyperlink.EncodedURL( + scheme=self.protocol if self.protocol else dummy_scheme, + userinfo=self.userinfo or '', + host=self.host, + port=self.port, + path=tuple(self.path.split('/')) if self.path else (), + query=tuple( + ( + qe.split("=", 1) + if "=" in qe + else (qe, None) + ) + for qe in self.query.split("&") + ) if self.query else (), # inspired by https://github.com/python-hyper/hyperlink/blob/b8c9152cd826bbe8e6cc125648f3738235019705/src/hyperlink/_url.py#L1427 + fragment=self.fragment or '' + ) + # Return a normalized version of the URL to avoid differences where there shouldn't be any difference. + # Example: https://google.com and https://google.com:443 + normalize_path = self.path # it used to add '/' at the end of host + clean_url = url.normalize(scheme=True, host=True, path=normalize_path, query=True, fragment=True, userinfo=True, percents=True).to_uri().to_text() + if not self.protocol: + if clean_url[:len(dummy_scheme) + 3] == (dummy_scheme + '://'): + clean_url = clean_url[len(dummy_scheme) + 3:] + else: + msg = 'hyperlink lib did not create URL as was expected' + raise ValueError(msg) + return clean_url + else: + msg = 'Missing host' + raise ValueError(msg) + except: + url = '' + if self.protocol: + url += f'{self.protocol}://' + if self.userinfo: + url += f'{self.userinfo}@' + if self.host: + url += self.host + if self.port: + url += f':{self.port}' + if self.path: + url += '{}{}'.format('/' if self.path[0] != '/' else '', self.path) + if self.query: + url += f'?{self.query}' + if self.fragment: + url += f'#{self.fragment}' + return url + + def get_absolute_url(self): + from django.urls import reverse + return reverse('view_endpoint', args=[str(self.id)]) + def clean(self): errors = [] null_char_list = ["0x00", "\x00"] @@ -1698,58 +1754,6 @@ def clean(self): if errors: raise ValidationError(errors) - def __str__(self): - try: - if self.host: - dummy_scheme = 'dummy-scheme' # workaround for https://github.com/python-hyper/hyperlink/blob/b8c9152cd826bbe8e6cc125648f3738235019705/src/hyperlink/_url.py#L988 - url = hyperlink.EncodedURL( - scheme=self.protocol if self.protocol else dummy_scheme, - userinfo=self.userinfo or '', - host=self.host, - port=self.port, - path=tuple(self.path.split('/')) if self.path else (), - query=tuple( - ( - qe.split("=", 1) - if "=" in qe - else (qe, None) - ) - for qe in self.query.split("&") - ) if self.query else (), # inspired by https://github.com/python-hyper/hyperlink/blob/b8c9152cd826bbe8e6cc125648f3738235019705/src/hyperlink/_url.py#L1427 - fragment=self.fragment or '' - ) - # Return a normalized version of the URL to avoid differences where there shouldn't be any difference. - # Example: https://google.com and https://google.com:443 - normalize_path = self.path # it used to add '/' at the end of host - clean_url = url.normalize(scheme=True, host=True, path=normalize_path, query=True, fragment=True, userinfo=True, percents=True).to_uri().to_text() - if not self.protocol: - if clean_url[:len(dummy_scheme) + 3] == (dummy_scheme + '://'): - clean_url = clean_url[len(dummy_scheme) + 3:] - else: - msg = 'hyperlink lib did not create URL as was expected' - raise ValueError(msg) - return clean_url - else: - msg = 'Missing host' - raise ValueError(msg) - except: - url = '' - if self.protocol: - url += f'{self.protocol}://' - if self.userinfo: - url += f'{self.userinfo}@' - if self.host: - url += self.host - if self.port: - url += f':{self.port}' - if self.path: - url += '{}{}'.format('/' if self.path[0] != '/' else '', self.path) - if self.query: - url += f'?{self.query}' - if self.fragment: - url += f'#{self.fragment}' - return url - def __hash__(self): return self.__str__().__hash__() @@ -1947,10 +1951,6 @@ def from_uri(uri): fragment=fragment, ) - def get_absolute_url(self): - from django.urls import reverse - return reverse('view_endpoint', args=[str(self.id)]) - def inherit_tags(self, potentially_existing_tags): # get a copy of the tags to be inherited incoming_inherited_tags = [tag.name for tag in self.product.tags.all()] @@ -2028,14 +2028,18 @@ class Meta: models.Index(fields=['engagement', 'test_type']), ] - def test_type_name(self) -> str: - return self.test_type.name - def __str__(self): if self.title: return f"{self.title} ({self.test_type})" return str(self.test_type) + def get_absolute_url(self): + from django.urls import reverse + return reverse('view_test', args=[str(self.id)]) + + def test_type_name(self) -> str: + return self.test_type.name + def get_breadcrumbs(self): bc = self.engagement.get_breadcrumbs() bc += [{'title': str(self), @@ -2129,10 +2133,6 @@ def hash_code_allows_null_cwe(self): deduplicationLogger.debug(f'HASHCODE_ALLOWS_NULL_CWE is: {hashCodeAllowsNullCwe}') return hashCodeAllowsNullCwe - def get_absolute_url(self): - from django.urls import reverse - return reverse('view_test', args=[str(self.id)]) - def delete(self, *args, **kwargs): logger.debug('%d test delete', self.id) super().delete(*args, **kwargs) @@ -2574,6 +2574,87 @@ class Meta: models.Index(fields=['duplicate_finding', 'id']), ] + def __str__(self): + return self.title + + def save(self, dedupe_option=True, rules_option=True, product_grading_option=True, + issue_updater_option=True, push_to_jira=False, user=None, *args, **kwargs): + + from dojo.finding import helper as finding_helper + + if not user: + from dojo.utils import get_current_user + user = get_current_user() + # Title Casing + from titlecase import titlecase + self.title = titlecase(self.title[:511]) + # Set the date of the finding if nothing is supplied + if self.date is None: + self.date = timezone.now() + # Assign the numerical severity for correct sorting order + self.numerical_severity = Finding.get_numerical_severity(self.severity) + + # Synchronize cvssv3 score using cvssv3 vector + if self.cvssv3: + try: + cvss_object = CVSS3(self.cvssv3) + # use the environmental score, which is the most refined score + self.cvssv3_score = cvss_object.scores()[2] + except Exception as ex: + logger.error("Can't compute cvssv3 score for finding id %i. Invalid cvssv3 vector found: '%s'. Exception: %s", self.id, self.cvssv3, ex) + + # Finding.save is called once from serializers.py with dedupe_option=False because the finding is not ready yet, for example the endpoints are not built + # It is then called a second time with dedupe_option defaulted to true; now we can compute the hash_code and run the deduplication + if dedupe_option: + if (self.hash_code is not None): + deduplicationLogger.debug("Hash_code already computed for finding") + else: + self.hash_code = self.compute_hash_code() + deduplicationLogger.debug("Hash_code computed for finding: %s", self.hash_code) + + if self.pk is None: + # We enter here during the first call from serializers.py + from dojo.utils import apply_cwe_to_template + self = apply_cwe_to_template(self) + + if (self.file_path is not None) and (len(self.unsaved_endpoints) == 0): + self.static_finding = True + self.dynamic_finding = False + elif (self.file_path is not None): + self.static_finding = True + + # because we have reduced the number of (super()).save() calls, the helper is no longer called for new findings + # so we call it manually + finding_helper.update_finding_status(self, user, changed_fields={'id': (None, None)}) + + else: + # logger.debug('setting static / dynamic in save') + # need to have an id/pk before we can access endpoints + if (self.file_path is not None) and (self.endpoints.count() == 0): + self.static_finding = True + self.dynamic_finding = False + elif (self.file_path is not None): + self.static_finding = True + + # update the SLA expiration date last, after all other finding fields have been updated + self.set_sla_expiration_date() + + logger.debug("Saving finding of id " + str(self.id) + " dedupe_option:" + str(dedupe_option) + " (self.pk is %s)", "None" if self.pk is None else "not None") + super().save(*args, **kwargs) + + self.found_by.add(self.test.test_type) + + # only perform post processing (in celery task) if needed. this check avoids submitting 1000s of tasks to celery that will do nothing + if dedupe_option or issue_updater_option or product_grading_option or push_to_jira: + finding_helper.post_process_finding_save(self, dedupe_option=dedupe_option, rules_option=rules_option, product_grading_option=product_grading_option, + issue_updater_option=issue_updater_option, push_to_jira=push_to_jira, user=user, *args, **kwargs) + else: + logger.debug('no options selected that require finding post processing') + + def get_absolute_url(self): + from django.urls import reverse + return reverse('view_finding', args=[str(self.id)]) + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -2618,10 +2699,6 @@ def copy(self, test=None): return copy - def get_absolute_url(self): - from django.urls import reverse - return reverse('view_finding', args=[str(self.id)]) - def delete(self, *args, **kwargs): logger.debug('%d finding delete', self.id) import dojo.finding.helper as helper @@ -2817,9 +2894,6 @@ def get_severity(num_severity): return None - def __str__(self): - return self.title - def status(self): status = [] if self.under_review: @@ -2987,80 +3061,6 @@ def save_no_options(self, *args, **kwargs): return self.save(dedupe_option=False, rules_option=False, product_grading_option=False, issue_updater_option=False, push_to_jira=False, user=None, *args, **kwargs) - def save(self, dedupe_option=True, rules_option=True, product_grading_option=True, - issue_updater_option=True, push_to_jira=False, user=None, *args, **kwargs): - - from dojo.finding import helper as finding_helper - - if not user: - from dojo.utils import get_current_user - user = get_current_user() - # Title Casing - from titlecase import titlecase - self.title = titlecase(self.title[:511]) - # Set the date of the finding if nothing is supplied - if self.date is None: - self.date = timezone.now() - # Assign the numerical severity for correct sorting order - self.numerical_severity = Finding.get_numerical_severity(self.severity) - - # Synchronize cvssv3 score using cvssv3 vector - if self.cvssv3: - try: - cvss_object = CVSS3(self.cvssv3) - # use the environmental score, which is the most refined score - self.cvssv3_score = cvss_object.scores()[2] - except Exception as ex: - logger.error("Can't compute cvssv3 score for finding id %i. Invalid cvssv3 vector found: '%s'. Exception: %s", self.id, self.cvssv3, ex) - - # Finding.save is called once from serializers.py with dedupe_option=False because the finding is not ready yet, for example the endpoints are not built - # It is then called a second time with dedupe_option defaulted to true; now we can compute the hash_code and run the deduplication - if dedupe_option: - if (self.hash_code is not None): - deduplicationLogger.debug("Hash_code already computed for finding") - else: - self.hash_code = self.compute_hash_code() - deduplicationLogger.debug("Hash_code computed for finding: %s", self.hash_code) - - if self.pk is None: - # We enter here during the first call from serializers.py - from dojo.utils import apply_cwe_to_template - self = apply_cwe_to_template(self) - - if (self.file_path is not None) and (len(self.unsaved_endpoints) == 0): - self.static_finding = True - self.dynamic_finding = False - elif (self.file_path is not None): - self.static_finding = True - - # because we have reduced the number of (super()).save() calls, the helper is no longer called for new findings - # so we call it manually - finding_helper.update_finding_status(self, user, changed_fields={'id': (None, None)}) - - else: - # logger.debug('setting static / dynamic in save') - # need to have an id/pk before we can access endpoints - if (self.file_path is not None) and (self.endpoints.count() == 0): - self.static_finding = True - self.dynamic_finding = False - elif (self.file_path is not None): - self.static_finding = True - - # update the SLA expiration date last, after all other finding fields have been updated - self.set_sla_expiration_date() - - logger.debug("Saving finding of id " + str(self.id) + " dedupe_option:" + str(dedupe_option) + " (self.pk is %s)", "None" if self.pk is None else "not None") - super().save(*args, **kwargs) - - self.found_by.add(self.test.test_type) - - # only perform post processing (in celery task) if needed. this check avoids submitting 1000s of tasks to celery that will do nothing - if dedupe_option or issue_updater_option or product_grading_option or push_to_jira: - finding_helper.post_process_finding_save(self, dedupe_option=dedupe_option, rules_option=rules_option, product_grading_option=product_grading_option, - issue_updater_option=issue_updater_option, push_to_jira=push_to_jira, user=user, *args, **kwargs) - else: - logger.debug('no options selected that require finding post processing') - # Check if a mandatory field is empty. If it's the case, fill it with "no given" def clean(self): no_check = ["test", "reporter"] @@ -3464,15 +3464,15 @@ class Meta: def __str__(self): return self.title + def get_absolute_url(self): + from django.urls import reverse + return reverse('edit_template', args=[str(self.id)]) + def get_breadcrumbs(self): bc = [{'title': str(self), 'url': reverse('view_template', args=(self.id,))}] return bc - def get_absolute_url(self): - from django.urls import reverse - return reverse('edit_template', args=[str(self.id)]) - @cached_property def vulnerability_ids(self): # Get vulnerability ids from database and convert to list of strings @@ -3809,6 +3809,9 @@ class JIRA_Instance(models.Model): global_jira_sla_notification = models.BooleanField(default=True, blank=False, verbose_name=_("Globally send SLA notifications as comment?"), help_text=_("This setting can be overidden at the Product level")) finding_jira_sync = models.BooleanField(default=False, blank=False, verbose_name=_("Automatically sync Findings with JIRA?"), help_text=_("If enabled, this will sync changes to a Finding automatically to JIRA")) + def __str__(self): + return self.configuration_name + " | " + self.url + " | " + self.username + @property def accepted_resolutions(self): return [m.strip() for m in (self.accepted_mapping_resolution or '').split(',')] @@ -3817,9 +3820,6 @@ def accepted_resolutions(self): def false_positive_resolutions(self): return [m.strip() for m in (self.false_positive_mapping_resolution or '').split(',')] - def __str__(self): - return self.configuration_name + " | " + self.url + " | " + self.username - def get_priority(self, status): if status == 'Info': return self.info_mapping_severity @@ -3890,14 +3890,14 @@ class JIRA_Project(models.Model): product_jira_sla_notification = models.BooleanField(default=False, blank=True, verbose_name=_("Send SLA notifications as comment?")) risk_acceptance_expiration_notification = models.BooleanField(default=False, blank=True, verbose_name=_("Send Risk Acceptance expiration notifications as comment?")) + def __str__(self): + return ('%s: ' + self.project_key + '(%s)') % (str(self.id), str(self.jira_instance.url) if self.jira_instance else 'None') + def clean(self): if not self.jira_instance: msg = 'Cannot save JIRA Project Configuration without JIRA Instance' raise ValidationError(msg) - def __str__(self): - return ('%s: ' + self.project_key + '(%s)') % (str(self.id), str(self.jira_instance.url) if self.jira_instance else 'None') - # declare form here as we can't import forms.py due to circular imports not even locally class JIRAForm_Admin(forms.ModelForm): @@ -3942,6 +3942,14 @@ class JIRA_Issue(models.Model): verbose_name=_('Jira last update'), help_text=_("The date the linked Jira issue was last modified.")) + def __str__(self): + text = "" + if self.finding: + text = self.finding.test.engagement.product.name + " | Finding: " + self.finding.title + ", ID: " + str(self.finding.id) + elif self.engagement: + text = self.engagement.product.name + " | Engagement: " + self.engagement.name + ", ID: " + str(self.engagement.id) + return text + " | Jira Key: " + str(self.jira_key) + def set_obj(self, obj): if isinstance(obj, Finding): self.finding = obj @@ -3952,14 +3960,6 @@ def set_obj(self, obj): else: raise TypeError('unknown object type while creating JIRA_Issue: %s' % to_str_typed(obj)) - def __str__(self): - text = "" - if self.finding: - text = self.finding.test.engagement.product.name + " | Finding: " + self.finding.title + ", ID: " + str(self.finding.id) - elif self.engagement: - text = self.engagement.product.name + " | Engagement: " + self.engagement.name + ", ID: " + str(self.engagement.id) - return text + " | Jira Key: " + str(self.jira_key) - NOTIFICATION_CHOICE_SLACK = ("slack", "slack") NOTIFICATION_CHOICE_MSTEAMS = ("msteams", "msteams") @@ -4014,6 +4014,9 @@ class Meta: models.Index(fields=['user', 'product']), ] + def __str__(self): + return f"Notifications about {self.product or 'all projects'} for {self.user or 'system notifications'}" + @classmethod def merge_notifications_list(cls, notifications_list): if not notifications_list: @@ -4045,9 +4048,6 @@ def merge_notifications_list(cls, notifications_list): result.risk_acceptance_expiration = {*result.risk_acceptance_expiration, *notifications.risk_acceptance_expiration} return result - def __str__(self): - return f"Notifications about {self.product or 'all projects'} for {self.user or 'system notifications'}" - class NotificationsAdmin(admin.ModelAdmin): list_filter = ('user', 'product') @@ -4160,12 +4160,12 @@ class Languages(models.Model): code = models.IntegerField(blank=True, null=True, verbose_name=_('Number of code lines')) created = models.DateTimeField(auto_now_add=True, null=False) - def __str__(self): - return self.language.language - class Meta: unique_together = [('language', 'product')] + def __str__(self): + return self.language.language + class App_Analysis(models.Model): product = models.ForeignKey(Product, on_delete=models.CASCADE) @@ -4307,12 +4307,12 @@ class Benchmark_Product(models.Model): created = models.DateTimeField(auto_now_add=True, null=False) updated = models.DateTimeField(auto_now=True) - def __str__(self): - return self.product.name + ': ' + self.control.objective_number + ': ' + self.control.category.name - class Meta: unique_together = [('product', 'control')] + def __str__(self): + return self.product.name + ': ' + self.control.objective_number + ': ' + self.control.category.name + class Benchmark_Product_Summary(models.Model): product = models.ForeignKey(Product, on_delete=models.CASCADE) @@ -4336,12 +4336,12 @@ class Benchmark_Product_Summary(models.Model): created = models.DateTimeField(auto_now_add=True, null=False) updated = models.DateTimeField(auto_now=True) - def __str__(self): - return self.product.name + ': ' + self.benchmark_type.name - class Meta: unique_together = [('product', 'benchmark_type')] + def __str__(self): + return self.product.name + ': ' + self.benchmark_type.name + # ========================== # Defect Dojo Engaegment Surveys diff --git a/ruff.toml b/ruff.toml index 31963485ed..20593fa239 100644 --- a/ruff.toml +++ b/ruff.toml @@ -42,6 +42,7 @@ select = [ "EXE", "TRIO", "C4", + "DJ003", "DJ012", "DJ013", "EM", "ICN", "LOG", From 0a993da416ebf6a1ee61a8e42add0d79b551a49c Mon Sep 17 00:00:00 2001 From: davidhernandeze Date: Tue, 30 Apr 2024 16:32:12 -0600 Subject: [PATCH 108/138] Fix engagements filters in 'engagements by product view' (#10046) * fix engagements filters in 'engagements by product view' * fix linter * add filtering without object lookups * fix imports order --- dojo/engagement/views.py | 10 +++++++--- dojo/filters.py | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/dojo/engagement/views.py b/dojo/engagement/views.py index 4f38ec4d32..696e7b0ea2 100644 --- a/dojo/engagement/views.py +++ b/dojo/engagement/views.py @@ -42,6 +42,8 @@ EngagementFilterWithoutObjectLookups, EngagementTestFilter, EngagementTestFilterWithoutObjectLookups, + ProductEngagementsFilter, + ProductEngagementsFilterWithoutObjectLookups, ) from dojo.finding.helper import NOT_ACCEPTED_FINDINGS_QUERY from dojo.finding.views import find_available_notetypes @@ -215,8 +217,11 @@ def engagements_all(request): products_with_engagements = products_with_engagements.filter(~Q(engagement=None)).distinct() # count using prefetch instead of just using 'engagement__set_test_test` to avoid loading all test in memory just to count them + filter_string_matching = get_system_setting('filter_string_matching', False) + products_filter_class = ProductEngagementsFilterWithoutObjectLookups if filter_string_matching else ProductEngagementsFilter + engagement_query = Engagement.objects.annotate(test_count=Count('test__id')) filter_qs = products_with_engagements.prefetch_related( - Prefetch('engagement_set', queryset=Engagement.objects.all().annotate(test_count=Count('test__id'))) + Prefetch('engagement_set', queryset=products_filter_class(request.GET, engagement_query).qs) ) filter_qs = filter_qs.prefetch_related( @@ -230,7 +235,6 @@ def engagements_all(request): 'engagement_set__jira_project__jira_instance', 'jira_project_set__jira_instance' ) - filter_string_matching = get_system_setting("filter_string_matching", False) filter_class = EngagementFilterWithoutObjectLookups if filter_string_matching else EngagementFilter filtered = filter_class( request.GET, @@ -238,7 +242,7 @@ def engagements_all(request): ) prods = get_page_items(request, filtered.qs, 25) - + prods.paginator.count = sum(len(prod.engagement_set.all()) for prod in prods) name_words = products_with_engagements.values_list('name', flat=True) eng_words = get_authorized_engagements(Permissions.Engagement_View).values_list('name', flat=True).distinct() diff --git a/dojo/filters.py b/dojo/filters.py index 0613034032..d69202ced0 100644 --- a/dojo/filters.py +++ b/dojo/filters.py @@ -1053,6 +1053,32 @@ class Meta: fields = ['name', 'prod_type'] +class ProductEngagementsFilter(DojoFilter): + engagement__name = CharFilter(field_name='name', lookup_expr='icontains', label='Engagement name contains') + engagement__lead = ModelChoiceFilter(field_name='lead', queryset=Dojo_User.objects.none(), label="Lead") + engagement__version = CharFilter(field_name='version', lookup_expr='icontains', label='Engagement version') + engagement__test__version = CharFilter(field_name='test__version', lookup_expr='icontains', label='Test version') + engagement__status = MultipleChoiceFilter(field_name='status', choices=ENGAGEMENT_STATUS_CHOICES, + label="Status") + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.form.fields['engagement__lead'].queryset = get_authorized_users(Permissions.Product_Type_View) \ + .filter(engagement__lead__isnull=False).distinct() + + class Meta: + model = Engagement + fields = [] + + +class ProductEngagementsFilterWithoutObjectLookups(ProductEngagementsFilter): + engagement__lead = CharFilter( + field_name="lead__username", + lookup_expr="iexact", + label="Lead Username", + help_text="Search for Lead username that are an exact match") + + class EngagementFilterWithoutObjectLookups(EngagementFilterHelper): engagement__lead = CharFilter( field_name="engagement__lead__username", From 37144db993c15a4d6f6058576e67f0db4471f81e Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Wed, 1 May 2024 04:34:47 +0200 Subject: [PATCH 109/138] refactor generic parser (#9922) * rework generic parser * fix ruff C4 * fix ruff --- dojo/tools/generic/csv_parser.py | 109 ++++++++++++++ dojo/tools/generic/json_parser.py | 119 +++++++++++++++ dojo/tools/generic/parser.py | 232 +----------------------------- 3 files changed, 235 insertions(+), 225 deletions(-) create mode 100644 dojo/tools/generic/csv_parser.py create mode 100644 dojo/tools/generic/json_parser.py diff --git a/dojo/tools/generic/csv_parser.py b/dojo/tools/generic/csv_parser.py new file mode 100644 index 0000000000..2bf500da1b --- /dev/null +++ b/dojo/tools/generic/csv_parser.py @@ -0,0 +1,109 @@ +import csv +import hashlib +import io + +from cvss import parser as cvss_parser +from dateutil.parser import parse + +from dojo.models import Endpoint, Finding + + +class GenericCSVParser: + ID = "Generic Findings Import" + + def _get_findings_csv(self, filename): + content = filename.read() + if isinstance(content, bytes): + content = content.decode("utf-8") + reader = csv.DictReader( + io.StringIO(content), delimiter=",", quotechar='"' + ) + + dupes = {} + for row in reader: + finding = Finding( + title=row["Title"], + description=row["Description"], + date=parse(row["Date"]).date(), + severity=self.get_severity(row["Severity"]), + duplicate=self._convert_bool( + row.get("Duplicate", "FALSE") + ), # bool False by default + nb_occurences=1, + ) + # manage active + if "Active" in row: + finding.active = self._convert_bool(row.get("Active")) + # manage mitigation + if "Mitigation" in row: + finding.mitigation = row["Mitigation"] + # manage impact + if "Impact" in row: + finding.impact = row["Impact"] + # manage impact + if "References" in row: + finding.references = row["References"] + # manage verified + if "Verified" in row: + finding.verified = self._convert_bool(row.get("Verified")) + # manage false positives + if "FalsePositive" in row: + finding.false_p = self._convert_bool(row.get("FalsePositive")) + # manage CVE + if "CVE" in row and [row["CVE"]]: + finding.unsaved_vulnerability_ids = [row["CVE"]] + # manage Vulnerability Id + if "Vulnerability Id" in row and row["Vulnerability Id"]: + if finding.unsaved_vulnerability_ids: + finding.unsaved_vulnerability_ids.append( + row["Vulnerability Id"] + ) + else: + finding.unsaved_vulnerability_ids = [ + row["Vulnerability Id"] + ] + # manage CWE + if "CweId" in row: + finding.cwe = int(row["CweId"]) + + if "CVSSV3" in row: + cvss_objects = cvss_parser.parse_cvss_from_text(row["CVSSV3"]) + if len(cvss_objects) > 0: + finding.cvssv3 = cvss_objects[0].clean_vector() + + # manage endpoints + if "Url" in row: + finding.unsaved_endpoints = [ + Endpoint.from_uri(row["Url"]) + if "://" in row["Url"] + else Endpoint.from_uri("//" + row["Url"]) + ] + + # manage internal de-duplication + key = hashlib.sha256( + f"{finding.severity}|{finding.title}|{finding.description}".encode() + ).hexdigest() + if key in dupes: + find = dupes[key] + find.unsaved_endpoints.extend(finding.unsaved_endpoints) + if find.unsaved_vulnerability_ids: + find.unsaved_vulnerability_ids.extend( + finding.unsaved_vulnerability_ids + ) + else: + find.unsaved_vulnerability_ids = ( + finding.unsaved_vulnerability_ids + ) + find.nb_occurences += 1 + else: + dupes[key] = finding + return list(dupes.values()) + + def _convert_bool(self, val): + return val.lower()[0:1] == "t" # bool False by default + + def get_severity(self, input): + if input in ["Info", "Low", "Medium", "High", "Critical"]: + return input + else: + return "Info" diff --git a/dojo/tools/generic/json_parser.py b/dojo/tools/generic/json_parser.py new file mode 100644 index 0000000000..ecf605e835 --- /dev/null +++ b/dojo/tools/generic/json_parser.py @@ -0,0 +1,119 @@ +from dojo.models import Endpoint, Finding +from dojo.tools.parser_test import ParserTest + + +class GenericJSONParser: + ID = "Generic Findings Import" + + def _get_test_json(self, data): + test_internal = ParserTest( + name=data.get("name", self.ID), + type=data.get("type", self.ID), + version=data.get("version"), + ) + test_internal.findings = [] + for item in data.get("findings", []): + # remove endpoints of the dictionnary + unsaved_endpoints = None + if "endpoints" in item: + unsaved_endpoints = item["endpoints"] + del item["endpoints"] + # remove files of the dictionnary + unsaved_files = None + if "files" in item: + unsaved_files = item["files"] + del item["files"] + # remove vulnerability_ids of the dictionnary + unsaved_vulnerability_ids = None + if "vulnerability_ids" in item: + unsaved_vulnerability_ids = item["vulnerability_ids"] + del item["vulnerability_ids"] + + # check for required keys + required = {"title", "severity", "description"} + missing = sorted(required.difference(item)) + if missing: + msg = f"Required fields are missing: {missing}" + raise ValueError(msg) + + # check for allowed keys + allowed = { + "date", + "cwe", + "cve", + "cvssv3", + "cvssv3_score", + "mitigation", + "impact", + "steps_to_reproduce", + "severity_justification", + "references", + "active", + "verified", + "false_p", + "out_of_scope", + "risk_accepted", + "under_review", + "is_mitigated", + "thread_id", + "mitigated", + "numerical_severity", + "param", + "payload", + "line", + "file_path", + "component_name", + "component_version", + "static_finding", + "dynamic_finding", + "scanner_confidence", + "unique_id_from_tool", + "vuln_id_from_tool", + "sast_source_object", + "sast_sink_object", + "sast_source_line", + "sast_source_file_path", + "nb_occurences", + "publish_date", + "service", + "planned_remediation_date", + "planned_remediation_version", + "effort_for_fixing", + "tags", + }.union(required) + not_allowed = sorted(set(item).difference(allowed)) + if not_allowed: + msg = f"Not allowed fields are present: {not_allowed}" + raise ValueError(msg) + finding = Finding(**item) + + # manage endpoints + if unsaved_endpoints: + finding.unsaved_endpoints = [] + for endpoint_item in unsaved_endpoints: + if isinstance(endpoint_item, str): + if "://" in endpoint_item: # is the host full uri? + endpoint = Endpoint.from_uri(endpoint_item) + # can raise exception if the host is not valid URL + else: + endpoint = Endpoint.from_uri("//" + endpoint_item) + # can raise exception if there is no way to parse + # the host + else: + endpoint = Endpoint(**endpoint_item) + finding.unsaved_endpoints.append(endpoint) + if unsaved_files: + finding.unsaved_files = unsaved_files + if finding.cve: + finding.unsaved_vulnerability_ids = [finding.cve] + if unsaved_vulnerability_ids: + if finding.unsaved_vulnerability_ids: + finding.unsaved_vulnerability_ids.append( + unsaved_vulnerability_ids + ) + else: + finding.unsaved_vulnerability_ids = ( + unsaved_vulnerability_ids + ) + test_internal.findings.append(finding) + return test_internal diff --git a/dojo/tools/generic/parser.py b/dojo/tools/generic/parser.py index dffbeeab6d..e2fb66086b 100644 --- a/dojo/tools/generic/parser.py +++ b/dojo/tools/generic/parser.py @@ -1,12 +1,7 @@ -import csv -import hashlib -import io import json -from cvss import parser as cvss_parser -from dateutil.parser import parse - -from dojo.models import Endpoint, Finding +from dojo.tools.generic.csv_parser import GenericCSVParser +from dojo.tools.generic.json_parser import GenericJSONParser from dojo.tools.parser_test import ParserTest @@ -24,236 +19,23 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, filename, test): if filename.name.lower().endswith(".csv"): - return self._get_findings_csv(filename) + return GenericCSVParser()._get_findings_csv(filename) elif filename.name.lower().endswith(".json"): data = json.load(filename) - test_internal = self._get_test_json(data) + test_internal = GenericJSONParser()._get_test_json(data) return test_internal.findings else: # default to CSV like before - return self._get_findings_csv(filename) + return GenericCSVParser()._get_findings_csv(filename) def get_tests(self, scan_type, filename): # if the file is a CSV just use the old function if filename.name.lower().endswith(".csv"): test = ParserTest(name=self.ID, type=self.ID, version=None) - test.findings = self._get_findings_csv(filename) + test.findings = GenericCSVParser()._get_findings_csv(filename) return [test] # we manage it like a JSON file (default) data = json.load(filename) - return [self._get_test_json(data)] + return [GenericJSONParser()._get_test_json(data)] def requires_file(self, scan_type): return True - - def _get_test_json(self, data): - test_internal = ParserTest( - name=data.get("name", self.ID), - type=data.get("type", self.ID), - version=data.get("version"), - ) - test_internal.findings = [] - for item in data.get("findings", []): - # remove endpoints of the dictionnary - unsaved_endpoints = None - if "endpoints" in item: - unsaved_endpoints = item["endpoints"] - del item["endpoints"] - # remove files of the dictionnary - unsaved_files = None - if "files" in item: - unsaved_files = item["files"] - del item["files"] - # remove vulnerability_ids of the dictionnary - unsaved_vulnerability_ids = None - if "vulnerability_ids" in item: - unsaved_vulnerability_ids = item["vulnerability_ids"] - del item["vulnerability_ids"] - - # check for required keys - required = {"title", "severity", "description"} - missing = sorted(required.difference(item)) - if missing: - msg = f"Required fields are missing: {missing}" - raise ValueError(msg) - - # check for allowed keys - allowed = { - "date", - "cwe", - "cve", - "cvssv3", - "cvssv3_score", - "mitigation", - "impact", - "steps_to_reproduce", - "severity_justification", - "references", - "active", - "verified", - "false_p", - "out_of_scope", - "risk_accepted", - "under_review", - "is_mitigated", - "thread_id", - "mitigated", - "numerical_severity", - "param", - "payload", - "line", - "file_path", - "component_name", - "component_version", - "static_finding", - "dynamic_finding", - "scanner_confidence", - "unique_id_from_tool", - "vuln_id_from_tool", - "sast_source_object", - "sast_sink_object", - "sast_source_line", - "sast_source_file_path", - "nb_occurences", - "publish_date", - "service", - "planned_remediation_date", - "planned_remediation_version", - "effort_for_fixing", - "tags", - }.union(required) - not_allowed = sorted(set(item).difference(allowed)) - if not_allowed: - msg = f"Not allowed fields are present: {not_allowed}" - raise ValueError(msg) - - finding = Finding(**item) - - # manage endpoints - if unsaved_endpoints: - finding.unsaved_endpoints = [] - for endpoint_item in unsaved_endpoints: - if isinstance(endpoint_item, str): - if "://" in endpoint_item: # is the host full uri? - endpoint = Endpoint.from_uri(endpoint_item) - # can raise exception if the host is not valid URL - else: - endpoint = Endpoint.from_uri("//" + endpoint_item) - # can raise exception if there is no way to parse - # the host - else: - endpoint = Endpoint(**endpoint_item) - finding.unsaved_endpoints.append(endpoint) - - if unsaved_files: - finding.unsaved_files = unsaved_files - if finding.cve: - finding.unsaved_vulnerability_ids = [finding.cve] - if unsaved_vulnerability_ids: - if finding.unsaved_vulnerability_ids: - finding.unsaved_vulnerability_ids.append( - unsaved_vulnerability_ids - ) - else: - finding.unsaved_vulnerability_ids = ( - unsaved_vulnerability_ids - ) - test_internal.findings.append(finding) - return test_internal - - def _get_findings_csv(self, filename): - content = filename.read() - if isinstance(content, bytes): - content = content.decode("utf-8") - reader = csv.DictReader( - io.StringIO(content), delimiter=",", quotechar='"' - ) - - dupes = {} - for row in reader: - finding = Finding( - title=row["Title"], - description=row["Description"], - date=parse(row["Date"]).date(), - severity=self.get_severity(row["Severity"]), - duplicate=self._convert_bool( - row.get("Duplicate", "FALSE") - ), # bool False by default - nb_occurences=1, - ) - # manage active - if "Active" in row: - finding.active = self._convert_bool(row.get("Active")) - # manage mitigation - if "Mitigation" in row: - finding.mitigation = row["Mitigation"] - # manage impact - if "Impact" in row: - finding.impact = row["Impact"] - # manage impact - if "References" in row: - finding.references = row["References"] - # manage verified - if "Verified" in row: - finding.verified = self._convert_bool(row.get("Verified")) - # manage false positives - if "FalsePositive" in row: - finding.false_p = self._convert_bool(row.get("FalsePositive")) - # manage CVE - if "CVE" in row and [row["CVE"]]: - finding.unsaved_vulnerability_ids = [row["CVE"]] - # manage Vulnerability Id - if "Vulnerability Id" in row and row["Vulnerability Id"]: - if finding.unsaved_vulnerability_ids: - finding.unsaved_vulnerability_ids.append( - row["Vulnerability Id"] - ) - else: - finding.unsaved_vulnerability_ids = [ - row["Vulnerability Id"] - ] - # manage CWE - if "CweId" in row: - finding.cwe = int(row["CweId"]) - - if "CVSSV3" in row: - cvss_objects = cvss_parser.parse_cvss_from_text(row["CVSSV3"]) - if len(cvss_objects) > 0: - finding.cvssv3 = cvss_objects[0].clean_vector() - - # manage endpoints - if "Url" in row: - finding.unsaved_endpoints = [ - Endpoint.from_uri(row["Url"]) - if "://" in row["Url"] - else Endpoint.from_uri("//" + row["Url"]) - ] - - # manage internal de-duplication - key = hashlib.sha256( - f"{finding.severity}|{finding.title}|{finding.description}".encode() - ).hexdigest() - if key in dupes: - find = dupes[key] - find.unsaved_endpoints.extend(finding.unsaved_endpoints) - if find.unsaved_vulnerability_ids: - find.unsaved_vulnerability_ids.extend( - finding.unsaved_vulnerability_ids - ) - else: - find.unsaved_vulnerability_ids = ( - finding.unsaved_vulnerability_ids - ) - find.nb_occurences += 1 - else: - dupes[key] = finding - - return list(dupes.values()) - - def _convert_bool(self, val): - return val.lower()[0:1] == "t" # bool False by default - - def get_severity(self, input): - if input in ["Info", "Low", "Medium", "High", "Critical"]: - return input - else: - return "Info" From 39094920a90de32a1cb95094afac8c18dd060566 Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Wed, 1 May 2024 04:44:21 +0200 Subject: [PATCH 110/138] remove aws scout2 parser (#9894) * remove scout2 content * remove aws_scout2 components --- .../integrations/parsers/file/aws_scout2.md | 17 -- dojo/settings/settings.dist.py | 2 +- dojo/tools/aws_scout2/__init__.py | 1 - dojo/tools/aws_scout2/parser.py | 192 ------------------ unittests/scans/aws_scout2/aws_config.js | 2 - unittests/tools/test_aws_scout2_parser.py | 48 ----- 6 files changed, 1 insertion(+), 261 deletions(-) delete mode 100644 docs/content/en/integrations/parsers/file/aws_scout2.md delete mode 100644 dojo/tools/aws_scout2/__init__.py delete mode 100644 dojo/tools/aws_scout2/parser.py delete mode 100644 unittests/scans/aws_scout2/aws_config.js delete mode 100644 unittests/tools/test_aws_scout2_parser.py diff --git a/docs/content/en/integrations/parsers/file/aws_scout2.md b/docs/content/en/integrations/parsers/file/aws_scout2.md deleted file mode 100644 index 2a5cbbf715..0000000000 --- a/docs/content/en/integrations/parsers/file/aws_scout2.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: "AWS Scout2 Scanner (deprecated)" -toc_hide: true ---- -JS file in scout2-report/inc-awsconfig/aws\_config.js. - -{{% alert title="Warning" color="warning" %}} -AWS Scout2 Scanner is deprecated and has been replaced with ScoutSuite (https://github.com/nccgroup/ScoutSuite) upstream. -Please switch to the new parser for ScoutSuite. -{{% /alert %}} - -{{% alert title="Warning" color="warning" %}} -This parser is disactivated by default in releases >= 2.3.1 and will be removed in release >= 3.x.x. -{{% /alert %}} - -### Sample Scan Data -Sample AWS Scout2 Scanner (deprecated) scans can be found [here](https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans/aws_scout2). \ No newline at end of file diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index 1c28b9f67e..5931af1125 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -220,7 +220,7 @@ # regular expression to exclude one or more parsers # could be usefull to limit parser allowed # AWS Scout2 Scan Parser is deprecated (see https://github.com/DefectDojo/django-DefectDojo/pull/5268) - DD_PARSER_EXCLUDE=(str, 'AWS Scout2 Scan'), + DD_PARSER_EXCLUDE=(str, ''), # when enabled in sytem settings, every minute a job run to delete excess duplicates # we limit the amount of duplicates that can be deleted in a single run of that job # to prevent overlapping runs of that job from occurrring diff --git a/dojo/tools/aws_scout2/__init__.py b/dojo/tools/aws_scout2/__init__.py deleted file mode 100644 index 20f78a98a5..0000000000 --- a/dojo/tools/aws_scout2/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__author__ = "Aaron Weaver" diff --git a/dojo/tools/aws_scout2/parser.py b/dojo/tools/aws_scout2/parser.py deleted file mode 100644 index 6b30e6c0da..0000000000 --- a/dojo/tools/aws_scout2/parser.py +++ /dev/null @@ -1,192 +0,0 @@ -import json -import textwrap -from datetime import datetime - -from html2text import html2text - -from dojo.models import Finding - - -class AWSScout2Parser: - # FIXME bad very bad - item_data = "" - pdepth = 0 - - def get_scan_types(self): - return ["AWS Scout2 Scan"] - - def get_label_for_scan_types(self, scan_type): - return "AWS Scout2 Scan" - - def get_description_for_scan_types(self, scan_type): - return "JS file in scout2-report/inc-awsconfig/aws_config.js." - - def get_findings(self, filename, test): - content = filename.read() - if isinstance(content, bytes): - content = content.decode("utf-8") - raw_data = content.replace("aws_info =", "") - data = json.loads(raw_data) - find_date = datetime.now() - dupes = {} - - test_description = "" - aws_account_id = data["aws_account_id"] - test_description = f"{test_description} **AWS Account:** {aws_account_id}\n" - last_run = data["last_run"] - test_description = "{} **Ruleset:** {}\n".format( - test_description, - last_run["ruleset_name"], - ) - test_description = "{} **Ruleset Description:** {}\n".format( - test_description, - last_run["ruleset_about"], - ) - test_description = "{} **Command:** {}\n".format( - test_description, - last_run["cmd"], - ) - - # Summary for AWS Services - test_description = "%s\n**AWS Services** \n\n" % (test_description) - for service, items in list(last_run["summary"].items()): - test_description = f"{test_description}\n**{service.upper()}** \n" - test_description = "{}\n* **Checked Items:** {}\n".format( - test_description, - items["checked_items"], - ) - test_description = "{}* **Flagged Items:** {}\n".format( - test_description, - items["flagged_items"], - ) - test_description = "{}* **Max Level:** {}\n".format( - test_description, - items["max_level"], - ) - test_description = "{}* **Resource Count:** {}\n".format( - test_description, - items["resources_count"], - ) - test_description = "{}* **Rules Count:** {}\n\n".format( - test_description, - items["rules_count"], - ) - test.description = test_description - test.save() - - scout2_findings = [] - - # Configured AWS Services - for service in list(data["services"].items()): - for service_item in service: - if "findings" in service_item: - for name, finding in list( - service_item["findings"].items() - ): - if finding["items"]: - description_text = "" - for name in finding["items"]: - description_text = ( - description_text - + "**Location:** " - + name - + "\n\n---\n" - ) - description_text = description_text + "\n" - key = name.split(".") - i = 1 - lookup = service_item - while i < len(key): - if key[i] in lookup: - if isinstance(lookup[key[i]], dict): - lookup = lookup[key[i]] - if ( - key[i - 1] == "security_groups" - or key[i - 1] - == "PolicyDocument" - ): - break - i = i + 1 - - self.recursive_print(lookup) - description_text = ( - description_text + self.item_data - ) - self.item_data = "" - - mobsf_item = { - "category": "Mobile Permissions", - "title": finding["description"], - "severity": finding["level"], - "description": description_text, - } - scout2_findings.append(mobsf_item) - - for scout2_finding in scout2_findings: - title = html2text(scout2_finding["title"]) - sev = self.getCriticalityRating(scout2_finding["severity"]) - description = scout2_finding["description"] - dupe_key = sev + title - if dupe_key in dupes: - find = dupes[dupe_key] - if description is not None: - find.description += description - else: - find = Finding( - title=textwrap.shorten(title, 150), - cwe=1032, # Security Configuration Weaknesses, would like to fine tune - test=test, - description="**AWS Account:** " - + aws_account_id - + "\n" - + description, - severity=sev, - references=None, - date=find_date, - dynamic_finding=True, - ) - dupes[dupe_key] = find - return list(dupes.values()) - - def formatview(self, depth): - if depth > 1: - return "* " - else: - return "" - - def recursive_print(self, src, depth=0, key=""): - def tabs(n): - return " " * n * 2 - - if isinstance(src, dict): - for key, value in src.items(): - if isinstance(src, str): - self.item_data = self.item_data + key + "\n" - self.recursive_print(value, depth + 1, key) - elif isinstance(src, list): - for litem in src: - self.recursive_print(litem, depth + 2) - else: - if self.pdepth != depth: - self.item_data = self.item_data + "\n" - if key: - self.item_data = ( - self.item_data - + self.formatview(depth) - + f"**{key.title()}:** {src}\n\n" - ) - else: - self.item_data = ( - self.item_data + self.formatview(depth) + "%s\n" % src - ) - self.pdepth = depth - - # Criticality rating - def getCriticalityRating(self, rating): - criticality = "Info" - if rating == "warning": - criticality = "Medium" - elif rating == "danger": - criticality = "Critical" - - return criticality diff --git a/unittests/scans/aws_scout2/aws_config.js b/unittests/scans/aws_scout2/aws_config.js deleted file mode 100644 index 6dc862a7ce..0000000000 --- a/unittests/scans/aws_scout2/aws_config.js +++ /dev/null @@ -1,2 +0,0 @@ -aws_info = -{"aws_account_id": "430150006394","last_run": {"cmd": "/home/damien/dd/.venv/bin/Scout2","ruleset_about": "This ruleset consists of numerous rules that are considered standard by the project's maintainers in an effort to avoid false-positive warnings. The rules enabled range from violations of well-known security best practices to gaps resulting from less-known security implications of AWS-specific mechanisms. Additional rules exist, some of them requiring extra-parameters to be configured, and some of them being applicable to a limited number of users. Consider using the RulesetGenerator tool to make the most of Scout2.","ruleset_name": "default","summary": {"awslambda": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 1,"rules_count": 0},"cloudformation": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 1},"cloudtrail": {"checked_items": 22,"flagged_items": 21,"max_level": "danger","resources_count": 0,"rules_count": 5},"cloudwatch": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 1},"directconnect": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 0},"ec2": {"checked_items": 653,"flagged_items": 83,"max_level": "danger","resources_count": 20,"rules_count": 23},"efs": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 0},"elasticache": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 0},"elb": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 1},"elbv2": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 3},"emr": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 0},"iam": {"checked_items": 80,"flagged_items": 10,"max_level": "danger","resources_count": 19,"rules_count": 31},"rds": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 17,"rules_count": 7},"redshift": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 6},"route53": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 3},"s3": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 19},"ses": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 2},"sns": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 7},"sqs": {"checked_items": 0,"flagged_items": 0,"max_level": "warning","resources_count": 0,"rules_count": 7},"vpc": {"checked_items": 250,"flagged_items": 199,"max_level": "warning","resources_count": 106,"rules_count": 8}},"time": "2021-03-19 13:32:13+0100","version": "3.2.1"},"metadata": {"analytics": {"emr": {"resources": {"clusters": {"api_call": "list_clusters","callbacks": [["match_security_groups_and_resources_callback",{"sg_id_attribute_name": "","sg_list_attribute_name": ["Ec2InstanceAttributes","EmrManagedMasterSecurityGroup"],"status_path": ["Status","State"]}],["match_security_groups_and_resources_callback",{"sg_id_attribute_name": "","sg_list_attribute_name": ["Ec2InstanceAttributes","EmrManagedSlaveSecurityGroup"],"status_path": ["Status","State"]}]],"cols": 2,"count": 0,"full_path": "services.emr.regions.id.vpcs.id.clusters","path": "services.emr.regions.id.vpcs.id.clusters","response": "Clusters","script": "services.emr.regions.vpcs.clusters"}}}},"compute": {"awslambda": {"resources": {"functions": {"api_call": "list_functions","callbacks": [["match_security_groups_and_resources_callback",{"sg_list_attribute_name": ["VpcConfig","SecurityGroupIds"],"status_path": ["Runtime"]}]],"count": 1,"full_path": "services.awslambda.regions.id.functions","path": "services.awslambda.regions.id.functions","response": "Functions","script": "services.awslambda.regions.functions"}}},"ec2": {"resources": {"instances": {"api_call": "describe_instances","callbacks": [["match_instances_and_subnets_callback",{}]],"cols": 2,"count": 0,"full_path": "services.ec2.regions.id.vpcs.id.instances","path": "services.ec2.regions.id.vpcs.id.instances","response": "Reservations","script": "services.ec2.regions.vpcs.instances"},"network_interfaces": {"api_call": "describe_network_interfaces","callbacks": [["match_security_groups_and_resources_callback",{"sg_id_attribute_name": "GroupId","sg_list_attribute_name": ["Groups"]}]],"count": 0,"full_path": "services.ec2.regions.id.vpcs.id.network_interfaces","hidden": true,"path": "services.ec2.regions.id.vpcs.id.network_interfaces","response": "NetworkInterfaces","script": "services.ec2.regions.vpcs.network_interfaces"},"security_groups": {"api_call": "describe_security_groups","cols": 2,"count": 20,"full_path": "services.ec2.regions.id.vpcs.id.security_groups","path": "services.ec2.regions.id.vpcs.id.security_groups","response": "SecurityGroups","script": "services.ec2.regions.vpcs.security_groups"},"snapshots": {"api_call": "describe_snapshots","cols": 2,"count": 0,"full_path": "services.ec2.regions.id.snapshots","params": {"OwnerIds": ["430150006394"]},"path": "services.ec2.regions.id.snapshots","response": "Snapshots","script": "services.ec2.regions.snapshots"},"volumes": {"api_call": "describe_volumes","cols": 2,"count": 0,"full_path": "services.ec2.regions.id.volumes","path": "services.ec2.regions.id.volumes","response": "Volumes","script": "services.ec2.regions.volumes"}},"summaries": {"external attack surface": {"callbacks": [["list_ec2_network_attack_surface_callback",{"path": "services.ec2.regions.id.vpcs.id.instances.id.network_interfaces.id.PrivateIpAddresses"}]],"cols": 1,"path": "services.ec2.external_attack_surface"}}},"elb": {"resources": {"elb_policies": {"cols": 2,"count": 0,"full_path": "services.elb.regions.id.elb_policies","path": "services.elb.regions.id.elb_policies","script": "services.elb.regions.elb_policies"},"elbs": {"api_call": "describe_load_balancers","callbacks": [["match_security_groups_and_resources_callback",{"sg_id_attribute_name": "GroupId","sg_list_attribute_name": ["security_groups"],"status_path": ["Scheme"]}],["get_lb_attack_surface",{}]],"cols": 2,"count": 0,"full_path": "services.elb.regions.id.vpcs.id.elbs","path": "services.elb.regions.id.vpcs.id.elbs","response": "LoadBalancerDescriptions","script": "services.elb.regions.vpcs.elbs"}},"summaries": {"external attack surface": {"cols": 1,"path": "services.elb.external_attack_surface"}}},"elbv2": {"resources": {"lbs": {"api_call": "describe_load_balancers","callbacks": [["match_security_groups_and_resources_callback",{"sg_id_attribute_name": "GroupId","sg_list_attribute_name": ["security_groups"],"status_path": ["State","Code"]}],["get_lb_attack_surface",{}]],"cols": 2,"count": 0,"full_path": "services.elbv2.regions.id.vpcs.id.lbs","path": "services.elbv2.regions.id.vpcs.id.lbs","response": "LoadBalancers","script": "services.elbv2.regions.vpcs.lbs"},"ssl_policies": {"api_call": "describe_ssl_policies","count": 0,"full_path": "services.elbv2.ssl_policies","hidden": true,"path": "services.elbv2.ssl_policies","response": "SslPolicies","script": "services.elbv2.ssl_policies"}},"summaries": {"external attack surface": {"cols": 1,"path": "services.elbv2.external_attack_surface"}}},"summaries": {"external attack surface": {"callbacks": [["merge",{"attribute": "external_attack_surface"}]],"cols": 1,"path": "service_groups.compute.summaries.external_attack_surface"}}},"database": {"elasticache": {"resources": {"clusters": {"api_call": "describe_cache_clusters","callbacks": [["match_security_groups_and_resources_callback",{"sg_id_attribute_name": "SecurityGroupId","sg_list_attribute_name": ["SecurityGroups"],"status_path": ["CacheClusterStatus"]}],["get_db_attack_surface",{}]],"cols": 2,"count": 0,"full_path": "services.elasticache.regions.id.vpcs.id.clusters","path": "services.elasticache.regions.id.vpcs.id.clusters","response": "CacheClusters","script": "services.elasticache.regions.vpcs.clusters"},"parameter_groups": {"api_to_call": "describe_db_parameter_groups","cols": 2,"count": 0,"full_path": "services.elasticache.regions.id.parameter_groups","path": "services.elasticache.regions.id.parameter_groups","response": "DBParameterGroups","script": "services.elasticache.regions.parameter_groups"},"security_groups": {"api_call": "describe_cache_security_groups","cols": 2,"count": 0,"full_path": "services.elasticache.regions.id.security_groups","no_exceptions": true,"path": "services.elasticache.regions.id.security_groups","response": "CacheSecurityGroups","script": "services.elasticache.regions.security_groups"},"subnet_groups": {"cols": 2,"count": 0,"full_path": "services.elasticache.regions.id.vpcs.id.subnet_groups","path": "services.elasticache.regions.id.vpcs.id.subnet_groups","script": "services.elasticache.regions.vpcs.subnet_groups"}}},"rds": {"resources": {"instances": {"api_call": "describe_db_instances","callbacks": [["match_security_groups_and_resources_callback",{"sg_id_attribute_name": "VpcSecurityGroupId","sg_list_attribute_name": ["VpcSecurityGroups"],"status_path": ["DBInstanceStatus"]}],["get_db_attack_surface",{}]],"cols": 2,"count": 0,"full_path": "services.rds.regions.id.vpcs.id.instances","path": "services.rds.regions.id.vpcs.id.instances","response": "DBInstances","script": "services.rds.regions.vpcs.instances"},"parameter_groups": {"api_call": "describe_db_parameter_groups","cols": 2,"count": 0,"full_path": "services.rds.regions.id.parameter_groups","path": "services.rds.regions.id.parameter_groups","response": "DBParameterGroups","script": "services.rds.regions.parameter_groups"},"security_groups": {"api_call": "describe_db_security_groups","cols": 2,"count": 17,"full_path": "services.rds.regions.id.security_groups","no_exceptions": true,"path": "services.rds.regions.id.security_groups","response": "DBSecurityGroups","script": "services.rds.regions.security_groups"},"snapshots": {"api_call": "describe_db_snapshots","cols": 2,"count": 0,"full_path": "services.rds.regions.id.vpcs.id.snapshots","path": "services.rds.regions.id.vpcs.id.snapshots","response": "DBSnapshots","script": "services.rds.regions.vpcs.snapshots"},"subnet_groups": {"api_call": "describe_db_subnet_groups","cols": 2,"count": 0,"full_path": "services.rds.regions.id.vpcs.id.subnet_groups","path": "services.rds.regions.id.vpcs.id.subnet_groups","response": "DBSubnetGroups","script": "services.rds.regions.vpcs.subnet_groups"}},"summaries": {"external attack surface": {"cols": 1,"path": "services.rds.external_attack_surface"}}},"redshift": {"resources": {"clusters": {"api_call": "describe_clusters","callbacks": [["match_security_groups_and_resources_callback",{"sg_id_attribute_name": "VpcSecurityGroupId","sg_list_attribute_name": ["VpcSecurityGroups"],"status_path": ["ClusterStatus"]}],["get_db_attack_surface",{}]],"cols": 2,"count": 0,"full_path": "services.redshift.regions.id.vpcs.id.clusters","path": "services.redshift.regions.id.vpcs.id.clusters","response": "Clusters","script": "services.redshift.regions.vpcs.clusters"},"parameter_groups": {"api_call": "describe_cluster_parameter_groups","cols": 2,"count": 0,"full_path": "services.redshift.regions.id.parameter_groups","path": "services.redshift.regions.id.parameter_groups","response": "ParameterGroups","script": "services.redshift.regions.parameter_groups"},"security_groups": {"api_call": "describe_cluster_security_groups","cols": 2,"count": 0,"full_path": "services.redshift.regions.id.security_groups","no_exceptions": true,"path": "services.redshift.regions.id.security_groups","response": "ClusterSecurityGroups","script": "services.redshift.regions.security_groups"}},"summaries": {"external attack surface": {"cols": 1,"path": "services.redshift.external_attack_surface"}}},"summaries": {"external attack surface": {"callbacks": [["merge",{"attribute": "external_attack_surface"}]],"cols": 1,"path": "service_groups.database.summaries.external_attack_surface"}}},"management": {"cloudformation": {"resources": {"stacks": {"api_call": "describe_stacks","callbacks": [["match_roles_and_cloudformation_stacks_callback",{}]],"cols": 2,"count": 0,"full_path": "services.cloudformation.regions.id.stacks","path": "services.cloudformation.regions.id.stacks","response": "Stacks","script": "services.cloudformation.regions.stacks"}}},"cloudtrail": {"resources": {"regions": {"cols": 2,"full_path": "services.cloudtrail.regions","path": "services.cloudtrail.regions","script": "services.cloudtrail.regions"},"trails": {"api_call": "describe_trails","cols": 2,"count": 0,"full_path": "services.cloudtrail.regions.id.trails","path": "services.cloudtrail.regions.id.trails","response": "trailList","script": "services.cloudtrail.regions.trails"}}},"cloudwatch": {"resources": {"alarms": {"api_call": "describe_alarms","cols": 2,"count": 0,"full_path": "services.cloudwatch.regions.id.alarms","path": "services.cloudwatch.regions.id.alarms","response": "MetricAlarms","script": "services.cloudwatch.regions.alarms"}},"summaries": {"statistics": {"cols": 1,"path": "services.cloudwatch.statistics"}}}},"messaging": {"ses": {"resources": {"identities": {"api_call": "list_identities","cols": 2,"count": 0,"full_path": "services.ses.regions.id.identities","path": "services.ses.regions.id.identities","response": "Identities","script": "services.ses.regions.identities"}}},"sns": {"resources": {"subscriptions": {"api_call": "list_subscriptions","count": 0,"full_path": "services.sns.regions.id.subscriptions","hidden": true,"path": "services.sns.regions.id.subscriptions","response": "Subscriptions","script": "services.sns.regions.subscriptions"},"topics": {"api_call": "list_topics","cols": 2,"count": 0,"full_path": "services.sns.regions.id.topics","path": "services.sns.regions.id.topics","response": "Topics","script": "services.sns.regions.topics"}}},"sqs": {"resources": {"queues": {"api_call": "list_queues","cols": 2,"count": 0,"full_path": "services.sqs.regions.id.queues","path": "services.sqs.regions.id.queues","response": "QueueUrls","script": "services.sqs.regions.queues"}}}},"network": {"directconnect": {"resources": {"connections": {"api_call": "describe_connections","cols": 2,"count": 0,"full_path": "services.directconnect.connections","path": "services.directconnect.connections","response": "connections","script": "services.directconnect.connections"}}},"route53": {"resources": {"domains": {"cols": 2,"count": 0,"full_path": "services.route53.domains","path": "services.route53.domains","script": "services.route53.domains"},"hosted_zones": {"cols": 2,"count": 0,"full_path": "services.route53.hosted_zones","path": "services.route53.hosted_zones","script": "services.route53.hosted_zones"}}},"vpc": {"resources": {"customer_gateways": {"api_call": "describe_customer_gateways","cols": 2,"count": 0,"full_path": "services.vpc.regions.id.customer_gateways","path": "services.vpc.regions.id.customer_gateways","response": "CustomerGateways","script": "services.vpc.regions.customer_gateways"},"flow_logs": {"api_call": "describe_flow_logs","callbacks": [["sort_vpc_flow_logs_callback",{}],["match_roles_and_vpc_flowlogs_callback",{}]],"count": 0,"full_path": "services.vpc.regions.id.flow_logs","hidden": true,"path": "services.vpc.regions.id.flow_logs","response": "FlowLogs","script": "services.vpc.regions.flow_logs"},"network_acls": {"api_call": "describe_network_acls","callbacks": [["match_network_acls_and_subnets_callback",{}],["process_network_acls_callback",{}]],"cols": 2,"count": 17,"full_path": "services.vpc.regions.id.vpcs.id.network_acls","path": "services.vpc.regions.id.vpcs.id.network_acls","response": "NetworkAcls","script": "services.vpc.regions.vpcs.network_acls"},"peering_connections": {"api_call": "describe_vpc_peering_connections","callbacks": [["process_vpc_peering_connections_callback",{}]],"count": 0,"full_path": "services.vpc.regions.id.peering_connections","hidden": true,"path": "services.vpc.regions.id.peering_connections","response": "VpcPeeringConnections","script": "services.vpc.regions.peering_connections"},"route_tables": {"api_call": "describe_route_tables","count": 17,"full_path": "services.vpc.regions.id.vpcs.id.route_tables","hidden": true,"path": "services.vpc.regions.id.vpcs.id.route_tables","response": "RouteTables","script": "services.vpc.regions.vpcs.route_tables"},"subnets": {"api_call": "describe_subnets","cols": 2,"count": 55,"full_path": "services.vpc.regions.id.vpcs.id.subnets","path": "services.vpc.regions.id.vpcs.id.subnets","response": "Subnets","script": "services.vpc.regions.vpcs.subnets"},"vpcs": {"api_call": "describe_vpcs","cols": 2,"count": 17,"full_path": "services.vpc.regions.id.vpcs","path": "services.vpc.regions.id.vpcs","response": "Vpcs","script": "services.vpc.regions.vpcs"},"vpn_connections": {"api_call": "describe_vpn_connections","cols": 2,"count": 0,"full_path": "services.vpc.regions.id.vpn_connections","path": "services.vpc.regions.id.vpn_connections","response": "VpnConnections","script": "services.vpc.regions.vpn_connections"},"vpn_gateways": {"api_call": "describe_vpn_gateways","cols": 2,"count": 0,"full_path": "services.vpc.regions.id.vpn_gateways","path": "services.vpc.regions.id.vpn_gateways","response": "VpnGateways","script": "services.vpc.regions.vpn_gateways"}}}},"security": {"iam": {"resources": {"groups": {"cols": 2,"count": 1,"full_path": "services.iam.groups","path": "services.iam.groups","script": "services.iam.groups"},"policies": {"cols": 2,"count": 8,"full_path": "services.iam.policies","path": "services.iam.policies","script": "services.iam.policies"},"roles": {"cols": 2,"count": 7,"full_path": "services.iam.roles","path": "services.iam.roles","script": "services.iam.roles"},"users": {"cols": 2,"count": 1,"full_path": "services.iam.users","path": "services.iam.users","script": "services.iam.users"}},"summaries": {"password_policy": {"cols": 1,"path": "services.iam.password_policy"},"permissions": {"cols": 1,"path": "services.iam.permissions"},"root_account": {"cols": 1,"path": "services.iam.credential_report."}}}},"storage": {"efs": {"hidden": true,"resources": {"file_systems": {"api_call": "describe_file_systems","callbacks": [["match_security_groups_and_resources_callback",{"sg_list_attribute_name": ["security_groups"],"status_path": ["LifeCycleState"]}]],"path": "services.efs.regions.id.file_systems","response": "FileSystems"}}},"s3": {"resources": {"buckets": {"cols": 2,"count": 0,"full_path": "services.s3.buckets","path": "services.s3.buckets","script": "services.s3.buckets"}}}}},"service_groups": {"compute": {"summaries": {"external_attack_surface": {}}},"database": {"summaries": {"external_attack_surface": {}}}},"service_list": ["cloudformation","cloudtrail","cloudwatch","directconnect","ec2","efs","elasticache","elb","elbv2","emr","iam","awslambda","redshift","rds","route53","route53domains","s3","ses","sns","sqs","vpc"],"services": {"awslambda": {"filters": {},"findings": {},"functions_count": 1,"regions": {"af-south-1": {"functions": {},"functions_count": 0,"region": "af-south-1"},"ap-east-1": {"functions": {},"functions_count": 0,"region": "ap-east-1"},"ap-northeast-1": {"functions": {},"functions_count": 0,"region": "ap-northeast-1"},"ap-northeast-2": {"functions": {},"functions_count": 0,"region": "ap-northeast-2"},"ap-northeast-3": {"functions": {},"functions_count": 0,"region": "ap-northeast-3"},"ap-south-1": {"functions": {},"functions_count": 0,"region": "ap-south-1"},"ap-southeast-1": {"functions": {},"functions_count": 0,"region": "ap-southeast-1"},"ap-southeast-2": {"functions": {},"functions_count": 0,"region": "ap-southeast-2"},"ca-central-1": {"functions": {},"functions_count": 0,"region": "ca-central-1"},"eu-central-1": {"functions": {},"functions_count": 0,"region": "eu-central-1"},"eu-north-1": {"functions": {},"functions_count": 0,"region": "eu-north-1"},"eu-south-1": {"functions": {},"functions_count": 0,"region": "eu-south-1"},"eu-west-1": {"functions": {"load-wikipedia": {"CodeSha256": "txY7sj38mwfot6uoeqMhNs4P/VycimyJcRBdlDBTyik=","CodeSize": 506,"Description": "","FunctionArn": "arn:aws:lambda:eu-west-1:430150006394:function:load-wikipedia","Handler": "lambda_function.lambda_handler","LastModified": "2019-01-25T17:47:21.038+0000","MemorySize": 128,"PackageType": "Zip","RevisionId": "9ec6c002-9048-4d53-a4c2-001e406827b3","Role": "arn:aws:iam::430150006394:role/service-role/load-wikipedia","Runtime": "python2.7","Timeout": 3,"TracingConfig": {"Mode": "PassThrough"},"Version": "$LATEST","name": "load-wikipedia"}},"functions_count": 1,"region": "eu-west-1"},"eu-west-2": {"functions": {},"functions_count": 0,"region": "eu-west-2"},"eu-west-3": {"functions": {},"functions_count": 0,"region": "eu-west-3"},"me-south-1": {"functions": {},"functions_count": 0,"region": "me-south-1"},"sa-east-1": {"functions": {},"functions_count": 0,"region": "sa-east-1"},"us-east-1": {"functions": {},"functions_count": 0,"region": "us-east-1"},"us-east-2": {"functions": {},"functions_count": 0,"region": "us-east-2"},"us-west-1": {"functions": {},"functions_count": 0,"region": "us-west-1"},"us-west-2": {"functions": {},"functions_count": 0,"region": "us-west-2"}},"regions_count": 21,"resource_types": {"global": [],"region": ["functions"],"vpc": []},"service": "lambda","targets": {"first_region": [["functions","Functions","list_functions",{},false]],"other_regions": [["functions","Functions","list_functions",{},false]]},"thread_config": {"list": 10,"parse": 20}},"cloudformation": {"filters": {},"findings": {"cloudformation-stack-with-role": {"checked_items": 0,"dashboard_name": "Stacks","description": "Role passed to stack","flagged_items": 0,"items": [],"level": "danger","path": "cloudformation.regions.id.stacks.id","rationale": "Passing a role to CloudFormation stacks may result in privilege escalation beause IAM users with privileges within the CloudFormation scope implicitly inherit the stack's role's permissions.","service": "CloudFormation"}},"regions": {"af-south-1": {"region": "af-south-1","stacks": {},"stacks_count": 0},"ap-east-1": {"region": "ap-east-1","stacks": {},"stacks_count": 0},"ap-northeast-1": {"region": "ap-northeast-1","stacks": {},"stacks_count": 0},"ap-northeast-2": {"region": "ap-northeast-2","stacks": {},"stacks_count": 0},"ap-northeast-3": {"region": "ap-northeast-3","stacks": {},"stacks_count": 0},"ap-south-1": {"region": "ap-south-1","stacks": {},"stacks_count": 0},"ap-southeast-1": {"region": "ap-southeast-1","stacks": {},"stacks_count": 0},"ap-southeast-2": {"region": "ap-southeast-2","stacks": {},"stacks_count": 0},"ca-central-1": {"region": "ca-central-1","stacks": {},"stacks_count": 0},"eu-central-1": {"region": "eu-central-1","stacks": {},"stacks_count": 0},"eu-north-1": {"region": "eu-north-1","stacks": {},"stacks_count": 0},"eu-south-1": {"region": "eu-south-1","stacks": {},"stacks_count": 0},"eu-west-1": {"region": "eu-west-1","stacks": {},"stacks_count": 0},"eu-west-2": {"region": "eu-west-2","stacks": {},"stacks_count": 0},"eu-west-3": {"region": "eu-west-3","stacks": {},"stacks_count": 0},"me-south-1": {"region": "me-south-1","stacks": {},"stacks_count": 0},"sa-east-1": {"region": "sa-east-1","stacks": {},"stacks_count": 0},"us-east-1": {"region": "us-east-1","stacks": {},"stacks_count": 0},"us-east-2": {"region": "us-east-2","stacks": {},"stacks_count": 0},"us-west-1": {"region": "us-west-1","stacks": {},"stacks_count": 0},"us-west-2": {"region": "us-west-2","stacks": {},"stacks_count": 0}},"regions_count": 21,"resource_types": {"global": [],"region": ["stacks"],"vpc": []},"service": "cloudformation","stacks_count": 0,"targets": {"first_region": [["stacks","Stacks","describe_stacks",{},false]],"other_regions": [["stacks","Stacks","describe_stacks",{},false]]},"thread_config": {"list": 10,"parse": 20}},"cloudtrail": {"DuplicatedGlobalServiceEvents": false,"IncludeGlobalServiceEvents": false,"data_logging_trails_count": 0,"filters": {},"findings": {"cloudtrail-duplicated-global-services-logging": {"checked_items": 1,"dashboard_name": "Configuration","description": "Global service logging duplicated","flagged_items": 0,"id_suffix": "IncludeGlobalServiceEvents","items": [],"level": "warning","path": "cloudtrail","rationale": "Global service logging is enabled in multiple Trails. While this does not jeopardize the security of the environment, duplicated entries in logs increase the difficulty to investate potential incidents.","service": "CloudTrail"},"cloudtrail-no-global-services-logging": {"checked_items": 1,"dashboard_name": "Configuration","description": "Global services logging disabled","flagged_items": 1,"id_suffix": "IncludeGlobalServiceEvents","items": ["cloudtrail.IncludeGlobalServiceEvents"],"level": "danger","path": "cloudtrail","rationale": "API activity for global services such as IAM and STS is not logged. Investigation of incidents will be incomplete due to the lack of information.","service": "CloudTrail"},"cloudtrail-no-log-file-validation": {"checked_items": 0,"dashboard_name": "Trails","description": "Log file validation disabled","flagged_items": 0,"id_suffix": "LogFileValidationDisabled","items": [],"level": "danger","path": "cloudtrail.regions.id.trails.id","rationale": "The lack of log file validation prevents one from verifying the integrity of the log files.","service": "CloudTrail"},"cloudtrail-no-logging": {"checked_items": 0,"dashboard_name": "Trails","description": "Logging disabled","flagged_items": 0,"id_suffix": "IsLogging","items": [],"level": "danger","path": "cloudtrail.regions.id.trails.id","rationale": "Logging is disabled for a given Trail. Depending on the configuration, logs for important API activity may be missing.","service": "CloudTrail"},"cloudtrail-not-configured": {"checked_items": 20,"dashboard_name": "Regions","description": "Not configured","flagged_items": 20,"id_suffix": "NotConfigured","items": ["cloudtrail.regions.af-south-1.NotConfigured","cloudtrail.regions.ap-east-1.NotConfigured","cloudtrail.regions.ap-northeast-1.NotConfigured","cloudtrail.regions.ap-northeast-2.NotConfigured","cloudtrail.regions.ap-south-1.NotConfigured","cloudtrail.regions.ap-southeast-1.NotConfigured","cloudtrail.regions.ap-southeast-2.NotConfigured","cloudtrail.regions.ca-central-1.NotConfigured","cloudtrail.regions.eu-central-1.NotConfigured","cloudtrail.regions.eu-north-1.NotConfigured","cloudtrail.regions.eu-south-1.NotConfigured","cloudtrail.regions.eu-west-1.NotConfigured","cloudtrail.regions.eu-west-2.NotConfigured","cloudtrail.regions.eu-west-3.NotConfigured","cloudtrail.regions.me-south-1.NotConfigured","cloudtrail.regions.sa-east-1.NotConfigured","cloudtrail.regions.us-east-1.NotConfigured","cloudtrail.regions.us-east-2.NotConfigured","cloudtrail.regions.us-west-1.NotConfigured","cloudtrail.regions.us-west-2.NotConfigured"],"level": "danger","path": "cloudtrail.regions.id","rationale": "CloudTrail is not configured, which means that API activity is not logged.","service": "CloudTrail"}},"regions": {"af-south-1": {"region": "af-south-1","regions": {},"regions_count": 0,"trails": {},"trails_count": 0},"ap-east-1": {"region": "ap-east-1","regions": {},"regions_count": 0,"trails": {},"trails_count": 0},"ap-northeast-1": {"region": "ap-northeast-1","regions": {},"regions_count": 0,"trails": {},"trails_count": 0},"ap-northeast-2": {"region": "ap-northeast-2","regions": {},"regions_count": 0,"trails": {},"trails_count": 0},"ap-south-1": {"region": "ap-south-1","regions": {},"regions_count": 0,"trails": {},"trails_count": 0},"ap-southeast-1": {"region": "ap-southeast-1","regions": {},"regions_count": 0,"trails": {},"trails_count": 0},"ap-southeast-2": {"region": "ap-southeast-2","regions": {},"regions_count": 0,"trails": {},"trails_count": 0},"ca-central-1": {"region": "ca-central-1","regions": {},"regions_count": 0,"trails": {},"trails_count": 0},"eu-central-1": {"region": "eu-central-1","regions": {},"regions_count": 0,"trails": {},"trails_count": 0},"eu-north-1": {"region": "eu-north-1","regions": {},"regions_count": 0,"trails": {},"trails_count": 0},"eu-south-1": {"region": "eu-south-1","regions": {},"regions_count": 0,"trails": {},"trails_count": 0},"eu-west-1": {"region": "eu-west-1","regions": {},"regions_count": 0,"trails": {},"trails_count": 0},"eu-west-2": {"region": "eu-west-2","regions": {},"regions_count": 0,"trails": {},"trails_count": 0},"eu-west-3": {"region": "eu-west-3","regions": {},"regions_count": 0,"trails": {},"trails_count": 0},"me-south-1": {"region": "me-south-1","regions": {},"regions_count": 0,"trails": {},"trails_count": 0},"sa-east-1": {"region": "sa-east-1","regions": {},"regions_count": 0,"trails": {},"trails_count": 0},"us-east-1": {"region": "us-east-1","regions": {},"regions_count": 0,"trails": {},"trails_count": 0},"us-east-2": {"region": "us-east-2","regions": {},"regions_count": 0,"trails": {},"trails_count": 0},"us-west-1": {"region": "us-west-1","regions": {},"regions_count": 0,"trails": {},"trails_count": 0},"us-west-2": {"region": "us-west-2","regions": {},"regions_count": 0,"trails": {},"trails_count": 0}},"regions_count": 20,"resource_types": {"global": ["regions"],"region": ["trails"],"vpc": []},"service": "cloudtrail","targets": {"first_region": [["trails","trailList","describe_trails",{},false]],"other_regions": [["trails","trailList","describe_trails",{},false]]},"thread_config": {"list": 10,"parse": 20},"trails_count": 0},"cloudwatch": {"alarms_count": 0,"filters": {},"findings": {"cloudwatch-alarm-without-actions": {"checked_items": 0,"dashboard_name": "Alarms","description": "Alarm without action","flagged_items": 0,"id_suffix": "NoActions","items": [],"level": "warning","path": "cloudwatch.regions.id.alarms.id","rationale": "Each alarm should have at least one action","service": "CloudWatch"}},"regions": {"af-south-1": {"alarms": {},"alarms_count": 0,"region": "af-south-1"},"ap-east-1": {"alarms": {},"alarms_count": 0,"region": "ap-east-1"},"ap-northeast-1": {"alarms": {},"alarms_count": 0,"region": "ap-northeast-1"},"ap-northeast-2": {"alarms": {},"alarms_count": 0,"region": "ap-northeast-2"},"ap-northeast-3": {"alarms": {},"alarms_count": 0,"region": "ap-northeast-3"},"ap-south-1": {"alarms": {},"alarms_count": 0,"region": "ap-south-1"},"ap-southeast-1": {"alarms": {},"alarms_count": 0,"region": "ap-southeast-1"},"ap-southeast-2": {"alarms": {},"alarms_count": 0,"region": "ap-southeast-2"},"ca-central-1": {"alarms": {},"alarms_count": 0,"region": "ca-central-1"},"eu-central-1": {"alarms": {},"alarms_count": 0,"region": "eu-central-1"},"eu-north-1": {"alarms": {},"alarms_count": 0,"region": "eu-north-1"},"eu-south-1": {"alarms": {},"alarms_count": 0,"region": "eu-south-1"},"eu-west-1": {"alarms": {},"alarms_count": 0,"region": "eu-west-1"},"eu-west-2": {"alarms": {},"alarms_count": 0,"region": "eu-west-2"},"eu-west-3": {"alarms": {},"alarms_count": 0,"region": "eu-west-3"},"me-south-1": {"alarms": {},"alarms_count": 0,"region": "me-south-1"},"sa-east-1": {"alarms": {},"alarms_count": 0,"region": "sa-east-1"},"us-east-1": {"alarms": {},"alarms_count": 0,"region": "us-east-1"},"us-east-2": {"alarms": {},"alarms_count": 0,"region": "us-east-2"},"us-west-1": {"alarms": {},"alarms_count": 0,"region": "us-west-1"},"us-west-2": {"alarms": {},"alarms_count": 0,"region": "us-west-2"}},"regions_count": 21,"resource_types": {"global": [],"region": ["alarms"],"vpc": []},"service": "cloudwatch","targets": {"first_region": [["alarms","MetricAlarms","describe_alarms",{},false]],"other_regions": [["alarms","MetricAlarms","describe_alarms",{},false]]},"thread_config": {"list": 10,"parse": 20}},"directconnect": {"connections_count": 0,"filters": {},"findings": {},"regions": {"af-south-1": {"connections": {},"connections_count": 0,"region": "af-south-1"},"ap-east-1": {"connections": {},"connections_count": 0,"region": "ap-east-1"},"ap-northeast-1": {"connections": {},"connections_count": 0,"region": "ap-northeast-1"},"ap-northeast-2": {"connections": {},"connections_count": 0,"region": "ap-northeast-2"},"ap-northeast-3": {"connections": {},"connections_count": 0,"region": "ap-northeast-3"},"ap-south-1": {"connections": {},"connections_count": 0,"region": "ap-south-1"},"ap-southeast-1": {"connections": {},"connections_count": 0,"region": "ap-southeast-1"},"ap-southeast-2": {"connections": {},"connections_count": 0,"region": "ap-southeast-2"},"ca-central-1": {"connections": {},"connections_count": 0,"region": "ca-central-1"},"eu-central-1": {"connections": {},"connections_count": 0,"region": "eu-central-1"},"eu-north-1": {"connections": {},"connections_count": 0,"region": "eu-north-1"},"eu-south-1": {"connections": {},"connections_count": 0,"region": "eu-south-1"},"eu-west-1": {"connections": {},"connections_count": 0,"region": "eu-west-1"},"eu-west-2": {"connections": {},"connections_count": 0,"region": "eu-west-2"},"eu-west-3": {"connections": {},"connections_count": 0,"region": "eu-west-3"},"me-south-1": {"connections": {},"connections_count": 0,"region": "me-south-1"},"sa-east-1": {"connections": {},"connections_count": 0,"region": "sa-east-1"},"us-east-1": {"connections": {},"connections_count": 0,"region": "us-east-1"},"us-east-2": {"connections": {},"connections_count": 0,"region": "us-east-2"},"us-west-1": {"connections": {},"connections_count": 0,"region": "us-west-1"},"us-west-2": {"connections": {},"connections_count": 0,"region": "us-west-2"}},"regions_count": 21,"resource_types": {"global": ["connections"],"region": [],"vpc": []},"service": "directconnect","targets": {"first_region": [["connections","connections","describe_connections",{},false]],"other_regions": []},"thread_config": {"list": 10,"parse": 20}},"ec2": {"filters": {"ec2-instance-with-open-nacls": {"checked_items": 0,"dashboard_name": "ENIs","description": "Public instance with open NACLs","display_path": "ec2.regions.id.vpcs.id.instances.id","flagged_items": 0,"items": [],"level": "","path": "ec2.regions.id.vpcs.id.instances.id.network_interfaces.id","rationale": "","service": "EC2"},"ec2-security-group-with-public-cidr-grant": {"checked_items": 6,"dashboard_name": "Rules","description": "Security group whitelists public CIDRs","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 6,"items": ["ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.0-65535.cidrs.0.CIDR","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.0.CIDR","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.1.CIDR","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.2.CIDR","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.3.CIDR","ec2.regions.eu-west-3.vpcs.vpc-87d3fdee.security_groups.sg-000c4c21c24f75b85.rules.ingress.protocols.TCP.ports.22.cidrs.0.CIDR"],"level": "","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.ingress.protocols.id.ports.id.cidrs.id.CIDR","rationale": "N/A","service": "EC2"}},"findings": {"ec2-default-security-group-in-use": {"checked_items": 20,"dashboard_name": "Security groups","description": "Default security groups in use","flagged_items": 0,"id_suffix": "default_in_use","items": [],"level": "warning","path": "ec2.regions.id.vpcs.id.security_groups.id","rationale": "N/A","service": "EC2"},"ec2-default-security-group-with-rules": {"checked_items": 40,"dashboard_name": "Rulesets","description": "Non-empty rulesets for default security groups","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 34,"id_suffix": "default_with_rules","items": ["ec2.regions.ap-northeast-1.vpcs.vpc-0cbc506a.security_groups.sg-6569b32b.rules.ingress.default_with_rules","ec2.regions.ap-northeast-1.vpcs.vpc-0cbc506a.security_groups.sg-6569b32b.rules.egress.default_with_rules","ec2.regions.ap-northeast-2.vpcs.vpc-73f44e18.security_groups.sg-854e9bfe.rules.ingress.default_with_rules","ec2.regions.ap-northeast-2.vpcs.vpc-73f44e18.security_groups.sg-854e9bfe.rules.egress.default_with_rules","ec2.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.security_groups.sg-9be71df6.rules.ingress.default_with_rules","ec2.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.security_groups.sg-9be71df6.rules.egress.default_with_rules","ec2.regions.ap-south-1.vpcs.vpc-2651a14d.security_groups.sg-3e983346.rules.ingress.default_with_rules","ec2.regions.ap-south-1.vpcs.vpc-2651a14d.security_groups.sg-3e983346.rules.egress.default_with_rules","ec2.regions.ap-southeast-1.vpcs.vpc-04ed1062.security_groups.sg-71eb4839.rules.ingress.default_with_rules","ec2.regions.ap-southeast-1.vpcs.vpc-04ed1062.security_groups.sg-71eb4839.rules.egress.default_with_rules","ec2.regions.ap-southeast-2.vpcs.vpc-5d22c33b.security_groups.sg-8a48ccc0.rules.ingress.default_with_rules","ec2.regions.ap-southeast-2.vpcs.vpc-5d22c33b.security_groups.sg-8a48ccc0.rules.egress.default_with_rules","ec2.regions.ca-central-1.vpcs.vpc-b5113ddd.security_groups.sg-62215504.rules.ingress.default_with_rules","ec2.regions.ca-central-1.vpcs.vpc-b5113ddd.security_groups.sg-62215504.rules.egress.default_with_rules","ec2.regions.eu-central-1.vpcs.vpc-78b43312.security_groups.sg-c1194bbf.rules.ingress.default_with_rules","ec2.regions.eu-central-1.vpcs.vpc-78b43312.security_groups.sg-c1194bbf.rules.egress.default_with_rules","ec2.regions.eu-north-1.vpcs.vpc-fa259d93.security_groups.sg-09c1e96a.rules.ingress.default_with_rules","ec2.regions.eu-north-1.vpcs.vpc-fa259d93.security_groups.sg-09c1e96a.rules.egress.default_with_rules","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-186a6a69.rules.ingress.default_with_rules","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-186a6a69.rules.egress.default_with_rules","ec2.regions.eu-west-2.vpcs.vpc-3fa2fa57.security_groups.sg-223b755a.rules.ingress.default_with_rules","ec2.regions.eu-west-2.vpcs.vpc-3fa2fa57.security_groups.sg-223b755a.rules.egress.default_with_rules","ec2.regions.eu-west-3.vpcs.vpc-87d3fdee.security_groups.sg-4cc9d827.rules.ingress.default_with_rules","ec2.regions.eu-west-3.vpcs.vpc-87d3fdee.security_groups.sg-4cc9d827.rules.egress.default_with_rules","ec2.regions.sa-east-1.vpcs.vpc-b14fa4d7.security_groups.sg-3965844c.rules.ingress.default_with_rules","ec2.regions.sa-east-1.vpcs.vpc-b14fa4d7.security_groups.sg-3965844c.rules.egress.default_with_rules","ec2.regions.us-east-1.vpcs.vpc-ba1cbdc7.security_groups.sg-4574a94e.rules.ingress.default_with_rules","ec2.regions.us-east-1.vpcs.vpc-ba1cbdc7.security_groups.sg-4574a94e.rules.egress.default_with_rules","ec2.regions.us-east-2.vpcs.vpc-e429ad8f.security_groups.sg-a81474db.rules.ingress.default_with_rules","ec2.regions.us-east-2.vpcs.vpc-e429ad8f.security_groups.sg-a81474db.rules.egress.default_with_rules","ec2.regions.us-west-1.vpcs.vpc-6e6fa508.security_groups.sg-778f4e3e.rules.ingress.default_with_rules","ec2.regions.us-west-1.vpcs.vpc-6e6fa508.security_groups.sg-778f4e3e.rules.egress.default_with_rules","ec2.regions.us-west-2.vpcs.vpc-d45709ac.security_groups.sg-a9b5628e.rules.ingress.default_with_rules","ec2.regions.us-west-2.vpcs.vpc-d45709ac.security_groups.sg-a9b5628e.rules.egress.default_with_rules"],"level": "warning","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id","rationale": "N/A","service": "EC2"},"ec2-ebs-volume-not-encrypted": {"checked_items": 0,"dashboard_name": "Volumes","description": "EBS volume not encrypted","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.volumes.id","rationale": "Enabling encryption of EBS volumes ensures that data is encrypted both at-rest and in-transit (between an instance and its attached EBS storage).","service": "EC2"},"ec2-security-group-opens-DNS-port-to-all": {"checked_items": 26,"dashboard_name": "Rules","description": "DNS port open to all","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "N/A","service": "EC2"},"ec2-security-group-opens-MongoDB-port-to-all": {"checked_items": 26,"dashboard_name": "Rules","description": "MongoDB port open to all","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "N/A","service": "EC2"},"ec2-security-group-opens-MsSQL-port-to-all": {"checked_items": 26,"dashboard_name": "Rules","description": "MsSQL port open to all","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "N/A","service": "EC2"},"ec2-security-group-opens-MySQL-port-to-all": {"checked_items": 26,"dashboard_name": "Rules","description": "MySQL port open to all","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "N/A","service": "EC2"},"ec2-security-group-opens-NFS-port-to-all": {"checked_items": 26,"dashboard_name": "Rules","description": "NFS port open to all","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "N/A","service": "EC2"},"ec2-security-group-opens-Oracle DB-port-to-all": {"checked_items": 26,"dashboard_name": "Rules","description": "Oracle DB port open to all","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "N/A","service": "EC2"},"ec2-security-group-opens-PostgreSQL-port-to-all": {"checked_items": 26,"dashboard_name": "Rules","description": "PostgreSQL port open to all","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "N/A","service": "EC2"},"ec2-security-group-opens-RDP-port-to-all": {"checked_items": 26,"dashboard_name": "Rules","description": "RDP port open to all","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "N/A","service": "EC2"},"ec2-security-group-opens-SMTP-port-to-all": {"checked_items": 26,"dashboard_name": "Rules","description": "SMTP port open to all","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "N/A","service": "EC2"},"ec2-security-group-opens-SSH-port-to-all": {"checked_items": 26,"dashboard_name": "Rules","description": "SSH port open to all","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "N/A","service": "EC2"},"ec2-security-group-opens-TCP-port-to-all": {"checked_items": 26,"dashboard_name": "Rules","description": "TCP port open to all","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "warning","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "N/A","service": "EC2"},"ec2-security-group-opens-UDP-port-to-all": {"checked_items": 26,"dashboard_name": "Rules","description": "UDP port open to all","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "warning","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "N/A","service": "EC2"},"ec2-security-group-opens-all-ports": {"checked_items": 45,"dashboard_name": "Rules","description": "All ports open","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 21,"items": ["ec2.regions.ap-northeast-1.vpcs.vpc-0cbc506a.security_groups.sg-6569b32b.rules.ingress.protocols.ALL.ports.N/A","ec2.regions.ap-northeast-2.vpcs.vpc-73f44e18.security_groups.sg-854e9bfe.rules.ingress.protocols.ALL.ports.N/A","ec2.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.security_groups.sg-9be71df6.rules.ingress.protocols.ALL.ports.N/A","ec2.regions.ap-south-1.vpcs.vpc-2651a14d.security_groups.sg-3e983346.rules.ingress.protocols.ALL.ports.N/A","ec2.regions.ap-southeast-1.vpcs.vpc-04ed1062.security_groups.sg-71eb4839.rules.ingress.protocols.ALL.ports.N/A","ec2.regions.ap-southeast-2.vpcs.vpc-5d22c33b.security_groups.sg-8a48ccc0.rules.ingress.protocols.ALL.ports.N/A","ec2.regions.ca-central-1.vpcs.vpc-b5113ddd.security_groups.sg-62215504.rules.ingress.protocols.ALL.ports.N/A","ec2.regions.eu-central-1.vpcs.vpc-78b43312.security_groups.sg-c1194bbf.rules.ingress.protocols.ALL.ports.N/A","ec2.regions.eu-north-1.vpcs.vpc-fa259d93.security_groups.sg-09c1e96a.rules.ingress.protocols.ALL.ports.N/A","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-02063087593480392.rules.ingress.protocols.TCP.ports.0-65535","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-02063087593480392.rules.ingress.protocols.UDP.ports.0-65535","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.0-65535","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.UDP.ports.0-65535","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-186a6a69.rules.ingress.protocols.ALL.ports.N/A","ec2.regions.eu-west-2.vpcs.vpc-3fa2fa57.security_groups.sg-223b755a.rules.ingress.protocols.ALL.ports.N/A","ec2.regions.eu-west-3.vpcs.vpc-87d3fdee.security_groups.sg-4cc9d827.rules.ingress.protocols.ALL.ports.N/A","ec2.regions.sa-east-1.vpcs.vpc-b14fa4d7.security_groups.sg-3965844c.rules.ingress.protocols.ALL.ports.N/A","ec2.regions.us-east-1.vpcs.vpc-ba1cbdc7.security_groups.sg-4574a94e.rules.ingress.protocols.ALL.ports.N/A","ec2.regions.us-east-2.vpcs.vpc-e429ad8f.security_groups.sg-a81474db.rules.ingress.protocols.ALL.ports.N/A","ec2.regions.us-west-1.vpcs.vpc-6e6fa508.security_groups.sg-778f4e3e.rules.ingress.protocols.ALL.ports.N/A","ec2.regions.us-west-2.vpcs.vpc-d45709ac.security_groups.sg-a9b5628e.rules.ingress.protocols.ALL.ports.N/A"],"level": "warning","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id","rationale": "N/A","service": "EC2"},"ec2-security-group-opens-all-ports-to-all": {"checked_items": 26,"dashboard_name": "Rules","description": "All ports open to all","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "N/A","service": "EC2"},"ec2-security-group-opens-all-ports-to-self": {"checked_items": 29,"dashboard_name": "Rules","description": "Unrestricted network traffic within security group","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 21,"items": ["ec2.regions.ap-northeast-1.vpcs.vpc-0cbc506a.security_groups.sg-6569b32b.rules.ingress.protocols.ALL.ports.N/A.security_groups.0","ec2.regions.ap-northeast-2.vpcs.vpc-73f44e18.security_groups.sg-854e9bfe.rules.ingress.protocols.ALL.ports.N/A.security_groups.0","ec2.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.security_groups.sg-9be71df6.rules.ingress.protocols.ALL.ports.N/A.security_groups.0","ec2.regions.ap-south-1.vpcs.vpc-2651a14d.security_groups.sg-3e983346.rules.ingress.protocols.ALL.ports.N/A.security_groups.0","ec2.regions.ap-southeast-1.vpcs.vpc-04ed1062.security_groups.sg-71eb4839.rules.ingress.protocols.ALL.ports.N/A.security_groups.0","ec2.regions.ap-southeast-2.vpcs.vpc-5d22c33b.security_groups.sg-8a48ccc0.rules.ingress.protocols.ALL.ports.N/A.security_groups.0","ec2.regions.ca-central-1.vpcs.vpc-b5113ddd.security_groups.sg-62215504.rules.ingress.protocols.ALL.ports.N/A.security_groups.0","ec2.regions.eu-central-1.vpcs.vpc-78b43312.security_groups.sg-c1194bbf.rules.ingress.protocols.ALL.ports.N/A.security_groups.0","ec2.regions.eu-north-1.vpcs.vpc-fa259d93.security_groups.sg-09c1e96a.rules.ingress.protocols.ALL.ports.N/A.security_groups.0","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-02063087593480392.rules.ingress.protocols.TCP.ports.0-65535.security_groups.0","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-02063087593480392.rules.ingress.protocols.UDP.ports.0-65535.security_groups.0","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.0-65535.security_groups.1","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.UDP.ports.0-65535.security_groups.1","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-186a6a69.rules.ingress.protocols.ALL.ports.N/A.security_groups.0","ec2.regions.eu-west-2.vpcs.vpc-3fa2fa57.security_groups.sg-223b755a.rules.ingress.protocols.ALL.ports.N/A.security_groups.0","ec2.regions.eu-west-3.vpcs.vpc-87d3fdee.security_groups.sg-4cc9d827.rules.ingress.protocols.ALL.ports.N/A.security_groups.0","ec2.regions.sa-east-1.vpcs.vpc-b14fa4d7.security_groups.sg-3965844c.rules.ingress.protocols.ALL.ports.N/A.security_groups.0","ec2.regions.us-east-1.vpcs.vpc-ba1cbdc7.security_groups.sg-4574a94e.rules.ingress.protocols.ALL.ports.N/A.security_groups.0","ec2.regions.us-east-2.vpcs.vpc-e429ad8f.security_groups.sg-a81474db.rules.ingress.protocols.ALL.ports.N/A.security_groups.0","ec2.regions.us-west-1.vpcs.vpc-6e6fa508.security_groups.sg-778f4e3e.rules.ingress.protocols.ALL.ports.N/A.security_groups.0","ec2.regions.us-west-2.vpcs.vpc-d45709ac.security_groups.sg-a9b5628e.rules.ingress.protocols.ALL.ports.N/A.security_groups.0"],"level": "warning","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.security_groups.id","rationale": "N/A","service": "EC2"},"ec2-security-group-opens-plaintext-port-FTP": {"checked_items": 45,"dashboard_name": "Rules","description": "FTP port open","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id","rationale": "N/A","service": "EC2"},"ec2-security-group-opens-plaintext-port-Telnet": {"checked_items": 45,"dashboard_name": "Rules","description": "Telnet port open","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id","rationale": "N/A","service": "EC2"},"ec2-security-group-opens-port-range": {"checked_items": 45,"dashboard_name": "Rules","description": "Use of port ranges","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "warning","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id","rationale": "N/A","service": "EC2"},"ec2-security-group-whitelists-aws": {"checked_items": 26,"dashboard_name": "Rules","description": "Security group whitelists AWS CIDRs","display_path": "ec2.regions.id.vpcs.id.security_groups.id","flagged_items": 4,"items": ["ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.0.CIDR","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.1.CIDR","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.2.CIDR","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171.rules.ingress.protocols.TCP.ports.8443.cidrs.3.CIDR"],"level": "danger","path": "ec2.regions.id.vpcs.id.security_groups.id.rules.id.protocols.id.ports.id.cidrs.id.CIDR","rationale": "N/A","service": "EC2"},"ec2-unused-security-group": {"checked_items": 20,"dashboard_name": "Security groups","description": "Unused security groups","flagged_items": 3,"items": ["ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-02063087593480392","ec2.regions.eu-west-1.vpcs.vpc-f24c7994.security_groups.sg-0c59ae38c42100171","ec2.regions.eu-west-3.vpcs.vpc-87d3fdee.security_groups.sg-000c4c21c24f75b85"],"level": "warning","path": "ec2.regions.id.vpcs.id.security_groups.id","rationale": "N/A","service": "EC2"}},"instances_count": 0,"network_interfaces_count": 0,"regions": {"af-south-1": {"instances_count": 0,"network_interfaces_count": 0,"region": "af-south-1","security_groups_count": 0,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpc_resource_types": ["instances","security_groups","network_interfaces"],"vpcs": {}},"ap-east-1": {"instances_count": 0,"network_interfaces_count": 0,"region": "ap-east-1","security_groups_count": 0,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpc_resource_types": ["instances","security_groups","network_interfaces"],"vpcs": {}},"ap-northeast-1": {"instances_count": 0,"network_interfaces_count": 0,"region": "ap-northeast-1","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpc_resource_types": ["instances","security_groups","network_interfaces"],"vpcs": {"vpc-0cbc506a": {"instances": {},"name": null,"network_interfaces": {},"security_groups": {"sg-6569b32b": {"description": "default VPC security group","id": "sg-6569b32b","name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"security_groups": [{"GroupId": "sg-6569b32b","GroupName": "default","UserId": "430150006394"}]}}}}}}}}}}},"ap-northeast-2": {"instances_count": 0,"network_interfaces_count": 0,"region": "ap-northeast-2","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpc_resource_types": ["instances","security_groups","network_interfaces"],"vpcs": {"vpc-73f44e18": {"instances": {},"name": null,"network_interfaces": {},"security_groups": {"sg-854e9bfe": {"description": "default VPC security group","id": "sg-854e9bfe","name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"security_groups": [{"GroupId": "sg-854e9bfe","GroupName": "default","UserId": "430150006394"}]}}}}}}}}}}},"ap-northeast-3": {"instances_count": 0,"network_interfaces_count": 0,"region": "ap-northeast-3","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpc_resource_types": ["instances","security_groups","network_interfaces"],"vpcs": {"vpc-47b7dd2e": {"instances": {},"name": null,"network_interfaces": {},"security_groups": {"sg-9be71df6": {"description": "default VPC security group","id": "sg-9be71df6","name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"security_groups": [{"GroupId": "sg-9be71df6","GroupName": "default","UserId": "430150006394"}]}}}}}}}}}}},"ap-south-1": {"instances_count": 0,"network_interfaces_count": 0,"region": "ap-south-1","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpc_resource_types": ["instances","security_groups","network_interfaces"],"vpcs": {"vpc-2651a14d": {"instances": {},"name": null,"network_interfaces": {},"security_groups": {"sg-3e983346": {"description": "default VPC security group","id": "sg-3e983346","name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"security_groups": [{"GroupId": "sg-3e983346","GroupName": "default","UserId": "430150006394"}]}}}}}}}}}}},"ap-southeast-1": {"instances_count": 0,"network_interfaces_count": 0,"region": "ap-southeast-1","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpc_resource_types": ["instances","security_groups","network_interfaces"],"vpcs": {"vpc-04ed1062": {"instances": {},"name": null,"network_interfaces": {},"security_groups": {"sg-71eb4839": {"description": "default VPC security group","id": "sg-71eb4839","name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"security_groups": [{"GroupId": "sg-71eb4839","GroupName": "default","UserId": "430150006394"}]}}}}}}}}}}},"ap-southeast-2": {"instances_count": 0,"network_interfaces_count": 0,"region": "ap-southeast-2","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpc_resource_types": ["instances","security_groups","network_interfaces"],"vpcs": {"vpc-5d22c33b": {"instances": {},"name": null,"network_interfaces": {},"security_groups": {"sg-8a48ccc0": {"description": "default VPC security group","id": "sg-8a48ccc0","name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"security_groups": [{"GroupId": "sg-8a48ccc0","GroupName": "default","UserId": "430150006394"}]}}}}}}}}}}},"ca-central-1": {"instances_count": 0,"network_interfaces_count": 0,"region": "ca-central-1","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpc_resource_types": ["instances","security_groups","network_interfaces"],"vpcs": {"vpc-b5113ddd": {"instances": {},"name": null,"network_interfaces": {},"security_groups": {"sg-62215504": {"description": "default VPC security group","id": "sg-62215504","name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"security_groups": [{"GroupId": "sg-62215504","GroupName": "default","UserId": "430150006394"}]}}}}}}}}}}},"eu-central-1": {"instances_count": 0,"network_interfaces_count": 0,"region": "eu-central-1","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpc_resource_types": ["instances","security_groups","network_interfaces"],"vpcs": {"vpc-78b43312": {"instances": {},"name": null,"network_interfaces": {},"security_groups": {"sg-c1194bbf": {"description": "default VPC security group","id": "sg-c1194bbf","name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"security_groups": [{"GroupId": "sg-c1194bbf","GroupName": "default","UserId": "430150006394"}]}}}}}}}}}}},"eu-north-1": {"instances_count": 0,"network_interfaces_count": 0,"region": "eu-north-1","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpc_resource_types": ["instances","security_groups","network_interfaces"],"vpcs": {"vpc-fa259d93": {"instances": {},"name": null,"network_interfaces": {},"security_groups": {"sg-09c1e96a": {"description": "default VPC security group","id": "sg-09c1e96a","name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"security_groups": [{"GroupId": "sg-09c1e96a","GroupName": "default","UserId": "430150006394"}]}}}}}}}}}}},"eu-south-1": {"instances_count": 0,"network_interfaces_count": 0,"region": "eu-south-1","security_groups_count": 0,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpc_resource_types": ["instances","security_groups","network_interfaces"],"vpcs": {}},"eu-west-1": {"instances_count": 0,"network_interfaces_count": 0,"region": "eu-west-1","security_groups_count": 3,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpc_resource_types": ["instances","security_groups","network_interfaces"],"vpcs": {"vpc-f24c7994": {"instances": {},"name": null,"network_interfaces": {},"security_groups": {"sg-02063087593480392": {"description": "Slave group for Elastic MapReduce created on 2019-01-26T08:00:38.387Z","id": "sg-02063087593480392","name": "ElasticMapReduce-slave","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 6,"protocols": {"ICMP": {"ports": {"ALL": {"security_groups": [{"GroupId": "sg-02063087593480392","GroupName": "ElasticMapReduce-slave","UserId": "430150006394"},{"GroupId": "sg-0c59ae38c42100171","GroupName": "ElasticMapReduce-master","UserId": "430150006394"}]}}},"TCP": {"ports": {"0-65535": {"security_groups": [{"GroupId": "sg-02063087593480392","GroupName": "ElasticMapReduce-slave","UserId": "430150006394"},{"GroupId": "sg-0c59ae38c42100171","GroupName": "ElasticMapReduce-master","UserId": "430150006394"}]}}},"UDP": {"ports": {"0-65535": {"security_groups": [{"GroupId": "sg-02063087593480392","GroupName": "ElasticMapReduce-slave","UserId": "430150006394"},{"GroupId": "sg-0c59ae38c42100171","GroupName": "ElasticMapReduce-master","UserId": "430150006394"}]}}}}}}},"sg-0c59ae38c42100171": {"description": "Master group for Elastic MapReduce created on 2019-01-26T08:00:38.387Z","id": "sg-0c59ae38c42100171","name": "ElasticMapReduce-master","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 11,"protocols": {"ICMP": {"ports": {"ALL": {"security_groups": [{"GroupId": "sg-02063087593480392","GroupName": "ElasticMapReduce-slave","UserId": "430150006394"},{"GroupId": "sg-0c59ae38c42100171","GroupName": "ElasticMapReduce-master","UserId": "430150006394"}]}}},"TCP": {"ports": {"0-65535": {"cidrs": [{"CIDR": "88.171.207.128/30"}],"security_groups": [{"GroupId": "sg-02063087593480392","GroupName": "ElasticMapReduce-slave","UserId": "430150006394"},{"GroupId": "sg-0c59ae38c42100171","GroupName": "ElasticMapReduce-master","UserId": "430150006394"}]},"8443": {"cidrs": [{"CIDR": "87.238.84.64/29"},{"CIDR": "54.239.99.0/24"},{"CIDR": "87.238.80.64/29"},{"CIDR": "54.240.197.0/24"}]}}},"UDP": {"ports": {"0-65535": {"security_groups": [{"GroupId": "sg-02063087593480392","GroupName": "ElasticMapReduce-slave","UserId": "430150006394"},{"GroupId": "sg-0c59ae38c42100171","GroupName": "ElasticMapReduce-master","UserId": "430150006394"}]}}}}}}},"sg-186a6a69": {"description": "default VPC security group","id": "sg-186a6a69","name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"security_groups": [{"GroupId": "sg-186a6a69","GroupName": "default","UserId": "430150006394"}]}}}}}}}}}}},"eu-west-2": {"instances_count": 0,"network_interfaces_count": 0,"region": "eu-west-2","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpc_resource_types": ["instances","security_groups","network_interfaces"],"vpcs": {"vpc-3fa2fa57": {"instances": {},"name": null,"network_interfaces": {},"security_groups": {"sg-223b755a": {"description": "default VPC security group","id": "sg-223b755a","name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"security_groups": [{"GroupId": "sg-223b755a","GroupName": "default","UserId": "430150006394"}]}}}}}}}}}}},"eu-west-3": {"instances_count": 0,"network_interfaces_count": 0,"region": "eu-west-3","security_groups_count": 2,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpc_resource_types": ["instances","security_groups","network_interfaces"],"vpcs": {"vpc-87d3fdee": {"instances": {},"name": null,"network_interfaces": {},"security_groups": {"sg-000c4c21c24f75b85": {"description": "launch-wizard-1 created 2019-12-23T12:17:14.882+01:00","id": "sg-000c4c21c24f75b85","name": "launch-wizard-1","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"TCP": {"ports": {"22": {"cidrs": [{"CIDR": "86.250.138.62/32"}]}}}}}}},"sg-4cc9d827": {"description": "default VPC security group","id": "sg-4cc9d827","name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"security_groups": [{"GroupId": "sg-4cc9d827","GroupName": "default","UserId": "430150006394"}]}}}}}}}}}}},"me-south-1": {"instances_count": 0,"network_interfaces_count": 0,"region": "me-south-1","security_groups_count": 0,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpc_resource_types": ["instances","security_groups","network_interfaces"],"vpcs": {}},"sa-east-1": {"instances_count": 0,"network_interfaces_count": 0,"region": "sa-east-1","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpc_resource_types": ["instances","security_groups","network_interfaces"],"vpcs": {"vpc-b14fa4d7": {"instances": {},"name": null,"network_interfaces": {},"security_groups": {"sg-3965844c": {"description": "default VPC security group","id": "sg-3965844c","name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"security_groups": [{"GroupId": "sg-3965844c","GroupName": "default","UserId": "430150006394"}]}}}}}}}}}}},"us-east-1": {"instances_count": 0,"network_interfaces_count": 0,"region": "us-east-1","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpc_resource_types": ["instances","security_groups","network_interfaces"],"vpcs": {"vpc-ba1cbdc7": {"instances": {},"name": null,"network_interfaces": {},"security_groups": {"sg-4574a94e": {"description": "default VPC security group","id": "sg-4574a94e","name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"security_groups": [{"GroupId": "sg-4574a94e","GroupName": "default","UserId": "430150006394"}]}}}}}}}}}}},"us-east-2": {"instances_count": 0,"network_interfaces_count": 0,"region": "us-east-2","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpc_resource_types": ["instances","security_groups","network_interfaces"],"vpcs": {"vpc-e429ad8f": {"instances": {},"name": null,"network_interfaces": {},"security_groups": {"sg-a81474db": {"description": "default VPC security group","id": "sg-a81474db","name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"security_groups": [{"GroupId": "sg-a81474db","GroupName": "default","UserId": "430150006394"}]}}}}}}}}}}},"us-west-1": {"instances_count": 0,"network_interfaces_count": 0,"region": "us-west-1","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpc_resource_types": ["instances","security_groups","network_interfaces"],"vpcs": {"vpc-6e6fa508": {"instances": {},"name": null,"network_interfaces": {},"security_groups": {"sg-778f4e3e": {"description": "default VPC security group","id": "sg-778f4e3e","name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"security_groups": [{"GroupId": "sg-778f4e3e","GroupName": "default","UserId": "430150006394"}]}}}}}}}}}}},"us-west-2": {"instances_count": 0,"network_interfaces_count": 0,"region": "us-west-2","security_groups_count": 1,"snapshots": {},"snapshots_count": 0,"volumes": {},"volumes_count": 0,"vpc_resource_types": ["instances","security_groups","network_interfaces"],"vpcs": {"vpc-d45709ac": {"instances": {},"name": null,"network_interfaces": {},"security_groups": {"sg-a9b5628e": {"description": "default VPC security group","id": "sg-a9b5628e","name": "default","owner_id": "430150006394","rules": {"egress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"cidrs": [{"CIDR": "0.0.0.0/0"}]}}}}},"ingress": {"count": 1,"protocols": {"ALL": {"ports": {"N/A": {"security_groups": [{"GroupId": "sg-a9b5628e","GroupName": "default","UserId": "430150006394"}]}}}}}}}}}}}},"regions_count": 21,"resource_types": {"global": [],"region": ["volumes","snapshots"],"vpc": ["instances","security_groups","network_interfaces"]},"security_groups_count": 20,"service": "ec2","snapshots_count": 0,"targets": {"first_region": [["instances","Reservations","describe_instances",{},false],["security_groups","SecurityGroups","describe_security_groups",{},false],["volumes","Volumes","describe_volumes",{},false],["snapshots","Snapshots","describe_snapshots",{"OwnerIds": ["430150006394"]},false],["network_interfaces","NetworkInterfaces","describe_network_interfaces",{},false]],"other_regions": [["instances","Reservations","describe_instances",{},false],["security_groups","SecurityGroups","describe_security_groups",{},false],["volumes","Volumes","describe_volumes",{},false],["snapshots","Snapshots","describe_snapshots",{"OwnerIds": ["430150006394"]},false],["network_interfaces","NetworkInterfaces","describe_network_interfaces",{},false]]},"thread_config": {"list": 10,"parse": 20},"volumes_count": 0},"efs": {"file_systems_count": 0,"filters": {},"findings": {},"regions": {"af-south-1": {"file_systems": {},"file_systems_count": 0,"region": "af-south-1"},"ap-east-1": {"file_systems": {},"file_systems_count": 0,"region": "ap-east-1"},"ap-northeast-1": {"file_systems": {},"file_systems_count": 0,"region": "ap-northeast-1"},"ap-northeast-2": {"file_systems": {},"file_systems_count": 0,"region": "ap-northeast-2"},"ap-northeast-3": {"file_systems": {},"file_systems_count": 0,"region": "ap-northeast-3"},"ap-south-1": {"file_systems": {},"file_systems_count": 0,"region": "ap-south-1"},"ap-southeast-1": {"file_systems": {},"file_systems_count": 0,"region": "ap-southeast-1"},"ap-southeast-2": {"file_systems": {},"file_systems_count": 0,"region": "ap-southeast-2"},"ca-central-1": {"file_systems": {},"file_systems_count": 0,"region": "ca-central-1"},"eu-central-1": {"file_systems": {},"file_systems_count": 0,"region": "eu-central-1"},"eu-north-1": {"file_systems": {},"file_systems_count": 0,"region": "eu-north-1"},"eu-south-1": {"file_systems": {},"file_systems_count": 0,"region": "eu-south-1"},"eu-west-1": {"file_systems": {},"file_systems_count": 0,"region": "eu-west-1"},"eu-west-2": {"file_systems": {},"file_systems_count": 0,"region": "eu-west-2"},"eu-west-3": {"file_systems": {},"file_systems_count": 0,"region": "eu-west-3"},"me-south-1": {"file_systems": {},"file_systems_count": 0,"region": "me-south-1"},"sa-east-1": {"file_systems": {},"file_systems_count": 0,"region": "sa-east-1"},"us-east-1": {"file_systems": {},"file_systems_count": 0,"region": "us-east-1"},"us-east-2": {"file_systems": {},"file_systems_count": 0,"region": "us-east-2"},"us-west-1": {"file_systems": {},"file_systems_count": 0,"region": "us-west-1"},"us-west-2": {"file_systems": {},"file_systems_count": 0,"region": "us-west-2"}},"regions_count": 21,"resource_types": {"global": [],"region": ["file_systems"],"vpc": []},"service": "efs","targets": {"first_region": [["file_systems","FileSystems","describe_file_systems",{},false]],"other_regions": [["file_systems","FileSystems","describe_file_systems",{},false]]},"thread_config": {"list": 10,"parse": 20}},"elasticache": {"clusters_count": 0,"filters": {},"findings": {},"regions": {"af-south-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "af-south-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters","subnet_groups"],"vpcs": {}},"ap-east-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ap-east-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters","subnet_groups"],"vpcs": {}},"ap-northeast-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ap-northeast-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters","subnet_groups"],"vpcs": {}},"ap-northeast-2": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ap-northeast-2","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters","subnet_groups"],"vpcs": {}},"ap-northeast-3": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ap-northeast-3","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters","subnet_groups"],"vpcs": {}},"ap-south-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ap-south-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters","subnet_groups"],"vpcs": {}},"ap-southeast-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ap-southeast-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters","subnet_groups"],"vpcs": {}},"ap-southeast-2": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ap-southeast-2","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters","subnet_groups"],"vpcs": {}},"ca-central-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ca-central-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters","subnet_groups"],"vpcs": {}},"eu-central-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "eu-central-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters","subnet_groups"],"vpcs": {}},"eu-north-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "eu-north-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters","subnet_groups"],"vpcs": {}},"eu-south-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "eu-south-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters","subnet_groups"],"vpcs": {}},"eu-west-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "eu-west-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters","subnet_groups"],"vpcs": {}},"eu-west-2": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "eu-west-2","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters","subnet_groups"],"vpcs": {}},"eu-west-3": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "eu-west-3","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters","subnet_groups"],"vpcs": {}},"me-south-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "me-south-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters","subnet_groups"],"vpcs": {}},"sa-east-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "sa-east-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters","subnet_groups"],"vpcs": {}},"us-east-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "us-east-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters","subnet_groups"],"vpcs": {}},"us-east-2": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "us-east-2","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters","subnet_groups"],"vpcs": {}},"us-west-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "us-west-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters","subnet_groups"],"vpcs": {}},"us-west-2": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "us-west-2","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters","subnet_groups"],"vpcs": {}}},"regions_count": 21,"resource_types": {"global": [],"region": ["parameter_groups","security_groups"],"vpc": ["clusters","subnet_groups"]},"security_groups_count": 0,"service": "elasticache","targets": {"first_region": [["clusters","CacheClusters","describe_cache_clusters",{},false],["security_groups","CacheSecurityGroups","describe_cache_security_groups",{},true]],"other_regions": [["clusters","CacheClusters","describe_cache_clusters",{},false],["security_groups","CacheSecurityGroups","describe_cache_security_groups",{},true]]},"thread_config": {"list": 10,"parse": 20}},"elb": {"elbs_count": 0,"filters": {},"findings": {"elb-no-access-logs": {"checked_items": 0,"dashboard_name": "Load Balancer Attributes","description": "Lack of access logs","display_path": "elb.regions.id.vpcs.id.elbs.id","flagged_items": 0,"items": [],"level": "warning","path": "elb.regions.id.vpcs.id.elbs.id.attributes.AccessLog.Enabled","rationale": "Access logs enable traffic analysis and identification of security issues.","service": "ELB"}},"regions": {"af-south-1": {"elb_policies": {},"elb_policies_count": 0,"elbs_count": 0,"region": "af-south-1","vpc_resource_types": ["elbs"],"vpcs": {}},"ap-east-1": {"elb_policies": {},"elb_policies_count": 0,"elbs_count": 0,"region": "ap-east-1","vpc_resource_types": ["elbs"],"vpcs": {}},"ap-northeast-1": {"elb_policies": {},"elb_policies_count": 0,"elbs_count": 0,"region": "ap-northeast-1","vpc_resource_types": ["elbs"],"vpcs": {}},"ap-northeast-2": {"elb_policies": {},"elb_policies_count": 0,"elbs_count": 0,"region": "ap-northeast-2","vpc_resource_types": ["elbs"],"vpcs": {}},"ap-northeast-3": {"elb_policies": {},"elb_policies_count": 0,"elbs_count": 0,"region": "ap-northeast-3","vpc_resource_types": ["elbs"],"vpcs": {}},"ap-south-1": {"elb_policies": {},"elb_policies_count": 0,"elbs_count": 0,"region": "ap-south-1","vpc_resource_types": ["elbs"],"vpcs": {}},"ap-southeast-1": {"elb_policies": {},"elb_policies_count": 0,"elbs_count": 0,"region": "ap-southeast-1","vpc_resource_types": ["elbs"],"vpcs": {}},"ap-southeast-2": {"elb_policies": {},"elb_policies_count": 0,"elbs_count": 0,"region": "ap-southeast-2","vpc_resource_types": ["elbs"],"vpcs": {}},"ca-central-1": {"elb_policies": {},"elb_policies_count": 0,"elbs_count": 0,"region": "ca-central-1","vpc_resource_types": ["elbs"],"vpcs": {}},"eu-central-1": {"elb_policies": {},"elb_policies_count": 0,"elbs_count": 0,"region": "eu-central-1","vpc_resource_types": ["elbs"],"vpcs": {}},"eu-north-1": {"elb_policies": {},"elb_policies_count": 0,"elbs_count": 0,"region": "eu-north-1","vpc_resource_types": ["elbs"],"vpcs": {}},"eu-south-1": {"elb_policies": {},"elb_policies_count": 0,"elbs_count": 0,"region": "eu-south-1","vpc_resource_types": ["elbs"],"vpcs": {}},"eu-west-1": {"elb_policies": {},"elb_policies_count": 0,"elbs_count": 0,"region": "eu-west-1","vpc_resource_types": ["elbs"],"vpcs": {}},"eu-west-2": {"elb_policies": {},"elb_policies_count": 0,"elbs_count": 0,"region": "eu-west-2","vpc_resource_types": ["elbs"],"vpcs": {}},"eu-west-3": {"elb_policies": {},"elb_policies_count": 0,"elbs_count": 0,"region": "eu-west-3","vpc_resource_types": ["elbs"],"vpcs": {}},"me-south-1": {"elb_policies": {},"elb_policies_count": 0,"elbs_count": 0,"region": "me-south-1","vpc_resource_types": ["elbs"],"vpcs": {}},"sa-east-1": {"elb_policies": {},"elb_policies_count": 0,"elbs_count": 0,"region": "sa-east-1","vpc_resource_types": ["elbs"],"vpcs": {}},"us-east-1": {"elb_policies": {},"elb_policies_count": 0,"elbs_count": 0,"region": "us-east-1","vpc_resource_types": ["elbs"],"vpcs": {}},"us-east-2": {"elb_policies": {},"elb_policies_count": 0,"elbs_count": 0,"region": "us-east-2","vpc_resource_types": ["elbs"],"vpcs": {}},"us-west-1": {"elb_policies": {},"elb_policies_count": 0,"elbs_count": 0,"region": "us-west-1","vpc_resource_types": ["elbs"],"vpcs": {}},"us-west-2": {"elb_policies": {},"elb_policies_count": 0,"elbs_count": 0,"region": "us-west-2","vpc_resource_types": ["elbs"],"vpcs": {}}},"regions_count": 21,"resource_types": {"global": [],"region": ["elb_policies"],"vpc": ["elbs"]},"service": "elb","targets": {"first_region": [["elbs","LoadBalancerDescriptions","describe_load_balancers",{},false]],"other_regions": [["elbs","LoadBalancerDescriptions","describe_load_balancers",{},false]]},"thread_config": {"list": 10,"parse": 20}},"elbv2": {"filters": {},"findings": {"elbv2-no-access-logs": {"checked_items": 0,"dashboard_name": "Load Balancer Attributes","description": "Lack of access logs","display_path": "elbv2.regions.id.vpcs.id.lbs.id","flagged_items": 0,"items": [],"level": "warning","path": "elbv2.regions.id.vpcs.id.lbs.id.attributes.id","rationale": "Access logs enable traffic analysis and identification of security issues.","service": "ELBV2"},"elbv2-no-deletion-protection": {"checked_items": 0,"dashboard_name": "Load Balancer Attributes","description": "Lack of deletion protection","display_path": "elbv2.regions.id.vpcs.id.lbs.id","flagged_items": 0,"items": [],"level": "warning","path": "elbv2.regions.id.vpcs.id.lbs.id.attributes.id","rationale": "Enabling deletion protection on load balancers mitigates risks of accidental deletion.","service": "ELBV2"},"elbv2-older-ssl-policy": {"checked_items": 0,"dashboard_name": "Load Balancer Listeners","description": "Older SSL/TLS policy","display_path": "elbv2.regions.id.vpcs.id.lbs.id","flagged_items": 0,"items": [],"level": "warning","path": "elbv2.regions.id.vpcs.id.lbs.id.listeners.id.SslPolicy","rationale": "Use of AWS latest TLS policy is best practice.","service": "ELBV2"}},"lbs_count": 0,"regions": {"af-south-1": {"lbs_count": 0,"region": "af-south-1","ssl_policies": {},"ssl_policies_count": 0,"vpc_resource_types": ["lbs"],"vpcs": {}},"ap-east-1": {"lbs_count": 0,"region": "ap-east-1","ssl_policies": {},"ssl_policies_count": 0,"vpc_resource_types": ["lbs"],"vpcs": {}},"ap-northeast-1": {"lbs_count": 0,"region": "ap-northeast-1","ssl_policies": {},"ssl_policies_count": 0,"vpc_resource_types": ["lbs"],"vpcs": {}},"ap-northeast-2": {"lbs_count": 0,"region": "ap-northeast-2","ssl_policies": {},"ssl_policies_count": 0,"vpc_resource_types": ["lbs"],"vpcs": {}},"ap-northeast-3": {"lbs_count": 0,"region": "ap-northeast-3","ssl_policies": {},"ssl_policies_count": 0,"vpc_resource_types": ["lbs"],"vpcs": {}},"ap-south-1": {"lbs_count": 0,"region": "ap-south-1","ssl_policies": {},"ssl_policies_count": 0,"vpc_resource_types": ["lbs"],"vpcs": {}},"ap-southeast-1": {"lbs_count": 0,"region": "ap-southeast-1","ssl_policies": {},"ssl_policies_count": 0,"vpc_resource_types": ["lbs"],"vpcs": {}},"ap-southeast-2": {"lbs_count": 0,"region": "ap-southeast-2","ssl_policies": {},"ssl_policies_count": 0,"vpc_resource_types": ["lbs"],"vpcs": {}},"ca-central-1": {"lbs_count": 0,"region": "ca-central-1","ssl_policies": {},"ssl_policies_count": 0,"vpc_resource_types": ["lbs"],"vpcs": {}},"eu-central-1": {"lbs_count": 0,"region": "eu-central-1","ssl_policies": {},"ssl_policies_count": 0,"vpc_resource_types": ["lbs"],"vpcs": {}},"eu-north-1": {"lbs_count": 0,"region": "eu-north-1","ssl_policies": {},"ssl_policies_count": 0,"vpc_resource_types": ["lbs"],"vpcs": {}},"eu-south-1": {"lbs_count": 0,"region": "eu-south-1","ssl_policies": {},"ssl_policies_count": 0,"vpc_resource_types": ["lbs"],"vpcs": {}},"eu-west-1": {"lbs_count": 0,"region": "eu-west-1","ssl_policies": {},"ssl_policies_count": 0,"vpc_resource_types": ["lbs"],"vpcs": {}},"eu-west-2": {"lbs_count": 0,"region": "eu-west-2","ssl_policies": {},"ssl_policies_count": 0,"vpc_resource_types": ["lbs"],"vpcs": {}},"eu-west-3": {"lbs_count": 0,"region": "eu-west-3","ssl_policies": {},"ssl_policies_count": 0,"vpc_resource_types": ["lbs"],"vpcs": {}},"me-south-1": {"lbs_count": 0,"region": "me-south-1","ssl_policies": {},"ssl_policies_count": 0,"vpc_resource_types": ["lbs"],"vpcs": {}},"sa-east-1": {"lbs_count": 0,"region": "sa-east-1","ssl_policies": {},"ssl_policies_count": 0,"vpc_resource_types": ["lbs"],"vpcs": {}},"us-east-1": {"lbs_count": 0,"region": "us-east-1","ssl_policies": {},"ssl_policies_count": 0,"vpc_resource_types": ["lbs"],"vpcs": {}},"us-east-2": {"lbs_count": 0,"region": "us-east-2","ssl_policies": {},"ssl_policies_count": 0,"vpc_resource_types": ["lbs"],"vpcs": {}},"us-west-1": {"lbs_count": 0,"region": "us-west-1","ssl_policies": {},"ssl_policies_count": 0,"vpc_resource_types": ["lbs"],"vpcs": {}},"us-west-2": {"lbs_count": 0,"region": "us-west-2","ssl_policies": {},"ssl_policies_count": 0,"vpc_resource_types": ["lbs"],"vpcs": {}}},"regions_count": 21,"resource_types": {"global": ["ssl_policies"],"region": [],"vpc": ["lbs"]},"service": "elbv2","ssl_policies_count": 0,"targets": {"first_region": [["lbs","LoadBalancers","describe_load_balancers",{},false],["ssl_policies","SslPolicies","describe_ssl_policies",{},false]],"other_regions": [["lbs","LoadBalancers","describe_load_balancers",{},false]]},"thread_config": {"list": 10,"parse": 20}},"emr": {"clusters_count": 0,"filters": {},"findings": {},"regions": {"af-south-1": {"clusters_count": 0,"region": "af-south-1","vpc_resource_types": ["clusters"],"vpcs": {}},"ap-east-1": {"clusters_count": 0,"region": "ap-east-1","vpc_resource_types": ["clusters"],"vpcs": {}},"ap-northeast-1": {"clusters_count": 0,"region": "ap-northeast-1","vpc_resource_types": ["clusters"],"vpcs": {}},"ap-northeast-2": {"clusters_count": 0,"region": "ap-northeast-2","vpc_resource_types": ["clusters"],"vpcs": {}},"ap-northeast-3": {"clusters_count": 0,"region": "ap-northeast-3","vpc_resource_types": ["clusters"],"vpcs": {}},"ap-south-1": {"clusters_count": 0,"region": "ap-south-1","vpc_resource_types": ["clusters"],"vpcs": {}},"ap-southeast-1": {"clusters_count": 0,"region": "ap-southeast-1","vpc_resource_types": ["clusters"],"vpcs": {}},"ap-southeast-2": {"clusters_count": 0,"region": "ap-southeast-2","vpc_resource_types": ["clusters"],"vpcs": {}},"ca-central-1": {"clusters_count": 0,"region": "ca-central-1","vpc_resource_types": ["clusters"],"vpcs": {}},"eu-central-1": {"clusters_count": 0,"region": "eu-central-1","vpc_resource_types": ["clusters"],"vpcs": {}},"eu-north-1": {"clusters_count": 0,"region": "eu-north-1","vpc_resource_types": ["clusters"],"vpcs": {}},"eu-south-1": {"clusters_count": 0,"region": "eu-south-1","vpc_resource_types": ["clusters"],"vpcs": {}},"eu-west-1": {"clusters_count": 0,"region": "eu-west-1","vpc_resource_types": ["clusters"],"vpcs": {}},"eu-west-2": {"clusters_count": 0,"region": "eu-west-2","vpc_resource_types": ["clusters"],"vpcs": {}},"eu-west-3": {"clusters_count": 0,"region": "eu-west-3","vpc_resource_types": ["clusters"],"vpcs": {}},"me-south-1": {"clusters_count": 0,"region": "me-south-1","vpc_resource_types": ["clusters"],"vpcs": {}},"sa-east-1": {"clusters_count": 0,"region": "sa-east-1","vpc_resource_types": ["clusters"],"vpcs": {}},"us-east-1": {"clusters_count": 0,"region": "us-east-1","vpc_resource_types": ["clusters"],"vpcs": {}},"us-east-2": {"clusters_count": 0,"region": "us-east-2","vpc_resource_types": ["clusters"],"vpcs": {}},"us-west-1": {"clusters_count": 0,"region": "us-west-1","vpc_resource_types": ["clusters"],"vpcs": {}},"us-west-2": {"clusters_count": 0,"region": "us-west-2","vpc_resource_types": ["clusters"],"vpcs": {}}},"regions_count": 21,"resource_types": {"global": [],"region": [],"vpc": ["clusters"]},"service": "emr","targets": {"first_region": [["clusters","Clusters","list_clusters",{},false]],"other_regions": [["clusters","Clusters","list_clusters",{},false]]},"thread_config": {"list": 10,"parse": 20}},"iam": {"credential_report": {"": {"access_key_1_active": "false","access_key_1_last_rotated": "N/A","access_key_1_last_used_date": "N/A","access_key_1_last_used_region": "N/A","access_key_1_last_used_service": "N/A","access_key_2_active": "false","access_key_2_last_rotated": "N/A","access_key_2_last_used_date": "N/A","access_key_2_last_used_region": "N/A","access_key_2_last_used_service": "N/A","arn": "arn:aws:iam::430150006394:root","cert_1_active": "false","cert_1_last_rotated": "N/A","cert_2_active": "false","cert_2_last_rotated": "N/A","mfa_active": "false","password_enabled": "not_supported","password_last_changed": "not_supported","password_last_used": "2021-01-31T18:29:28+00:00","password_next_rotation": "not_supported","user": "","user_creation_time": "2013-12-19T08:57:25+00:00"},"dams": {"access_key_1_active": "true","access_key_1_last_rotated": "2013-12-19T09:13:40+00:00","access_key_1_last_used_date": "N/A","access_key_1_last_used_region": "N/A","access_key_1_last_used_service": "N/A","access_key_2_active": "true","access_key_2_last_rotated": "2019-01-25T17:58:41+00:00","access_key_2_last_used_date": "2021-01-31T19:12:00+00:00","access_key_2_last_used_region": "ap-northeast-1","access_key_2_last_used_service": "rds","arn": "arn:aws:iam::430150006394:user/dams","cert_1_active": "false","cert_1_last_rotated": "N/A","cert_2_active": "false","cert_2_last_rotated": "N/A","mfa_active": "false","password_enabled": "false","password_last_changed": "N/A","password_last_used": "N/A","password_next_rotation": "N/A","user": "dams","user_creation_time": "2013-12-19T09:13:40+00:00"}},"credential_report_count": 1,"filters": {"iam-role-for-EC2": {"checked_items": 7,"dashboard_name": "Roles","description": "Role for EC2","display_path": "iam.roles.id","flagged_items": 1,"items": ["iam.roles.AROAI265GPNVMDZAKJPPA.assume_role_policy.PolicyDocument.Statement.0"],"level": "","path": "iam.roles.id.assume_role_policy.PolicyDocument.Statement.id","rationale": "N/A","service": "IAM"},"iam-role-for-Lambda": {"checked_items": 7,"dashboard_name": "Roles","description": "Role for Lambda","display_path": "iam.roles.id","flagged_items": 1,"items": ["iam.roles.AROAJY5MNJYDKGD2UIATQ.assume_role_policy.PolicyDocument.Statement.0"],"level": "","path": "iam.roles.id.assume_role_policy.PolicyDocument.Statement.id","rationale": "N/A","service": "IAM"},"iam-role-for-cross-account": {"checked_items": 7,"dashboard_name": "Roles","description": "Role for cross account","display_path": "iam.roles.id","flagged_items": 0,"items": [],"level": "","path": "iam.roles.id.assume_role_policy.PolicyDocument.Statement.id","rationale": "N/A","service": "IAM"},"iam-role-for-same-account": {"checked_items": 7,"dashboard_name": "Roles","description": "Role for same account","display_path": "iam.roles.id","flagged_items": 0,"items": [],"level": "","path": "iam.roles.id.assume_role_policy.PolicyDocument.Statement.id","rationale": "N/A","service": "IAM"}},"findings": {"iam-assume-role-lacks-external-id-and-mfa": {"checked_items": 7,"dashboard_name": "Roles","description": "Cross-account AssumeRole policy lacks external ID and MFA","display_path": "iam.roles.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.roles.id.assume_role_policy.PolicyDocument.Statement.id","rationale": "When authorizing cross-account role assumption, an external ID or MFA should be required.","service": "IAM"},"iam-assume-role-policy-allows-all": {"checked_items": 7,"dashboard_name": "Roles","description": "AssumeRole policy allows all principals","display_path": "iam.roles.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.roles.id.assume_role_policy.PolicyDocument.Statement.id","rationale": "Setting the AssumeRole policy's principal attribute to AWS:* means that anyone is authorized to assume the role and access the AWS account.","service": "IAM"},"iam-ec2-role-without-instances": {"checked_items": 0,"dashboard_name": "Roles","description": "Unused role for EC2","display_path": "iam.roles.id","flagged_items": 0,"id_suffix": "instances","items": [],"level": "warning","path": "iam.roles.id.assume_role_policy.Statement.id.Principal","rationale": "N/A","service": "IAM"},"iam-group-with-inline-policies": {"checked_items": 1,"dashboard_name": "groups","description": "Group with inline policies","flagged_items": 1,"id_suffix": "inline_policies","items": ["iam.groups.AGPAIW3P3726RZDVZBZL2.inline_policies"],"level": "warning","path": "iam.groups.id","rationale": "N/A","service": "IAM"},"iam-group-with-no-users": {"checked_items": 1,"dashboard_name": "groups","description": "Group with no users","flagged_items": 0,"items": [],"level": "warning","path": "iam.groups.id","rationale": "Groups with no users should be reviewed and deleted if not necessary.","service": "IAM"},"iam-inline-group-policy-allows-NotActions": {"checked_items": 1,"dashboard_name": "Policies","description": "Inline group policy allows NotActions","display_path": "iam.groups.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.groups.id.inline_policies.id.PolicyDocument.Statement.id","rationale": "The combination of \"effect = allow\" and \"NotAction\" results in the policy allowing every action except those listed in the statement. The target policy does not follow the principle of least privilege because thousands of actions exist in AWS and because this policy automatically authorizes users to perform new actions created, regardless of their nature.","service": "IAM"},"iam-inline-group-policy-allows-iam-PassRole": {"checked_items": 1,"dashboard_name": "Policies","description": "Inline group policy allows iam:PassRole *","display_path": "iam.groups.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.groups.id.inline_policies.id.PolicyDocument.Statement.id","rationale": "N/A","service": "IAM"},"iam-inline-group-policy-allows-sts-AssumeRole": {"checked_items": 1,"dashboard_name": "Policies","description": "Inline group policy allows sts:AssumeRole *","display_path": "iam.groups.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.groups.id.inline_policies.id.PolicyDocument.Statement.id","rationale": "N/A","service": "IAM"},"iam-inline-role-policy-allows-NotActions": {"checked_items": 0,"dashboard_name": "Policies","description": "Inline role policy allows NotActions","display_path": "iam.roles.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.roles.id.inline_policies.id.PolicyDocument.Statement.id","rationale": "The combination of \"effect = allow\" and \"NotAction\" results in the policy allowing every action except those listed in the statement. The target policy does not follow the principle of least privilege because thousands of actions exist in AWS and because this policy automatically authorizes users to perform new actions created, regardless of their nature.","service": "IAM"},"iam-inline-role-policy-allows-iam-PassRole": {"checked_items": 0,"dashboard_name": "Policies","description": "Inline role policy allows iam:PassRole *","display_path": "iam.roles.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.roles.id.inline_policies.id.PolicyDocument.Statement.id","rationale": "N/A","service": "IAM"},"iam-inline-role-policy-allows-sts-AssumeRole": {"checked_items": 0,"dashboard_name": "Policies","description": "Inline role policy allows sts:AssumeRole *","display_path": "iam.roles.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.roles.id.inline_policies.id.PolicyDocument.Statement.id","rationale": "N/A","service": "IAM"},"iam-inline-user-policy-allows-NotActions": {"checked_items": 0,"dashboard_name": "Policies","description": "Inline user policy allows NotActions","display_path": "iam.users.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.users.id.inline_policies.id.PolicyDocument.Statement.id","rationale": "The combination of \"effect = allow\" and \"NotAction\" results in the policy allowing every action except those listed in the statement. The target policy does not follow the principle of least privilege because thousands of actions exist in AWS and because this policy automatically authorizes users to perform new actions created, regardless of their nature.","service": "IAM"},"iam-inline-user-policy-allows-iam-PassRole": {"checked_items": 0,"dashboard_name": "Policies","description": "Inline user policy allows iam:PassRole *","display_path": "iam.users.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.users.id.inline_policies.id.PolicyDocument.Statement.id","rationale": "N/A","service": "IAM"},"iam-inline-user-policy-allows-sts-AssumeRole": {"checked_items": 0,"dashboard_name": "Policies","description": "Inline user policy allows sts:AssumeRole *","display_path": "iam.users.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.users.id.inline_policies.id.PolicyDocument.Statement.id","rationale": "N/A","service": "IAM"},"iam-managed-policy-allows-NotActions": {"checked_items": 11,"dashboard_name": "Policies","description": "Managed policy allows NotActions","display_path": "iam.policies.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.policies.id.PolicyDocument.Statement.id","rationale": "The combination of \"effect = allow\" and \"NotAction\" results in the policy allowing every action except those listed in the statement. The target policy does not follow the principle of least privilege because thousands of actions exist in AWS and because this policy automatically authorizes users to perform new actions created, regardless of their nature.","service": "IAM"},"iam-managed-policy-allows-iam-PassRole": {"checked_items": 11,"dashboard_name": "Policies","description": "Managed policy allows iam:PassRole *","display_path": "iam.policies.id","flagged_items": 1,"items": ["iam.policies.ANPAIDI2BQT2LKXZG36TW.PolicyDocument.Statement.0"],"level": "danger","path": "iam.policies.id.PolicyDocument.Statement.id","rationale": "N/A","service": "IAM"},"iam-managed-policy-allows-sts-AssumeRole": {"checked_items": 11,"dashboard_name": "Policies","description": "Managed policy allows sts:AssumeRole *","display_path": "iam.policies.id","flagged_items": 0,"items": [],"level": "danger","path": "iam.policies.id.PolicyDocument.Statement.id","rationale": "N/A","service": "IAM"},"iam-managed-policy-no-attachments": {"checked_items": 7,"dashboard_name": "Policies","description": "Managed policy not attached to any entity","display_path": "iam.policies.id","flagged_items": 0,"items": [],"level": "warning","path": "iam.policies.id","rationale": "Customer Managed policies should be reviewed and deleted if not necessary.","service": "IAM"},"iam-password-policy-minimum-length": {"checked_items": 1,"dashboard_name": "Password policy","description": "Minimum password length too short","flagged_items": 1,"items": ["iam.password_policy.MinimumPasswordLength"],"level": "danger","path": "iam.password_policy.MinimumPasswordLength","rationale": "N/A","service": "IAM"},"iam-password-policy-no-expiration": {"checked_items": 1,"dashboard_name": "Password policy","description": "Password expiration disabled","flagged_items": 1,"items": ["iam.password_policy.ExpirePasswords"],"level": "danger","path": "iam.password_policy.ExpirePasswords","rationale": "N/A","service": "IAM"},"iam-password-policy-reuse-enabled": {"checked_items": 1,"dashboard_name": "Password policy","description": "Password reuse enabled","flagged_items": 1,"items": ["iam.password_policy.PasswordReusePrevention"],"level": "danger","path": "iam.password_policy.PasswordReusePrevention","rationale": "N/A","service": "IAM"},"iam-role-with-inline-policies": {"checked_items": 7,"dashboard_name": "Roles","description": "Role with inline policies","flagged_items": 0,"id_suffix": "inline_policies","items": [],"level": "warning","path": "iam.roles.id","rationale": "N/A","service": "IAM"},"iam-root-account-no-mfa": {"checked_items": 1,"dashboard_name": "Root account","description": "Lack of MFA (root account)","flagged_items": 1,"id_suffix": "mfa_active","items": ["iam.credential_report..mfa_active"],"level": "danger","path": "iam.credential_report.","rationale": "N/A","service": "IAM"},"iam-root-account-used-recently": {"checked_items": 1,"dashboard_name": "Root account","description": "Root account used recently","flagged_items": 1,"id_suffix": "password_last_used","items": ["iam.credential_report..password_last_used"],"level": "danger","path": "iam.credential_report.","rationale": "N/A","service": "IAM"},"iam-root-account-with-active-certs": {"checked_items": 1,"dashboard_name": "Root account","description": "Root account has active X.509 certs","flagged_items": 0,"items": [],"level": "danger","path": "iam.credential_report.","rationale": "Root account X.509 certificates should be deleted as they may be used to make SOAP-protocol requests in the context of the root account.","service": "IAM"},"iam-root-account-with-active-keys": {"checked_items": 1,"dashboard_name": "Root account","description": "Root account has active keys","flagged_items": 0,"items": [],"level": "danger","path": "iam.credential_report.","rationale": "AWS root account access keys should be deleted as they provide unrestricted access to the AWS Account.","service": "IAM"},"iam-user-no-Active-key-rotation": {"checked_items": 2,"dashboard_name": "Access keys","description": "Lack of key rotation (Active)","display_path": "iam.users.id","flagged_items": 2,"items": ["iam.users.AIDAJUK77MEJCW5J3DWZU.AccessKeys.0","iam.users.AIDAJUK77MEJCW5J3DWZU.AccessKeys.1"],"level": "danger","path": "iam.users.id.AccessKeys.id","rationale": "In case of access key compromise, the lack of credential rotation increases the period during which an attacker has access to the AWS account","service": "IAM"},"iam-user-no-Inactive-key-rotation": {"checked_items": 2,"dashboard_name": "Access keys","description": "Lack of key rotation (Inactive)","display_path": "iam.users.id","flagged_items": 0,"items": [],"level": "warning","path": "iam.users.id.AccessKeys.id","rationale": "In case of access key compromise, the lack of credential rotation increases the period during which an attacker has access to the AWS account","service": "IAM"},"iam-user-with-inline-policies": {"checked_items": 1,"dashboard_name": "Users","description": "User with inline policies","flagged_items": 0,"id_suffix": "inline_policies","items": [],"level": "warning","path": "iam.users.id","rationale": "N/A","service": "IAM"},"iam-user-with-multiple-access-keys": {"checked_items": 1,"dashboard_name": "Users","description": "User with multiple API keys","flagged_items": 1,"id_suffix": "multiple_api_keys","items": ["iam.users.AIDAJUK77MEJCW5J3DWZU.multiple_api_keys"],"level": "warning","path": "iam.users.id","rationale": "N/A","service": "IAM"},"iam-user-without-mfa": {"checked_items": 1,"dashboard_name": "Users","description": "User without MFA","flagged_items": 0,"id_suffix": "mfa_enabled","items": [],"level": "danger","path": "iam.users.id","rationale": "N/A","service": "IAM"}},"groups": {"AGPAIW3P3726RZDVZBZL2": {"CreateDate": "2013-12-19 09:13:40+00:00","Path": "/","arn": "arn:aws:iam::430150006394:group/devs","id": "AGPAIW3P3726RZDVZBZL2","inline_policies": {"58cd3df92811df89e93933e00cd5a76813cf6258": {"PolicyDocument": {"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version": "2012-10-17"},"name": "AdministratorAccess-201312191013"}},"inline_policies_count": 1,"name": "devs","users": ["AIDAJUK77MEJCW5J3DWZU"]}},"groups_count": 1,"password_policy": {"AllowUsersToChangePassword": true,"ExpirePasswords": false,"MinimumPasswordLength": 6,"PasswordReusePrevention": false,"RequireLowercaseCharacters": false,"RequireNumbers": false,"RequireSymbols": false,"RequireUppercaseCharacters": false},"password_policy_count": 1,"permissions": {"Action": {"*": {"groups": {"Allow": {"AGPAIW3P3726RZDVZBZL2": {"Resource": {"*": {"inline_policies": {"58cd3df92811df89e93933e00cd5a76813cf6258": {"condition": null}}}}}}}},"a4b:getDevice": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"a4b:getProfile": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"a4b:getRoom": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"a4b:getRoomSkillParameter": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"a4b:getSkillGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"a4b:searchDevices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"a4b:searchProfiles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"a4b:searchRooms": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"a4b:searchSkillGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"access-analyzer:getFinding": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"access-analyzer:listAnalyzers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"access-analyzer:listArchiveRules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"access-analyzer:listFindings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm-pca:describeCertificateAuthority": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm-pca:describeCertificateAuthorityAuditReport": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm-pca:getCertificate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm-pca:getCertificateAuthorityCertificate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm-pca:getCertificateAuthorityCsr": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm-pca:listCertificateAuthorities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm-pca:listTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm:describeCertificate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm:getCertificate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm:listCertificates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"acm:listTagsForCertificate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"amplify:getApp": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"amplify:getBranch": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"amplify:getDomainAssociation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"amplify:getJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"amplify:getWebhook": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"amplify:listApps": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"amplify:listWebhooks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"apigateway:GET": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"arn:aws:apigateway:*::/account": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/authorizers": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/authorizers/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/deployments": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/deployments/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/integrations": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/integrations/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/integrations/*/integrationresponses": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/integrations/*/integrationresponses/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/models": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/models/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/routes": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/routes/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/routes/*/routeresponses": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/routes/*/routeresponses/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/stages": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/apis/*/stages/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/clientcertificates": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/clientcertificates/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/domainnames": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/domainnames/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/domainnames/*/apimappings": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/domainnames/*/apimappings/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/domainnames/*/basepathmappings": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/domainnames/*/basepathmappings/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/authorizers": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/authorizers/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/deployments": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/deployments/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/models": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/models/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/models/*/default_template": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/resources": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/resources/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/resources/*/methods/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/integration": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/integration/responses/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/responses/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/stages": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/stages/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}},"arn:aws:apigateway:*::/restapis/*/stages/*/sdks/*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"application-autoscaling:DeleteScalingPolicy": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"application-autoscaling:DeregisterScalableTarget": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"application-autoscaling:Describe*": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"application-autoscaling:PutScalingPolicy": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"application-autoscaling:RegisterScalableTarget": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"application-autoscaling:describeScalableTargets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"application-autoscaling:describeScalingActivities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"application-autoscaling:describeScalingPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"application-autoscaling:describeScheduledActions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:describeMesh": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:describeRoute": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:describeVirtualNode": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:describeVirtualRouter": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:describeVirtualService": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:listMeshes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:listRoutes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:listVirtualNodes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:listVirtualRouters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appmesh:listVirtualServices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appstream:describeDirectoryConfigs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appstream:describeFleets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appstream:describeImageBuilders": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appstream:describeImages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appstream:describeSessions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appstream:describeStacks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appstream:listAssociatedFleets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appstream:listAssociatedStacks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appstream:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:getFunction": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:getGraphqlApi": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:getIntrospectionSchema": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:getResolver": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:getSchemaCreationStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:getType": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:listDataSources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:listFunctions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:listGraphqlApis": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:listResolvers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"appsync:listTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"athena:batchGetNamedQuery": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"athena:batchGetQueryExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"athena:getNamedQuery": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"athena:getQueryExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"athena:getWorkGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"athena:listNamedQueries": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"athena:listQueryExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"athena:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"athena:listWorkGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling-plans:describeScalingPlanResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling-plans:describeScalingPlans": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling-plans:getScalingPlanResourceForecastData": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:DescribeAccountLimits": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"autoscaling:DescribeAutoScalingGroups": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"autoscaling:DescribeLaunchConfigurations": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"autoscaling:describeAccountLimits": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeAdjustmentTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeAutoScalingGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeAutoScalingInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeAutoScalingNotificationTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeLaunchConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeLifecycleHookTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeLifecycleHooks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeLoadBalancerTargetGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeLoadBalancers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeMetricCollectionTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeNotificationConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describePolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeScalingActivities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeScalingProcessTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeScheduledActions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"autoscaling:describeTerminationPolicyTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:describeBackupJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:describeBackupVault": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:describeProtectedResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:describeRecoveryPoint": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:describeRestoreJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:getBackupPlan": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:getBackupPlanFromJSON": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:getBackupPlanFromTemplate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:getBackupSelection": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:getBackupVaultAccessPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:getBackupVaultNotifications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:getRecoveryPointRestoreMetadata": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:getSupportedResourceTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listBackupJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listBackupPlanTemplates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listBackupPlanVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listBackupPlans": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listBackupSelections": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listBackupVaults": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listProtectedResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listRecoveryPointsByBackupVault": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listRecoveryPointsByResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listRestoreJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"backup:listTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"batch:describeComputeEnvironments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"batch:describeJobDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"batch:describeJobQueues": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"batch:describeJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"batch:listJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"braket:getDevice": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"braket:getQuantumTask": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"braket:searchDevices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"braket:searchQuantumTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"budgets:viewBudget": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ce:GetReservationPurchaseRecommendation": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ce:GetSavingsPlansPurchaseRecommendation": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ce:getCostAndUsage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ce:getDimensionValues": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ce:getReservationCoverage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ce:getReservationUtilization": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ce:getTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloud9:describeEnvironmentMemberships": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloud9:describeEnvironments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloud9:listEnvironments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"clouddirectory:getDirectory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"clouddirectory:listDirectories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:DescribeAccountLimits": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"cloudformation:DescribeStacks": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"cloudformation:ListStacks": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"cloudformation:describeAccountLimits": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:describeChangeSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:describeStackEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:describeStackInstance": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:describeStackResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:describeStackResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:describeStackSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:describeStackSetOperation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:describeStacks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:estimateTemplateCost": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:getStackPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:getTemplate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:getTemplateSummary": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:listChangeSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:listExports": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:listImports": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:listStackInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:listStackResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:listStackSetOperationResults": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:listStackSetOperations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:listStackSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudformation:listStacks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:ListDistributions": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"cloudfront:getCloudFrontOriginAccessIdentity": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:getCloudFrontOriginAccessIdentityConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:getDistribution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:getDistributionConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:getInvalidation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:getStreamingDistribution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:getStreamingDistributionConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:listCloudFrontOriginAccessIdentities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:listDistributions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:listDistributionsByWebACLId": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:listInvalidations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudfront:listStreamingDistributions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudhsm:describeBackups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudhsm:describeClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudsearch:describeAnalysisSchemes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudsearch:describeAvailabilityOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudsearch:describeDomains": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudsearch:describeExpressions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudsearch:describeIndexFields": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudsearch:describeScalingParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudsearch:describeServiceAccessPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudsearch:describeSuggesters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudsearch:listDomainNames": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudtrail:DescribeTrails": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"cloudtrail:GetTrailStatus": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"cloudtrail:describeTrails": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudtrail:getEventSelectors": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudtrail:getInsightSelectors": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudtrail:getTrail": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudtrail:getTrailStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudtrail:listPublicKeys": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudtrail:listTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudtrail:listTrails": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudtrail:lookupEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudwatch:*": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"cloudwatch:DeleteAlarms": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"cloudwatch:DescribeAlarms": {"roles": {"Allow": {"AROAIH747R37LKSEOZ2MA": {"Resource": {"*": {"policies": {"ANPAJSVXG6QHPE6VHDZ4Q": {"condition": null}}}}},"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"cloudwatch:GetMetricStatistics": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"cloudwatch:PutMetricAlarm": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"cloudwatch:describeAlarmHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudwatch:describeAlarms": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudwatch:describeAlarmsForMetric": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudwatch:getDashboard": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudwatch:getMetricData": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudwatch:getMetricStatistics": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudwatch:listDashboards": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cloudwatch:listMetrics": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:describeDomain": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:describePackageVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:describeRepository": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:getDomainPermissionsPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:getRepositoryEndPoint": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:getRepositoryPermissionsPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:listDomains": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:listPackageVersionAssets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:listPackageVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:listPackages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:listRepositories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codeartifact:listRepositoriesInDomain": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codebuild:batchGetBuildBatches": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codebuild:batchGetBuilds": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codebuild:batchGetProjects": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codebuild:listBuildBatches": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codebuild:listBuildBatchesForProject": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codebuild:listBuilds": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codebuild:listBuildsForProject": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codebuild:listCuratedEnvironmentImages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codebuild:listProjects": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codebuild:listSourceCredentials": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codecommit:batchGetRepositories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codecommit:getBranch": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codecommit:getRepository": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codecommit:getRepositoryTriggers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codecommit:listBranches": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codecommit:listRepositories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:batchGetApplicationRevisions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:batchGetApplications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:batchGetDeploymentGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:batchGetDeploymentInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:batchGetDeploymentTargets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:batchGetDeployments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:batchGetOnPremisesInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:getApplication": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:getApplicationRevision": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:getDeployment": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:getDeploymentConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:getDeploymentGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:getDeploymentInstance": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:getDeploymentTarget": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:getOnPremisesInstance": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:listApplicationRevisions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:listApplications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:listDeploymentConfigs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:listDeploymentGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:listDeploymentInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:listDeploymentTargets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:listDeployments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:listGitHubAccountTokenNames": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codedeploy:listOnPremisesInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codepipeline:getJobDetails": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codepipeline:getPipeline": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codepipeline:getPipelineExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codepipeline:getPipelineState": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codepipeline:listActionExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codepipeline:listActionTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codepipeline:listPipelineExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codepipeline:listPipelines": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codepipeline:listWebhooks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codestar:describeProject": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codestar:listProjects": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codestar:listResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codestar:listTeamMembers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"codestar:listUserProfiles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-identity:describeIdentityPool": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-identity:getIdentityPoolRoles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-identity:listIdentities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-identity:listIdentityPools": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:adminGetUser": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:describeIdentityProvider": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:describeResourceServer": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:describeRiskConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:describeUserImportJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:describeUserPool": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:describeUserPoolClient": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:describeUserPoolDomain": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:getGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:getUICustomization": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:getUser": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:getUserPoolMfaConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:listGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:listIdentityProviders": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:listResourceServers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:listUserImportJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:listUserPoolClients": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-idp:listUserPools": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-sync:describeDataset": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-sync:describeIdentityPoolUsage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-sync:describeIdentityUsage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-sync:getCognitoEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-sync:getIdentityPoolConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-sync:listDatasets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"cognito-sync:listIdentityPoolUsage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"compute-optimizer:getAutoScalingGroupRecommendations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"compute-optimizer:getEC2InstanceRecommendations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"compute-optimizer:getEC2RecommendationProjectedMetrics": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"compute-optimizer:getEnrollmentStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"compute-optimizer:getRecommendationSummaries": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"config:describeConfigRuleEvaluationStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"config:describeConfigRules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"config:describeConfigurationRecorderStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"config:describeConfigurationRecorders": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"config:describeDeliveryChannelStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"config:describeDeliveryChannels": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"config:getResourceConfigHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"config:listDiscoveredResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"connect:describeUser": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"connect:getCurrentMetricData": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"connect:getMetricData": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"connect:listRoutingProfiles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"connect:listSecurityProfiles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"connect:listUsers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:describeAccountFactoryConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:describeCoreService": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:describeGuardrail": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:describeGuardrailForTarget": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:describeManagedAccount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:describeSingleSignOn": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:getAvailableUpdates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:getHomeRegion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:getLandingZoneStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:listDirectoryGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:listGuardrailViolations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:listGuardrailsForTarget": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:listManagedAccounts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:listManagedAccountsForGuardrail": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:listManagedAccountsForParent": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:listManagedOrganizationalUnits": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"controltower:listManagedOrganizationalUnitsForGuardrail": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datapipeline:describeObjects": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datapipeline:describePipelines": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datapipeline:getPipelineDefinition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datapipeline:listPipelines": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datapipeline:queryObjects": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:describeAgent": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:describeLocationEfs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:describeLocationFsxWindows": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:describeLocationNfs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:describeLocationS3": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:describeLocationSmb": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:describeTask": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:describeTaskExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:listAgents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:listLocations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:listTaskExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"datasync:listTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dax:describeClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dax:describeDefaultParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dax:describeEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dax:describeParameterGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dax:describeParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dax:describeSubnetGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"detective:getMembers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"detective:listGraphs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"detective:listInvitations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"detective:listMembers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getAccountSettings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getDevice": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getDevicePool": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getDevicePoolCompatibility": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getProject": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getRemoteAccessSession": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getRun": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getSuite": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getTest": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getTestGridProject": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getTestGridSession": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:getUpload": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listArtifacts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listDevicePools": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listDevices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listProjects": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listRemoteAccessSessions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listRuns": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listSamples": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listSuites": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listTestGridProjects": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listTestGridSessionActions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listTestGridSessionArtifacts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listTestGridSessions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listTests": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listUniqueProblems": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"devicefarm:listUploads": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"directconnect:describeConnections": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"directconnect:describeConnectionsOnInterconnect": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"directconnect:describeInterconnects": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"directconnect:describeLocations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"directconnect:describeVirtualGateways": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"directconnect:describeVirtualInterfaces": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dlm:getLifecyclePolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dlm:getLifecyclePolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dms:describeAccountAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dms:describeConnections": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dms:describeEndpointTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dms:describeEndpoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dms:describeOrderableReplicationInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dms:describeRefreshSchemasStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dms:describeReplicationInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dms:describeReplicationSubnetGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ds:describeConditionalForwarders": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ds:describeDirectories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ds:describeEventTopics": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ds:describeSnapshots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ds:describeTrusts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ds:getDirectoryLimits": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ds:getSnapshotLimits": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ds:listIpRoutes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ds:listSchemaExtensions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ds:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:*": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"dynamodb:DescribeLimits": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"dynamodb:DescribeTable": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"dynamodb:ListTables": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"dynamodb:describeBackup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:describeContinuousBackups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:describeGlobalTable": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:describeLimits": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:describeStream": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:describeTable": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:describeTimeToLive": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:listBackups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:listGlobalTables": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:listStreams": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:listTables": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"dynamodb:listTagsOfResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:AuthorizeSecurityGroupEgress": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:AuthorizeSecurityGroupIngress": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:CancelSpotInstanceRequests": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:CreateFleet": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:CreateLaunchTemplate": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:CreateNetworkInterface": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:CreateSecurityGroup": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:CreateTags": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DeleteLaunchTemplate": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:DeleteNetworkInterface": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:DeletePlacementGroup": {"roles": {"Allow": {"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:DeleteSecurityGroup": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DeleteTags": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DeleteVolume": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:Describe*": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"ec2:DescribeAccountAttributes": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeAddresses": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeAvailabilityZones": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeDhcpOptions": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeImages": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeInstanceAttribute": {"roles": {"Allow": {"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:DescribeInstanceStatus": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeInstances": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}},"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeInternetGateways": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeKeyPairs": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeLaunchTemplateVersions": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeLaunchTemplates": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:DescribeNetworkAcls": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeNetworkInterfaces": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribePlacementGroups": {"roles": {"Allow": {"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:DescribePrefixLists": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeReservedInstances": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeReservedInstancesOfferings": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeRouteTables": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeSecurityGroups": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeSnapshots": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeSpotInstanceRequests": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:DescribeSpotPriceHistory": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeSubnets": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeTags": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeVolumeStatus": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:DescribeVolumes": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}},"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeVpcAttribute": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeVpcEndpointServices": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeVpcEndpoints": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DescribeVpcs": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeVpnConnections": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DescribeVpnGateways": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ec2:DetachNetworkInterface": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:DetachVolume": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:ModifyImageAttribute": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:ModifyInstanceAttribute": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:RequestSpotInstances": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:RevokeSecurityGroupEgress": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:RunInstances": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"ec2:TerminateInstances": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}},"AROAJ2LRZXYT2USPF2ZTY": {"Resource": {"*": {"policies": {"ANPAI4YEZURRMKACW56EA": {"condition": null}}}}}}}},"ec2:acceptReservedInstancesExchangeQuote": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:cancelReservedInstancesListing": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:createReservedInstancesListing": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeAccountAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeAddresses": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeAvailabilityZones": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeBundleTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeByoipCidrs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeCapacityReservations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeClassicLinkInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeClientVpnAuthorizationRules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeClientVpnConnections": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeClientVpnEndpoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeClientVpnRoutes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeClientVpnTargetNetworks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeCoipPools": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeConversionTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeCustomerGateways": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeDhcpOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeElasticGpus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeExportImageTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeExportTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeFastSnapshotRestores": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeFleetHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeFleetInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeFleets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeFlowLogs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeHostReservationOfferings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeHostReservations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeHosts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeIdFormat": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeIdentityIdFormat": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeImageAttribute": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeImages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeImportImageTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeImportSnapshotTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeInstanceAttribute": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeInstanceStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeInternetGateways": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeKeyPairs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeLaunchTemplateVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeLaunchTemplates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeLocalGatewayRouteTableVirtualInterfaceGroupAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeLocalGatewayRouteTableVpcAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeLocalGatewayRouteTables": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeLocalGatewayVirtualInterfaceGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeLocalGatewayVirtualInterfaces": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeLocalGateways": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeMovingAddresses": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeNatGateways": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeNetworkAcls": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeNetworkInterfaceAttribute": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeNetworkInterfaces": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describePlacementGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describePrefixLists": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describePublicIpv4Pools": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeRegions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeReservedInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeReservedInstancesListings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeReservedInstancesModifications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeReservedInstancesOfferings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeRouteTables": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeScheduledInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeSecurityGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeSnapshotAttribute": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeSnapshots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeSpotDatafeedSubscription": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeSpotFleetInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeSpotFleetRequestHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeSpotFleetRequests": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeSpotInstanceRequests": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeSpotPriceHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeSubnets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeTrafficMirrorFilters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeTrafficMirrorSessions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeTrafficMirrorTargets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeTransitGatewayAttachments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeTransitGatewayRouteTables": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeTransitGatewayVpcAttachments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeTransitGateways": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVolumeAttribute": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVolumeStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVolumes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVolumesModifications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcAttribute": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcClassicLink": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcClassicLinkDnsSupport": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcEndpointConnectionNotifications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcEndpointConnections": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcEndpointServiceConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcEndpointServicePermissions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcEndpointServices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcEndpoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcPeeringConnections": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpcs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpnConnections": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:describeVpnGateways": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:getCoipPoolUsage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:getConsoleScreenshot": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:getReservedInstancesExchangeQuote": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:getTransitGatewayAttachmentPropagations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:getTransitGatewayRouteTableAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:getTransitGatewayRouteTablePropagations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:modifyReservedInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:purchaseReservedInstancesOffering": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ec2:searchLocalGatewayRoutes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr:batchCheckLayerAvailability": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr:describeImages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr:describeRepositories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr:getRepositoryPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecr:listImages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:describeClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:describeContainerInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:describeServices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:describeTaskDefinition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:describeTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:listClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:listContainerInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:listServices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:listTaskDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ecs:listTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"eks:describeCluster": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"eks:describeFargateProfile": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"eks:describeNodegroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"eks:describeUpdate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"eks:listClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"eks:listFargateProfiles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"eks:listNodegroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"eks:listUpdates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeCacheClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeCacheEngineVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeCacheParameterGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeCacheParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeCacheSecurityGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeCacheSubnetGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeEngineDefaultParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeReplicationGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeReservedCacheNodes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeReservedCacheNodesOfferings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:describeSnapshots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:listAllowedNodeTypeModifications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticache:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:checkDNSAvailability": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeApplicationVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeApplications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeConfigurationOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeConfigurationSettings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeEnvironmentHealth": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeEnvironmentManagedActionHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeEnvironmentManagedActions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeEnvironmentResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeEnvironments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describeInstancesHealth": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:describePlatformVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:listAvailableSolutionStacks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:listPlatformVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticbeanstalk:validateConfigurationSettings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticfilesystem:describeAccessPoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticfilesystem:describeFileSystemPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticfilesystem:describeFileSystems": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticfilesystem:describeLifecycleConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticfilesystem:describeMountTargetSecurityGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticfilesystem:describeMountTargets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticfilesystem:describeTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticfilesystem:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:DescribeAccountLimits": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"elasticloadbalancing:DescribeInstanceHealth": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"elasticloadbalancing:DescribeLoadBalancerAttributes": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"elasticloadbalancing:DescribeLoadBalancerPolicies": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"elasticloadbalancing:DescribeLoadBalancerPolicyTypes": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"elasticloadbalancing:DescribeLoadBalancers": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"elasticloadbalancing:describeInstanceHealth": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeListenerCertificates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeListeners": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeLoadBalancerAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeLoadBalancerPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeLoadBalancerPolicyTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeLoadBalancers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeRules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeSSLPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeTargetGroupAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeTargetGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticloadbalancing:describeTargetHealth": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticmapreduce:Describe*": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"elasticmapreduce:ListBootstrapActions": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"elasticmapreduce:ListClusters": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"elasticmapreduce:ListInstanceGroups": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}},"AROAIH747R37LKSEOZ2MA": {"Resource": {"*": {"policies": {"ANPAJSVXG6QHPE6VHDZ4Q": {"condition": null}}}}}}}},"elasticmapreduce:ListInstances": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"elasticmapreduce:ListSteps": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"elasticmapreduce:ModifyInstanceGroups": {"roles": {"Allow": {"AROAIH747R37LKSEOZ2MA": {"Resource": {"*": {"policies": {"ANPAJSVXG6QHPE6VHDZ4Q": {"condition": null}}}}}}}},"elasticmapreduce:describeCluster": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticmapreduce:describeSecurityConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticmapreduce:describeStep": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticmapreduce:listBootstrapActions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticmapreduce:listClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticmapreduce:listInstanceGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticmapreduce:listInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticmapreduce:listSecurityConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elasticmapreduce:listSteps": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elastictranscoder:listJobsByPipeline": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elastictranscoder:listJobsByStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elastictranscoder:listPipelines": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elastictranscoder:listPresets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elastictranscoder:readPipeline": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"elastictranscoder:readPreset": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"es:describeElasticsearchDomain": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"es:describeElasticsearchDomainConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"es:describeElasticsearchDomains": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"es:listDomainNames": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"es:listTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"events:describeEventBus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"events:describeRule": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"events:listRuleNamesByTarget": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"events:listRules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"events:listTargetsByRule": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"events:testEventPattern": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"firehose:describeDeliveryStream": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"firehose:listDeliveryStreams": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fms:getAdminAccount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fms:getComplianceDetail": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fms:getNotificationChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fms:getPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fms:getProtectionStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fms:listComplianceStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fms:listMemberAccounts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fms:listPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:describeDataset": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:describeDatasetGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:describeDatasetImportJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:describeForecast": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:describeForecastExportJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:describePredictor": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:getAccuracyMetrics": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:listDatasetGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:listDatasetImportJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:listDatasets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:listForecastExportJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:listForecasts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"forecast:listPredictors": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fsx:describeBackups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fsx:describeFileSystems": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"fsx:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glacier:describeJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glacier:describeVault": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glacier:getDataRetrievalPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glacier:getVaultAccessPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glacier:getVaultLock": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glacier:getVaultNotifications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glacier:listJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glacier:listTagsForVault": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glacier:listVaults": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"globalaccelerator:describeAccelerator": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"globalaccelerator:describeAcceleratorAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"globalaccelerator:describeEndpointGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"globalaccelerator:describeListener": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"globalaccelerator:listAccelerators": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"globalaccelerator:listEndpointGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"globalaccelerator:listListeners": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:BatchCreatePartition": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:BatchDeletePartition": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:BatchGetPartition": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:CreateDatabase": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:CreatePartition": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:CreateTable": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:CreateUserDefinedFunction": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:DeleteDatabase": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:DeletePartition": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:DeleteTable": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:DeleteUserDefinedFunction": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:GetDatabase": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:GetDatabases": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:GetPartition": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:GetPartitions": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:GetTable": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:GetTableVersions": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:GetTables": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:GetUserDefinedFunction": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:GetUserDefinedFunctions": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:UpdateDatabase": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:UpdatePartition": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:UpdateTable": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:UpdateUserDefinedFunction": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"glue:batchGetPartition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getCatalogImportStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getClassifier": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getClassifiers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getCrawler": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getCrawlerMetrics": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getCrawlers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getDatabase": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getDatabases": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getDataflowGraph": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getDevEndpoint": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getDevEndpoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getJobRun": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getJobRuns": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getMapping": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getPartition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getPartitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getTable": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getTableVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getTables": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getTrigger": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getTriggers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getUserDefinedFunction": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"glue:getUserDefinedFunctions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getConnectivityInfo": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getCoreDefinition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getCoreDefinitionVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getDeploymentStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getDeviceDefinition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getDeviceDefinitionVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getFunctionDefinition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getFunctionDefinitionVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getGroupCertificateAuthority": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getGroupVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getLoggerDefinition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getLoggerDefinitionVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getResourceDefinitionVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getServiceRoleForAccount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getSubscriptionDefinition": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:getSubscriptionDefinitionVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listCoreDefinitionVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listCoreDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listDeployments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listDeviceDefinitionVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listDeviceDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listFunctionDefinitionVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listFunctionDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listGroupVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listLoggerDefinitionVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listLoggerDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listResourceDefinitionVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listResourceDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listSubscriptionDefinitionVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"greengrass:listSubscriptionDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:getDetector": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:getFindings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:getFindingsStatistics": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:getIPSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:getInvitationsCount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:getMasterAccount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:getMembers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:getThreatIntelSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:listDetectors": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:listFindings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:listIPSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:listInvitations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:listMembers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"guardduty:listThreatIntelSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"health:describeAffectedEntities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"health:describeEntityAggregates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"health:describeEventAggregates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"health:describeEventDetails": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"health:describeEventTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"health:describeEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:CreateServiceLinkedRole": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"arn:aws:iam::*:role/aws-service-role/spot.amazonaws.com/AWSServiceRoleForEC2Spot*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": {"StringLike": {"iam:AWSServiceName": "spot.amazonaws.com"}}}}}}}}}},"iam:DeleteRole": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"arn:aws:iam::*:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:GenerateCredentialReport": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"iam:GetAccountPasswordPolicy": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"iam:GetAccountSummary": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"iam:GetCredentialReport": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"iam:GetRole": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"iam:GetRolePolicy": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"iam:GetServerCertificate": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"iam:ListInstanceProfiles": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"iam:ListRolePolicies": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"iam:ListServerCertificates": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"iam:PassRole": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"iam:getAccessKeyLastUsed": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getAccountAuthorizationDetails": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getAccountPasswordPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getAccountSummary": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getContextKeysForCustomPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getContextKeysForPrincipalPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getCredentialReport": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getGroupPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getInstanceProfile": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getLoginProfile": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getOpenIDConnectProvider": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getPolicyVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getRole": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getRolePolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getSAMLProvider": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getSSHPublicKey": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getServerCertificate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getUser": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:getUserPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listAccessKeys": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listAccountAliases": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listAttachedGroupPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listAttachedRolePolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listAttachedUserPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listEntitiesForPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listGroupPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listGroupsForUser": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listInstanceProfiles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listInstanceProfilesForRole": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listMFADevices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listOpenIDConnectProviders": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listPolicyVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listRolePolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listRoles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listSAMLProviders": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listSSHPublicKeys": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listServerCertificates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listSigningCertificates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listUserPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listUsers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:listVirtualMFADevices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:simulateCustomPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iam:simulatePrincipalPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:getComponent": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:getComponentPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:getDistributionConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:getImage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:getImagePipeline": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:getImagePolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:getImageRecipe": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:getImageRecipePolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:getInfrastructureConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:listComponentBuildVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:listComponents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:listDistributionConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:listImageBuildVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:listImagePipelineImages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:listImagePipelines": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:listImageRecipes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:listImages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:listInfrastructureConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"imagebuilder:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"importexport:getStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"importexport:listJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:describeAssessmentRuns": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:describeAssessmentTargets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:describeAssessmentTemplates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:describeCrossAccountAccessRole": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:describeResourceGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:describeRulesPackages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:getTelemetryMetadata": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:listAssessmentRunAgents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:listAssessmentRuns": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:listAssessmentTargets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:listAssessmentTemplates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:listEventSubscriptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:listRulesPackages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"inspector:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:describeAuthorizer": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:describeCACertificate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:describeCertificate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:describeDefaultAuthorizer": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:describeEndpoint": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:describeIndex": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:describeJobExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:describeThing": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:describeThingGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:describeTunnel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:getEffectivePolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:getIndexingConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:getLoggingOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:getPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:getPolicyVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:getTopicRule": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:getV2LoggingOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listAttachedPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listAuthorizers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listCACertificates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listCertificates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listCertificatesByCA": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listJobExecutionsForJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listJobExecutionsForThing": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listOutgoingCertificates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listPolicyPrincipals": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listPolicyVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listPrincipalPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listPrincipalThings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listRoleAliases": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listTargetsForPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listThingGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listThingGroupsForThing": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listThingPrincipals": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listThingRegistrationTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listThingTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listThings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listTopicRules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listTunnels": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iot:listV2LoggingLevels": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotevents:describeDetector": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotevents:describeDetectorModel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotevents:describeInput": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotevents:describeLoggingOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotevents:listDetectorModelVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotevents:listDetectorModels": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotevents:listDetectors": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotevents:listInputs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:describeAccessPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:describeAsset": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:describeAssetModel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:describeAssetProperty": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:describeDashboard": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:describeGateway": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:describeGatewayCapabilityConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:describeLoggingOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:describePortal": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:describeProject": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:listAccessPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:listAssetModels": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:listAssociatedAssets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:listDashboards": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:listGateways": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:listPortals": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:listProjectAssets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"iotsitewise:listProjects": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kafka:describeCluster": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kafka:getBootstrapBrokers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kafka:listClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kafka:listNodes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kendra:describeDataSource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kendra:describeFaq": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kendra:describeIndex": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kendra:getDataSourceSyncJobHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kendra:listDataSources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kendra:listFaqs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kendra:listIndices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kinesis:CreateStream": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"kinesis:DeleteStream": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"kinesis:DescribeLimits": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"kinesis:DescribeStream": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"kinesis:GetRecords": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"kinesis:GetShardIterator": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"kinesis:MergeShards": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"kinesis:PutRecord": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"kinesis:SplitShard": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"kinesis:describeStream": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kinesis:listStreams": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kinesis:listTagsForStream": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kinesisanalytics:describeApplication": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kinesisanalytics:listApplications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kms:describeKey": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kms:getKeyPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kms:getKeyRotationStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kms:listAliases": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kms:listGrants": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kms:listKeyPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kms:listKeys": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kms:listResourceTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"kms:listRetirableGrants": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getAccountSettings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getAlias": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getEventSourceMapping": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getFunction": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getFunctionConcurrency": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getFunctionConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getFunctionEventInvokeConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getLayerVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getLayerVersionPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:getProvisionedConcurrencyConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:listAliases": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:listEventSourceMappings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:listFunctionEventInvokeConfigs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:listFunctions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:listLayerVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:listLayers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:listProvisionedConcurrencyConfigs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lambda:listVersionsByFunction": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"launchwizard:describeProvisionedApp": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"launchwizard:describeProvisioningEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"launchwizard:listProvisionedApps": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getBot": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getBotAlias": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getBotAliases": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getBotChannelAssociation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getBotChannelAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getBotVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getBots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getBuiltinIntent": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getBuiltinIntents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getBuiltinSlotTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getIntent": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getIntentVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getIntents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getSlotType": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getSlotTypeVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lex:getSlotTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"license-manager:getLicenseConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"license-manager:getServiceSettings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"license-manager:listAssociationsForLicenseConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"license-manager:listFailuresForLicenseConfigurationOperations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"license-manager:listLicenseConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"license-manager:listLicenseSpecificationsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"license-manager:listResourceInventory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"license-manager:listUsageForLicenseConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getActiveNames": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getBlueprints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getBundles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getDomain": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getDomains": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getInstance": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getInstanceMetricData": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getInstancePortStates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getInstanceSnapshot": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getInstanceSnapshots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getInstanceState": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getKeyPair": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getKeyPairs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getOperation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getOperations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getOperationsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getRegions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getStaticIp": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"lightsail:getStaticIps": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"logs:CreateLogGroup": {"roles": {"Allow": {"AROAJY5MNJYDKGD2UIATQ": {"Resource": {"arn:aws:logs:eu-west-1:430150006394:*": {"policies": {"ANPAIDFYJXP7KKG7FLVWO": {"condition": null}}}}}}}},"logs:CreateLogStream": {"roles": {"Allow": {"AROAJY5MNJYDKGD2UIATQ": {"Resource": {"arn:aws:logs:eu-west-1:430150006394:log-group:/aws/lambda/load-wikipedia:*": {"policies": {"ANPAIDFYJXP7KKG7FLVWO": {"condition": null}}}}}}}},"logs:PutLogEvents": {"roles": {"Allow": {"AROAJY5MNJYDKGD2UIATQ": {"Resource": {"arn:aws:logs:eu-west-1:430150006394:log-group:/aws/lambda/load-wikipedia:*": {"policies": {"ANPAIDFYJXP7KKG7FLVWO": {"condition": null}}}}}}}},"logs:describeDestinations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"logs:describeExportTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"logs:describeLogGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"logs:describeLogStreams": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"logs:describeMetricFilters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"logs:describeQueries": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"logs:describeSubscriptionFilters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"logs:testMetricFilter": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"machinelearning:describeBatchPredictions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"machinelearning:describeDataSources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"machinelearning:describeEvaluations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"machinelearning:describeMLModels": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"machinelearning:getBatchPrediction": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"machinelearning:getDataSource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"machinelearning:getEvaluation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"machinelearning:getMLModel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"managedblockchain:getMember": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"managedblockchain:getNetwork": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"managedblockchain:getNode": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"managedblockchain:listMembers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"managedblockchain:listNetworks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"managedblockchain:listNodes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediaconvert:describeEndpoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediaconvert:getJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediaconvert:getJobTemplate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediaconvert:getPreset": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediaconvert:getQueue": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediaconvert:listJobTemplates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediaconvert:listJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:describeChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:describeInput": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:describeInputDevice": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:describeInputSecurityGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:describeMultiplex": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:describeOffering": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:describeReservation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:describeSchedule": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:listChannels": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:listInputDevices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:listInputSecurityGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:listInputs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:listMultiplexes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:listOfferings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"medialive:listReservations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediapackage:describeChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediapackage:describeOriginEndpoint": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediapackage:listChannels": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediapackage:listOriginEndpoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediastore:describeContainer": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediastore:describeObject": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediastore:getContainerPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediastore:getCorsPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediastore:listContainers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediastore:listItems": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediatailor:getPlaybackConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mediatailor:listPlaybackConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getAdmChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getApnsChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getApnsSandboxChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getApnsVoipChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getApnsVoipSandboxChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getApp": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getApplicationSettings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getApps": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getBaiduChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getCampaign": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getCampaignActivities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getCampaignVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getCampaignVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getCampaigns": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getEmailChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getEndpoint": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getEventStream": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getExportJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getExportJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getGcmChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getImportJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getImportJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getSegment": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getSegmentImportJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getSegmentVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getSegmentVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getSegments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mobiletargeting:getSmsChannel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mq:describeBroker": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mq:describeConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mq:describeConfigurationRevision": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mq:describeUser": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mq:listBrokers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mq:listConfigurationRevisions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mq:listConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"mq:listUsers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"networkmanager:describeGlobalNetworks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"networkmanager:getCustomerGatewayAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"networkmanager:getDevices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"networkmanager:getLinkAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"networkmanager:getLinks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"networkmanager:getSites": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"networkmanager:getTransitGatewayRegistrations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks-cm:describeAccountAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks-cm:describeBackups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks-cm:describeEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks-cm:describeNodeAssociationStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks-cm:describeServers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeAgentVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeApps": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeCommands": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeDeployments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeEcsClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeElasticIps": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeElasticLoadBalancers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeLayers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeLoadBasedAutoScaling": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeMyUserProfile": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describePermissions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeRaidArrays": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeRdsDbInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeServiceErrors": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeStackProvisioningParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeStackSummary": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeStacks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeTimeBasedAutoScaling": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeUserProfiles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:describeVolumes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"opsworks:getHostnameSuggestion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"outposts:getOutpost": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"outposts:getOutpostInstanceTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"outposts:listOutposts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"outposts:listSites": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeAlgorithm": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeCampaign": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeDataset": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeDatasetGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeDatasetImportJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeEventTracker": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeFeatureTransformation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeRecipe": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeSchema": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeSolution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:describeSolutionVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:listCampaigns": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:listDatasetGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:listDatasetImportJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:listDatasets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:listEventTrackers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:listRecipes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:listSchemas": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:listSolutionVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"personalize:listSolutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"polly:describeVoices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"polly:getLexicon": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"polly:listLexicons": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"pricing:describeServices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"pricing:getAttributeValues": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"pricing:getProducts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:describeDashboard": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:describeDashboardPermissions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:describeGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:describeIAMPolicyAssignment": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:describeTemplate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:describeTemplateAlias": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:describeTemplatePermissions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:describeUser": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:listDashboards": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:listGroupMemberships": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:listGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:listIAMPolicyAssignments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:listIAMPolicyAssignmentsForUser": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:listTemplateAliases": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:listTemplateVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:listTemplates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:listUserGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"quicksight:listUsers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:Describe*": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"rds:DescribeAccountAttributes": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeDBClusters": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeDBEngineVersions": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeDBInstances": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeDBParameterGroups": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeDBParameters": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeDBSecurityGroups": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeDBSnapshots": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeDBSubnetGroups": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeEngineDefaultParameters": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeEvents": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeOptionGroupOptions": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeOptionGroups": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeOrderableDBInstanceOptions": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeReservedDBInstances": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:DescribeReservedDBInstancesOfferings": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:ListTagsForResource": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"rds:describeAccountAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeCertificates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBClusterParameterGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBClusterParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBClusterSnapshots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBEngineVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBParameterGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBSecurityGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBSnapshotAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBSnapshots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeDBSubnetGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeEngineDefaultClusterParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeEngineDefaultParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeEventCategories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeEventSubscriptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeOptionGroupOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeOptionGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeOrderableDBInstanceOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describePendingMaintenanceActions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeReservedDBInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:describeReservedDBInstancesOfferings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rds:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:DescribeClusters": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"redshift:DescribeReservedNodeOfferings": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"redshift:DescribeReservedNodes": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"redshift:describeClusterParameterGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeClusterParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeClusterSecurityGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeClusterSnapshots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeClusterSubnetGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeClusterVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeClusters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeDefaultClusterParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeEventCategories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeEventSubscriptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeEvents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeHsmClientCertificates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeHsmConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeLoggingStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeOrderableClusterOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeReservedNodeOfferings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeReservedNodes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeResize": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeSnapshotCopyGrants": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeStorage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeTableRestoreStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"redshift:describeTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rekognition:listCollections": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"rekognition:listFaces": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"resource-groups:getGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"resource-groups:getGroupQuery": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"resource-groups:getTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"resource-groups:listGroupResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"resource-groups:listGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"resource-groups:searchResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:batchDescribeSimulationJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:describeDeploymentJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:describeFleet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:describeRobot": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:describeRobotApplication": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:describeSimulationApplication": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:describeSimulationJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:listDeploymentJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:listFleets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:listRobotApplications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:listRobots": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:listSimulationApplications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"robomaker:listSimulationJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:GetAccountLimit": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"route53:GetHealthCheck": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"route53:GetHostedZone": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"route53:ListHealthChecks": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"route53:ListHostedZones": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"route53:ListHostedZonesByName": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"route53:ListResourceRecordSets": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"route53:getChange": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getCheckerIpRanges": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getGeoLocation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getHealthCheck": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getHealthCheckCount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getHealthCheckLastFailureReason": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getHealthCheckStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getHostedZone": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getHostedZoneCount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getReusableDelegationSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getTrafficPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getTrafficPolicyInstance": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:getTrafficPolicyInstanceCount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listGeoLocations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listHealthChecks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listHostedZones": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listHostedZonesByName": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listResourceRecordSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listReusableDelegationSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listTagsForResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listTrafficPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listTrafficPolicyInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listTrafficPolicyInstancesByHostedZone": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listTrafficPolicyInstancesByPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53:listTrafficPolicyVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53domains:checkDomainAvailability": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53domains:getContactReachabilityStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53domains:getDomainDetail": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53domains:getOperationDetail": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53domains:listDomains": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53domains:listOperations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53domains:listTagsForDomain": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53domains:viewBilling": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:getResolverRulePolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:listResolverEndpointIpAddresses": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:listResolverEndpoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:listResolverRuleAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:listResolverRules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"route53resolver:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:*": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"s3:CreateBucket": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"s3:Get*": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"s3:GetBucketAcl": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"s3:GetBucketLocation": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"s3:GetBucketLogging": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"s3:GetBucketPolicy": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"s3:GetBucketPolicyStatus": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"s3:GetBucketPublicAccessBlock": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"s3:GetBucketVersioning": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"s3:List*": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"s3:ListAllMyBuckets": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"s3:ListBucket": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"s3:getAccelerateConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getAnalyticsConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getBucketAcl": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getBucketCORS": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getBucketLocation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getBucketLogging": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getBucketNotification": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getBucketPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getBucketRequestPayment": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getBucketTagging": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getBucketVersioning": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getBucketWebsite": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getEncryptionConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getInventoryConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getLifecycleConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getMetricsConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:getReplicationConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:listAllMyBuckets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:listBucket": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"s3:listBucketMultipartUploads": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeAlgorithm": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeApp": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeAutoMLJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeCompilationJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeDomain": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeEndpoint": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeEndpointConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeExperiment": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeHumanTaskUi": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeHyperParameterTuningJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeLabelingJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeModel": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeModelPackage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeMonitoringSchedule": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeNotebookInstance": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeNotebookInstanceLifecycleConfig": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeProcessingJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeSubscribedWorkteam": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeTrainingJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeTransformJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeTrial": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeTrialComponent": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeUserProfile": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:describeWorkteam": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listAlgorithms": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listApps": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listAutoMLJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listCandidatesForAutoMLJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listCodeRepositories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listCompilationJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listDomains": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listEndpointConfigs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listEndpoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listExperiments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listFlowDefinitions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listHumanTaskUis": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listHyperParameterTuningJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listLabelingJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listLabelingJobsForWorkteam": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listModelPackages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listModels": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listMonitoringExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listMonitoringSchedules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listNotebookInstanceLifecycleConfigs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listNotebookInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listProcessingJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listSubscribedWorkteams": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listTrainingJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listTrainingJobsForHyperParameterTuningJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listTransformJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listTrialComponents": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listTrials": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listUserProfiles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sagemaker:listWorkteams": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sdb:*": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"sdb:BatchPutAttributes": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"sdb:Select": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"sdb:domainMetadata": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sdb:listDomains": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"secretsmanager:describeSecret": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"secretsmanager:getResourcePolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"secretsmanager:listSecretVersionIds": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"secretsmanager:listSecrets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"securityhub:getEnabledStandards": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"securityhub:getFindings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"securityhub:getInsightResults": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"securityhub:getInsights": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"securityhub:getMasterAccount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"securityhub:getMembers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"securityhub:listEnabledProductsForImport": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"securityhub:listInvitations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"securityhub:listMembers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:describeConstraint": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:describePortfolio": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:describeProduct": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:describeProductAsAdmin": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:describeProductView": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:describeProvisioningArtifact": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:describeProvisioningParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:describeRecord": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:listAcceptedPortfolioShares": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:listConstraintsForPortfolio": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:listLaunchPaths": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:listPortfolioAccess": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:listPortfolios": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:listPortfoliosForProduct": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:listPrincipalsForPortfolio": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:listProvisioningArtifacts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:listRecordHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:scanProvisionedProducts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicecatalog:searchProducts": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:getAWSDefaultServiceQuota": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:getAssociationForServiceQuotaTemplate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:getRequestedServiceQuotaChange": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:getServiceQuota": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:getServiceQuotaIncreaseRequestFromTemplate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:listAWSDefaultServiceQuotas": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:listRequestedServiceQuotaChangeHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:listRequestedServiceQuotaChangeHistoryByQuota": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:listServiceQuotaIncreaseRequestsInTemplate": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:listServiceQuotas": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"servicequotas:listServices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:GetSendQuota": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"ses:describeActiveReceiptRuleSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:describeReceiptRule": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:describeReceiptRuleSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getAccount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getBlacklistReports": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getConfigurationSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getConfigurationSetEventDestinations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getDedicatedIp": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getDedicatedIps": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getDeliverabilityDashboardOptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getDeliverabilityTestReport": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getDomainDeliverabilityCampaign": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getDomainStatisticsReport": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getEmailIdentity": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getIdentityDkimAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getIdentityMailFromDomainAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getIdentityNotificationAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getIdentityPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getIdentityVerificationAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getSendQuota": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:getSendStatistics": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listConfigurationSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listDedicatedIpPools": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listDeliverabilityTestReports": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listDomainDeliverabilityCampaigns": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listEmailIdentities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listIdentities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listIdentityPolicies": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listReceiptFilters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listReceiptRuleSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ses:listVerifiedEmailAddresses": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"shield:describeAttack": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"shield:describeProtection": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"shield:describeSubscription": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"shield:listAttacks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"shield:listProtections": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sms-voice:getConfigurationSetEventDestinations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sms:getConnectors": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sms:getReplicationJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sms:getReplicationRuns": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sms:getServers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"snowball:describeAddress": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"snowball:describeAddresses": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"snowball:describeJob": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"snowball:getSnowballUsage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"snowball:listJobs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:*": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"sns:checkIfPhoneNumberIsOptedOut": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:getEndpointAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:getPlatformApplicationAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:getSMSAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:getSubscriptionAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:getTopicAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:listEndpointsByPlatformApplication": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:listPhoneNumbersOptedOut": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:listPlatformApplications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:listSubscriptions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:listSubscriptionsByTopic": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sns:listTopics": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sqs:*": {"roles": {"Allow": {"AROAI265GPNVMDZAKJPPA": {"Resource": {"*": {"policies": {"ANPAIGALS5RCDLZLB3PGS": {"condition": null}}}}}}}},"sqs:CreateQueue": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"sqs:Delete*": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"sqs:GetQueue*": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"sqs:ListQueues": {"roles": {"Allow": {"AROAJCHEQKY4NYQFQWP5K": {"Resource": {"*": {"policies": {"ANPAJH4QJ2WMHBOB47BUE": {"condition": null}}}}}}}},"sqs:PurgeQueue": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"sqs:ReceiveMessage": {"roles": {"Allow": {"AROAIXBSWIKGEEDLMO53I": {"Resource": {"*": {"policies": {"ANPAIDI2BQT2LKXZG36TW": {"condition": null}}}}}}}},"sqs:getQueueAttributes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sqs:getQueueUrl": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sqs:listDeadLetterSourceQueues": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"sqs:listQueues": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeActivations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeAssociation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeAssociationExecutionTargets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeAssociationExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeAutomationExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeAutomationStepExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeAvailablePatches": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeDocument": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeDocumentPermission": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeEffectiveInstanceAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeEffectivePatchesForPatchBaseline": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeInstanceAssociationsStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeInstanceInformation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeInstancePatchStates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeInstancePatchStatesForPatchGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeInstancePatches": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeInventoryDeletions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeMaintenanceWindowExecutionTaskInvocations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeMaintenanceWindowExecutionTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeMaintenanceWindowExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeMaintenanceWindowSchedule": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeMaintenanceWindowTargets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeMaintenanceWindowTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeMaintenanceWindows": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeMaintenanceWindowsForTarget": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeParameters": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describePatchBaselines": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describePatchGroupState": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describePatchGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describePatchProperties": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:describeSessions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getAutomationExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getCommandInvocation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getConnectionStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getDefaultPatchBaseline": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getDeployablePatchSnapshotForInstance": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getInventorySchema": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getMaintenanceWindow": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getMaintenanceWindowExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getMaintenanceWindowExecutionTask": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getMaintenanceWindowExecutionTaskInvocation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getMaintenanceWindowTask": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getPatchBaseline": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getPatchBaselineForPatchGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:getServiceSetting": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:labelParameterVersion": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listAssociationVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listAssociations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listCommandInvocations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listCommands": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listComplianceItems": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listComplianceSummaries": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listDocumentVersions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listDocuments": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listResourceComplianceSummaries": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listResourceDataSync": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"ssm:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"states:describeActivity": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"states:describeExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"states:describeStateMachine": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"states:describeStateMachineForExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"states:getExecutionHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"states:listActivities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"states:listExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"states:listStateMachines": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeBandwidthRateLimit": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeCache": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeCachediSCSIVolumes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeGatewayInformation": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeMaintenanceStartTime": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeNFSFileShares": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeSMBFileShares": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeSMBSettings": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeSnapshotSchedule": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeStorediSCSIVolumes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeTapeArchives": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeTapeRecoveryPoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeTapes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeUploadBuffer": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeVTLDevices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:describeWorkingStorage": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:listFileShares": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:listGateways": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:listLocalDisks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:listTapes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:listVolumeInitiators": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:listVolumeRecoveryPoints": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"storagegateway:listVolumes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:countClosedWorkflowExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:countOpenWorkflowExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:countPendingActivityTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:countPendingDecisionTasks": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:describeActivityType": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:describeDomain": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:describeWorkflowExecution": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:describeWorkflowType": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:getWorkflowExecutionHistory": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:listActivityTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:listClosedWorkflowExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:listDomains": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:listOpenWorkflowExecutions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"swf:listWorkflowTypes": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"transfer:describeServer": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"transfer:describeUser": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"transfer:listServers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"transfer:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"transfer:listUsers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:getByteMatchSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:getChangeTokenStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:getIPSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:getRule": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:getSqlInjectionMatchSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:getWebACL": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:getWebACLForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:listByteMatchSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:listIPSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:listResourcesForWebACL": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:listRules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:listSqlInjectionMatchSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf-regional:listWebACLs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:getByteMatchSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:getChangeTokenStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:getIPSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:getRule": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:getSampledRequests": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:getSizeConstraintSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:getSqlInjectionMatchSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:getWebACL": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:getXssMatchSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:listByteMatchSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:listIPSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:listRules": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:listSizeConstraintSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:listSqlInjectionMatchSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:listWebACLs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"waf:listXssMatchSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:checkCapacity": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:describeManagedRuleGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:getIPSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:getLoggingConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:getPermissionPolicy": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:getRateBasedStatementManagedKeys": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:getRegexPatternSet": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:getRuleGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:getSampledRequests": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:getWebACL": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:getWebACLForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:listAvailableManagedRuleGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:listIPSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:listLoggingConfigurations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:listRegexPatternSets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:listResourcesForWebACL": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:listRuleGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:listTagsForResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"wafv2:listWebACLs": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workdocs:checkAlias": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workdocs:describeAvailableDirectories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workdocs:describeInstances": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:describeAuditStreamConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:describeCompanyNetworkConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:describeDevice": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:describeDevicePolicyConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:describeDomain": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:describeFleetMetadata": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:describeIdentityProviderConfiguration": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:describeWebsiteCertificateAuthority": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:listDevices": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:listDomains": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:listFleets": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:listWebsiteAuthorizationProviders": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"worklink:listWebsiteCertificateAuthorities": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:describeGroup": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:describeOrganization": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:describeResource": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:describeUser": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:listAliases": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:listGroupMembers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:listGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:listMailboxPermissions": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:listOrganizations": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:listResourceDelegates": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:listResources": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workmail:listUsers": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workspaces:describeAccount": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workspaces:describeAccountModifications": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workspaces:describeIpGroups": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workspaces:describeTags": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workspaces:describeWorkspaceBundles": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workspaces:describeWorkspaceDirectories": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workspaces:describeWorkspaceImages": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workspaces:describeWorkspaces": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}},"workspaces:describeWorkspacesConnectionStatus": {"roles": {"Allow": {"AROAJCXETX2ROIWUKOPGG": {"Resource": {"*": {"policies": {"ANPAJ7W6266ELXF5MISDS": {"condition": null}}}}}}}}}},"policies": {"ANPAI4YEZURRMKACW56EA": {"PolicyDocument": {"Statement": [{"Action": ["ec2:DescribeInstances","ec2:DescribeLaunchTemplates","ec2:DescribeSpotInstanceRequests","ec2:DeleteLaunchTemplate","ec2:ModifyInstanceAttribute","ec2:TerminateInstances","ec2:CancelSpotInstanceRequests","ec2:DeleteNetworkInterface","ec2:DescribeInstanceAttribute","ec2:DescribeVolumeStatus","ec2:DescribeVolumes","ec2:DetachVolume","ec2:DeleteVolume","ec2:DescribePlacementGroups","ec2:DeletePlacementGroup"],"Effect": "Allow","Resource": ["*"]}],"Version": "2012-10-17"},"arn": "arn:aws:iam::aws:policy/aws-service-role/AmazonEMRCleanupPolicy","attached_to": {"roles": [{"id": "AROAJ2LRZXYT2USPF2ZTY","name": "AWSServiceRoleForEMRCleanup"}]},"id": "ANPAI4YEZURRMKACW56EA","name": "AmazonEMRCleanupPolicy"},"ANPAIDFYJXP7KKG7FLVWO": {"PolicyDocument": {"Statement": [{"Action": ["logs:CreateLogGroup"],"Effect": "Allow","Resource": ["arn:aws:logs:eu-west-1:430150006394:*"]},{"Action": ["logs:CreateLogStream","logs:PutLogEvents"],"Effect": "Allow","Resource": ["arn:aws:logs:eu-west-1:430150006394:log-group:/aws/lambda/load-wikipedia:*"]}],"Version": "2012-10-17"},"arn": "arn:aws:iam::430150006394:policy/service-role/AWSLambdaBasicExecutionRole-676647ec-377e-496c-8355-37f23bf12c85","attached_to": {"roles": [{"id": "AROAJY5MNJYDKGD2UIATQ","name": "load-wikipedia"}]},"id": "ANPAIDFYJXP7KKG7FLVWO","name": "AWSLambdaBasicExecutionRole-676647ec-377e-496c-8355-37f23bf12c85"},"ANPAIDI2BQT2LKXZG36TW": {"PolicyDocument": {"Statement": [{"Action": ["ec2:AuthorizeSecurityGroupEgress","ec2:AuthorizeSecurityGroupIngress","ec2:CancelSpotInstanceRequests","ec2:CreateFleet","ec2:CreateLaunchTemplate","ec2:CreateNetworkInterface","ec2:CreateSecurityGroup","ec2:CreateTags","ec2:DeleteLaunchTemplate","ec2:DeleteNetworkInterface","ec2:DeleteSecurityGroup","ec2:DeleteTags","ec2:DescribeAvailabilityZones","ec2:DescribeAccountAttributes","ec2:DescribeDhcpOptions","ec2:DescribeImages","ec2:DescribeInstanceStatus","ec2:DescribeInstances","ec2:DescribeKeyPairs","ec2:DescribeLaunchTemplates","ec2:DescribeNetworkAcls","ec2:DescribeNetworkInterfaces","ec2:DescribePrefixLists","ec2:DescribeRouteTables","ec2:DescribeSecurityGroups","ec2:DescribeSpotInstanceRequests","ec2:DescribeSpotPriceHistory","ec2:DescribeSubnets","ec2:DescribeTags","ec2:DescribeVpcAttribute","ec2:DescribeVpcEndpoints","ec2:DescribeVpcEndpointServices","ec2:DescribeVpcs","ec2:DetachNetworkInterface","ec2:ModifyImageAttribute","ec2:ModifyInstanceAttribute","ec2:RequestSpotInstances","ec2:RevokeSecurityGroupEgress","ec2:RunInstances","ec2:TerminateInstances","ec2:DeleteVolume","ec2:DescribeVolumeStatus","ec2:DescribeVolumes","ec2:DetachVolume","iam:GetRole","iam:GetRolePolicy","iam:ListInstanceProfiles","iam:ListRolePolicies","iam:PassRole","s3:CreateBucket","s3:Get*","s3:List*","sdb:BatchPutAttributes","sdb:Select","sqs:CreateQueue","sqs:Delete*","sqs:GetQueue*","sqs:PurgeQueue","sqs:ReceiveMessage","cloudwatch:PutMetricAlarm","cloudwatch:DescribeAlarms","cloudwatch:DeleteAlarms","application-autoscaling:RegisterScalableTarget","application-autoscaling:DeregisterScalableTarget","application-autoscaling:PutScalingPolicy","application-autoscaling:DeleteScalingPolicy","application-autoscaling:Describe*"],"Effect": "Allow","Resource": ["*"]},{"Action": ["iam:CreateServiceLinkedRole"],"Condition": {"StringLike": {"iam:AWSServiceName": "spot.amazonaws.com"}},"Effect": "Allow","Resource": ["arn:aws:iam::*:role/aws-service-role/spot.amazonaws.com/AWSServiceRoleForEC2Spot*"]}],"Version": "2012-10-17"},"arn": "arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceRole","attached_to": {"roles": [{"id": "AROAIXBSWIKGEEDLMO53I","name": "EMR_DefaultRole"}]},"id": "ANPAIDI2BQT2LKXZG36TW","name": "AmazonElasticMapReduceRole"},"ANPAIGALS5RCDLZLB3PGS": {"PolicyDocument": {"Statement": [{"Action": ["cloudwatch:*","dynamodb:*","ec2:Describe*","elasticmapreduce:Describe*","elasticmapreduce:ListBootstrapActions","elasticmapreduce:ListClusters","elasticmapreduce:ListInstanceGroups","elasticmapreduce:ListInstances","elasticmapreduce:ListSteps","kinesis:CreateStream","kinesis:DeleteStream","kinesis:DescribeStream","kinesis:GetRecords","kinesis:GetShardIterator","kinesis:MergeShards","kinesis:PutRecord","kinesis:SplitShard","rds:Describe*","s3:*","sdb:*","sns:*","sqs:*","glue:CreateDatabase","glue:UpdateDatabase","glue:DeleteDatabase","glue:GetDatabase","glue:GetDatabases","glue:CreateTable","glue:UpdateTable","glue:DeleteTable","glue:GetTable","glue:GetTables","glue:GetTableVersions","glue:CreatePartition","glue:BatchCreatePartition","glue:UpdatePartition","glue:DeletePartition","glue:BatchDeletePartition","glue:GetPartition","glue:GetPartitions","glue:BatchGetPartition","glue:CreateUserDefinedFunction","glue:UpdateUserDefinedFunction","glue:DeleteUserDefinedFunction","glue:GetUserDefinedFunction","glue:GetUserDefinedFunctions"],"Effect": "Allow","Resource": ["*"]}],"Version": "2012-10-17"},"arn": "arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceforEC2Role","attached_to": {"roles": [{"id": "AROAI265GPNVMDZAKJPPA","name": "EMR_EC2_DefaultRole"}]},"id": "ANPAIGALS5RCDLZLB3PGS","name": "AmazonElasticMapReduceforEC2Role"},"ANPAJ7W6266ELXF5MISDS": {"PolicyDocument": {"Statement": [{"Action": ["apigateway:GET"],"Effect": "Allow","Resource": ["arn:aws:apigateway:*::/account","arn:aws:apigateway:*::/apis","arn:aws:apigateway:*::/apis/*","arn:aws:apigateway:*::/apis/*/authorizers","arn:aws:apigateway:*::/apis/*/authorizers/*","arn:aws:apigateway:*::/apis/*/deployments","arn:aws:apigateway:*::/apis/*/deployments/*","arn:aws:apigateway:*::/apis/*/integrations","arn:aws:apigateway:*::/apis/*/integrations/*","arn:aws:apigateway:*::/apis/*/integrations/*/integrationresponses","arn:aws:apigateway:*::/apis/*/integrations/*/integrationresponses/*","arn:aws:apigateway:*::/apis/*/models","arn:aws:apigateway:*::/apis/*/models/*","arn:aws:apigateway:*::/apis/*/routes","arn:aws:apigateway:*::/apis/*/routes/*","arn:aws:apigateway:*::/apis/*/routes/*/routeresponses","arn:aws:apigateway:*::/apis/*/routes/*/routeresponses/*","arn:aws:apigateway:*::/apis/*/stages","arn:aws:apigateway:*::/apis/*/stages/*","arn:aws:apigateway:*::/clientcertificates","arn:aws:apigateway:*::/clientcertificates/*","arn:aws:apigateway:*::/domainnames","arn:aws:apigateway:*::/domainnames/*","arn:aws:apigateway:*::/domainnames/*/apimappings","arn:aws:apigateway:*::/domainnames/*/apimappings/*","arn:aws:apigateway:*::/domainnames/*/basepathmappings","arn:aws:apigateway:*::/domainnames/*/basepathmappings/*","arn:aws:apigateway:*::/restapis","arn:aws:apigateway:*::/restapis/*","arn:aws:apigateway:*::/restapis/*/authorizers","arn:aws:apigateway:*::/restapis/*/authorizers/*","arn:aws:apigateway:*::/restapis/*/deployments","arn:aws:apigateway:*::/restapis/*/deployments/*","arn:aws:apigateway:*::/restapis/*/models","arn:aws:apigateway:*::/restapis/*/models/*","arn:aws:apigateway:*::/restapis/*/models/*/default_template","arn:aws:apigateway:*::/restapis/*/resources","arn:aws:apigateway:*::/restapis/*/resources/*","arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/integration/responses/*","arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/responses/*","arn:aws:apigateway:*::/restapis/*/stages/*/sdks/*","arn:aws:apigateway:*::/restapis/*/resources/*/methods/*","arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/integration","arn:aws:apigateway:*::/restapis/*/stages","arn:aws:apigateway:*::/restapis/*/stages/*"]},{"Action": ["iam:DeleteRole"],"Effect": "Allow","Resource": ["arn:aws:iam::*:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport"]},{"Action": ["a4b:getDevice","a4b:getProfile","a4b:getRoom","a4b:getRoomSkillParameter","a4b:getSkillGroup","a4b:searchDevices","a4b:searchProfiles","a4b:searchRooms","a4b:searchSkillGroups","access-analyzer:getFinding","access-analyzer:listAnalyzers","access-analyzer:listArchiveRules","access-analyzer:listFindings","acm-pca:describeCertificateAuthority","acm-pca:describeCertificateAuthorityAuditReport","acm-pca:getCertificate","acm-pca:getCertificateAuthorityCertificate","acm-pca:getCertificateAuthorityCsr","acm-pca:listCertificateAuthorities","acm-pca:listTags","acm:describeCertificate","acm:getCertificate","acm:listCertificates","acm:listTagsForCertificate","amplify:getApp","amplify:getBranch","amplify:getDomainAssociation","amplify:getJob","amplify:getWebhook","amplify:listApps","amplify:listWebhooks","application-autoscaling:describeScalableTargets","application-autoscaling:describeScalingActivities","application-autoscaling:describeScalingPolicies","application-autoscaling:describeScheduledActions","appmesh:describeMesh","appmesh:describeRoute","appmesh:describeVirtualNode","appmesh:describeVirtualRouter","appmesh:describeVirtualService","appmesh:listMeshes","appmesh:listRoutes","appmesh:listVirtualNodes","appmesh:listVirtualRouters","appmesh:listVirtualServices","appstream:describeDirectoryConfigs","appstream:describeFleets","appstream:describeImageBuilders","appstream:describeImages","appstream:describeSessions","appstream:describeStacks","appstream:listAssociatedFleets","appstream:listAssociatedStacks","appstream:listTagsForResource","appsync:getFunction","appsync:getGraphqlApi","appsync:getIntrospectionSchema","appsync:getResolver","appsync:getSchemaCreationStatus","appsync:getType","appsync:listDataSources","appsync:listFunctions","appsync:listGraphqlApis","appsync:listResolvers","appsync:listTypes","athena:batchGetNamedQuery","athena:batchGetQueryExecution","athena:getNamedQuery","athena:getQueryExecution","athena:getWorkGroup","athena:listNamedQueries","athena:listQueryExecutions","athena:listTagsForResource","athena:listWorkGroups","autoscaling-plans:describeScalingPlanResources","autoscaling-plans:describeScalingPlans","autoscaling-plans:getScalingPlanResourceForecastData","autoscaling:describeAccountLimits","autoscaling:describeAdjustmentTypes","autoscaling:describeAutoScalingGroups","autoscaling:describeAutoScalingInstances","autoscaling:describeAutoScalingNotificationTypes","autoscaling:describeLaunchConfigurations","autoscaling:describeLifecycleHookTypes","autoscaling:describeLifecycleHooks","autoscaling:describeLoadBalancerTargetGroups","autoscaling:describeLoadBalancers","autoscaling:describeMetricCollectionTypes","autoscaling:describeNotificationConfigurations","autoscaling:describePolicies","autoscaling:describeScalingActivities","autoscaling:describeScalingProcessTypes","autoscaling:describeScheduledActions","autoscaling:describeTags","autoscaling:describeTerminationPolicyTypes","backup:describeBackupJob","backup:describeBackupVault","backup:describeProtectedResource","backup:describeRecoveryPoint","backup:describeRestoreJob","backup:getBackupPlan","backup:getBackupPlanFromJSON","backup:getBackupPlanFromTemplate","backup:getBackupSelection","backup:getBackupVaultAccessPolicy","backup:getBackupVaultNotifications","backup:getRecoveryPointRestoreMetadata","backup:getSupportedResourceTypes","backup:listBackupJobs","backup:listBackupPlanTemplates","backup:listBackupPlanVersions","backup:listBackupPlans","backup:listBackupSelections","backup:listBackupVaults","backup:listProtectedResources","backup:listRecoveryPointsByBackupVault","backup:listRecoveryPointsByResource","backup:listRestoreJobs","backup:listTags","batch:describeComputeEnvironments","batch:describeJobDefinitions","batch:describeJobQueues","batch:describeJobs","batch:listJobs","braket:getDevice","braket:getQuantumTask","braket:searchDevices","braket:searchQuantumTasks","budgets:viewBudget","ce:getCostAndUsage","ce:getDimensionValues","ce:getReservationCoverage","ce:getReservationUtilization","ce:getTags","cloud9:describeEnvironmentMemberships","cloud9:describeEnvironments","cloud9:listEnvironments","clouddirectory:getDirectory","clouddirectory:listDirectories","cloudformation:describeAccountLimits","cloudformation:describeChangeSet","cloudformation:describeStackEvents","cloudformation:describeStackInstance","cloudformation:describeStackResource","cloudformation:describeStackResources","cloudformation:describeStackSet","cloudformation:describeStackSetOperation","cloudformation:describeStacks","cloudformation:estimateTemplateCost","cloudformation:getStackPolicy","cloudformation:getTemplate","cloudformation:getTemplateSummary","cloudformation:listChangeSets","cloudformation:listExports","cloudformation:listImports","cloudformation:listStackInstances","cloudformation:listStackResources","cloudformation:listStackSetOperationResults","cloudformation:listStackSetOperations","cloudformation:listStackSets","cloudformation:listStacks","cloudfront:getCloudFrontOriginAccessIdentity","cloudfront:getCloudFrontOriginAccessIdentityConfig","cloudfront:getDistribution","cloudfront:getDistributionConfig","cloudfront:getInvalidation","cloudfront:getStreamingDistribution","cloudfront:getStreamingDistributionConfig","cloudfront:listCloudFrontOriginAccessIdentities","cloudfront:listDistributions","cloudfront:listDistributionsByWebACLId","cloudfront:listInvalidations","cloudfront:listStreamingDistributions","cloudhsm:describeBackups","cloudhsm:describeClusters","cloudsearch:describeAnalysisSchemes","cloudsearch:describeAvailabilityOptions","cloudsearch:describeDomains","cloudsearch:describeExpressions","cloudsearch:describeIndexFields","cloudsearch:describeScalingParameters","cloudsearch:describeServiceAccessPolicies","cloudsearch:describeSuggesters","cloudsearch:listDomainNames","cloudtrail:describeTrails","cloudtrail:getEventSelectors","cloudtrail:getInsightSelectors","cloudtrail:getTrail","cloudtrail:getTrailStatus","cloudtrail:listPublicKeys","cloudtrail:listTags","cloudtrail:listTrails","cloudtrail:lookupEvents","cloudwatch:describeAlarmHistory","cloudwatch:describeAlarms","cloudwatch:describeAlarmsForMetric","cloudwatch:getDashboard","cloudwatch:getMetricData","cloudwatch:getMetricStatistics","cloudwatch:listDashboards","cloudwatch:listMetrics","codeartifact:describeDomain","codeartifact:describePackageVersion","codeartifact:describeRepository","codeartifact:getDomainPermissionsPolicy","codeartifact:getRepositoryEndPoint","codeartifact:getRepositoryPermissionsPolicy","codeartifact:listDomains","codeartifact:listPackageVersionAssets","codeartifact:listPackageVersions","codeartifact:listPackages","codeartifact:listRepositories","codeartifact:listRepositoriesInDomain","codebuild:batchGetBuildBatches","codebuild:batchGetBuilds","codebuild:batchGetProjects","codebuild:listBuildBatches","codebuild:listBuildBatchesForProject","codebuild:listBuilds","codebuild:listBuildsForProject","codebuild:listCuratedEnvironmentImages","codebuild:listProjects","codebuild:listSourceCredentials","codecommit:batchGetRepositories","codecommit:getBranch","codecommit:getRepository","codecommit:getRepositoryTriggers","codecommit:listBranches","codecommit:listRepositories","codedeploy:batchGetApplicationRevisions","codedeploy:batchGetApplications","codedeploy:batchGetDeploymentGroups","codedeploy:batchGetDeploymentInstances","codedeploy:batchGetDeploymentTargets","codedeploy:batchGetDeployments","codedeploy:batchGetOnPremisesInstances","codedeploy:getApplication","codedeploy:getApplicationRevision","codedeploy:getDeployment","codedeploy:getDeploymentConfig","codedeploy:getDeploymentGroup","codedeploy:getDeploymentInstance","codedeploy:getDeploymentTarget","codedeploy:getOnPremisesInstance","codedeploy:listApplicationRevisions","codedeploy:listApplications","codedeploy:listDeploymentConfigs","codedeploy:listDeploymentGroups","codedeploy:listDeploymentInstances","codedeploy:listDeploymentTargets","codedeploy:listDeployments","codedeploy:listGitHubAccountTokenNames","codedeploy:listOnPremisesInstances","codepipeline:getJobDetails","codepipeline:getPipeline","codepipeline:getPipelineExecution","codepipeline:getPipelineState","codepipeline:listActionExecutions","codepipeline:listActionTypes","codepipeline:listPipelineExecutions","codepipeline:listPipelines","codepipeline:listWebhooks","codestar:describeProject","codestar:listProjects","codestar:listResources","codestar:listTeamMembers","codestar:listUserProfiles","cognito-identity:describeIdentityPool","cognito-identity:getIdentityPoolRoles","cognito-identity:listIdentities","cognito-identity:listIdentityPools","cognito-idp:adminGetUser","cognito-idp:describeIdentityProvider","cognito-idp:describeResourceServer","cognito-idp:describeRiskConfiguration","cognito-idp:describeUserImportJob","cognito-idp:describeUserPool","cognito-idp:describeUserPoolClient","cognito-idp:describeUserPoolDomain","cognito-idp:getGroup","cognito-idp:getUICustomization","cognito-idp:getUser","cognito-idp:getUserPoolMfaConfig","cognito-idp:listGroups","cognito-idp:listIdentityProviders","cognito-idp:listResourceServers","cognito-idp:listUserImportJobs","cognito-idp:listUserPoolClients","cognito-idp:listUserPools","cognito-sync:describeDataset","cognito-sync:describeIdentityPoolUsage","cognito-sync:describeIdentityUsage","cognito-sync:getCognitoEvents","cognito-sync:getIdentityPoolConfiguration","cognito-sync:listDatasets","cognito-sync:listIdentityPoolUsage","compute-optimizer:getAutoScalingGroupRecommendations","compute-optimizer:getEC2InstanceRecommendations","compute-optimizer:getEC2RecommendationProjectedMetrics","compute-optimizer:getEnrollmentStatus","compute-optimizer:getRecommendationSummaries","config:describeConfigRuleEvaluationStatus","config:describeConfigRules","config:describeConfigurationRecorderStatus","config:describeConfigurationRecorders","config:describeDeliveryChannelStatus","config:describeDeliveryChannels","config:getResourceConfigHistory","config:listDiscoveredResources","connect:describeUser","connect:getCurrentMetricData","connect:getMetricData","connect:listRoutingProfiles","connect:listSecurityProfiles","connect:listUsers","controltower:describeAccountFactoryConfig","controltower:describeCoreService","controltower:describeGuardrail","controltower:describeGuardrailForTarget","controltower:describeManagedAccount","controltower:describeSingleSignOn","controltower:getAvailableUpdates","controltower:getHomeRegion","controltower:getLandingZoneStatus","controltower:listDirectoryGroups","controltower:listGuardrailViolations","controltower:listGuardrailsForTarget","controltower:listManagedAccounts","controltower:listManagedAccountsForGuardrail","controltower:listManagedAccountsForParent","controltower:listManagedOrganizationalUnits","controltower:listManagedOrganizationalUnitsForGuardrail","datapipeline:describeObjects","datapipeline:describePipelines","datapipeline:getPipelineDefinition","datapipeline:listPipelines","datapipeline:queryObjects","datasync:describeAgent","datasync:describeLocationEfs","datasync:describeLocationFsxWindows","datasync:describeLocationNfs","datasync:describeLocationS3","datasync:describeLocationSmb","datasync:describeTask","datasync:describeTaskExecution","datasync:listAgents","datasync:listLocations","datasync:listTaskExecutions","datasync:listTasks","dax:describeClusters","dax:describeDefaultParameters","dax:describeEvents","dax:describeParameterGroups","dax:describeParameters","dax:describeSubnetGroups","detective:getMembers","detective:listGraphs","detective:listInvitations","detective:listMembers","devicefarm:getAccountSettings","devicefarm:getDevice","devicefarm:getDevicePool","devicefarm:getDevicePoolCompatibility","devicefarm:getJob","devicefarm:getProject","devicefarm:getRemoteAccessSession","devicefarm:getRun","devicefarm:getSuite","devicefarm:getTest","devicefarm:getTestGridProject","devicefarm:getTestGridSession","devicefarm:getUpload","devicefarm:listArtifacts","devicefarm:listDevicePools","devicefarm:listDevices","devicefarm:listJobs","devicefarm:listProjects","devicefarm:listRemoteAccessSessions","devicefarm:listRuns","devicefarm:listSamples","devicefarm:listSuites","devicefarm:listTestGridProjects","devicefarm:listTestGridSessionActions","devicefarm:listTestGridSessionArtifacts","devicefarm:listTestGridSessions","devicefarm:listTests","devicefarm:listUniqueProblems","devicefarm:listUploads","directconnect:describeConnections","directconnect:describeConnectionsOnInterconnect","directconnect:describeInterconnects","directconnect:describeLocations","directconnect:describeVirtualGateways","directconnect:describeVirtualInterfaces","dlm:getLifecyclePolicies","dlm:getLifecyclePolicy","dms:describeAccountAttributes","dms:describeConnections","dms:describeEndpointTypes","dms:describeEndpoints","dms:describeOrderableReplicationInstances","dms:describeRefreshSchemasStatus","dms:describeReplicationInstances","dms:describeReplicationSubnetGroups","ds:describeConditionalForwarders","ds:describeDirectories","ds:describeEventTopics","ds:describeSnapshots","ds:describeTrusts","ds:getDirectoryLimits","ds:getSnapshotLimits","ds:listIpRoutes","ds:listSchemaExtensions","ds:listTagsForResource","dynamodb:describeBackup","dynamodb:describeContinuousBackups","dynamodb:describeGlobalTable","dynamodb:describeLimits","dynamodb:describeStream","dynamodb:describeTable","dynamodb:describeTimeToLive","dynamodb:listBackups","dynamodb:listGlobalTables","dynamodb:listStreams","dynamodb:listTables","dynamodb:listTagsOfResource","ec2:acceptReservedInstancesExchangeQuote","ec2:cancelReservedInstancesListing","ec2:createReservedInstancesListing","ec2:describeAccountAttributes","ec2:describeAddresses","ec2:describeAvailabilityZones","ec2:describeBundleTasks","ec2:describeByoipCidrs","ec2:describeCapacityReservations","ec2:describeClassicLinkInstances","ec2:describeClientVpnAuthorizationRules","ec2:describeClientVpnConnections","ec2:describeClientVpnEndpoints","ec2:describeClientVpnRoutes","ec2:describeClientVpnTargetNetworks","ec2:describeCoipPools","ec2:describeConversionTasks","ec2:describeCustomerGateways","ec2:describeDhcpOptions","ec2:describeElasticGpus","ec2:describeExportImageTasks","ec2:describeExportTasks","ec2:describeFastSnapshotRestores","ec2:describeFleetHistory","ec2:describeFleetInstances","ec2:describeFleets","ec2:describeFlowLogs","ec2:describeHostReservationOfferings","ec2:describeHostReservations","ec2:describeHosts","ec2:describeIdFormat","ec2:describeIdentityIdFormat","ec2:describeImageAttribute","ec2:describeImages","ec2:describeImportImageTasks","ec2:describeImportSnapshotTasks","ec2:describeInstanceAttribute","ec2:describeInstanceStatus","ec2:describeInstances","ec2:describeInternetGateways","ec2:describeKeyPairs","ec2:describeLaunchTemplateVersions","ec2:describeLaunchTemplates","ec2:describeLocalGatewayRouteTableVirtualInterfaceGroupAssociations","ec2:describeLocalGatewayRouteTableVpcAssociations","ec2:describeLocalGatewayRouteTables","ec2:describeLocalGatewayVirtualInterfaceGroups","ec2:describeLocalGatewayVirtualInterfaces","ec2:describeLocalGateways","ec2:describeMovingAddresses","ec2:describeNatGateways","ec2:describeNetworkAcls","ec2:describeNetworkInterfaceAttribute","ec2:describeNetworkInterfaces","ec2:describePlacementGroups","ec2:describePrefixLists","ec2:describePublicIpv4Pools","ec2:describeRegions","ec2:describeReservedInstances","ec2:describeReservedInstancesListings","ec2:describeReservedInstancesModifications","ec2:describeReservedInstancesOfferings","ec2:describeRouteTables","ec2:describeScheduledInstances","ec2:describeSecurityGroups","ec2:describeSnapshotAttribute","ec2:describeSnapshots","ec2:describeSpotDatafeedSubscription","ec2:describeSpotFleetInstances","ec2:describeSpotFleetRequestHistory","ec2:describeSpotFleetRequests","ec2:describeSpotInstanceRequests","ec2:describeSpotPriceHistory","ec2:describeSubnets","ec2:describeTags","ec2:describeTrafficMirrorFilters","ec2:describeTrafficMirrorSessions","ec2:describeTrafficMirrorTargets","ec2:describeTransitGatewayAttachments","ec2:describeTransitGatewayRouteTables","ec2:describeTransitGatewayVpcAttachments","ec2:describeTransitGateways","ec2:describeVolumeAttribute","ec2:describeVolumeStatus","ec2:describeVolumes","ec2:describeVolumesModifications","ec2:describeVpcAttribute","ec2:describeVpcClassicLink","ec2:describeVpcClassicLinkDnsSupport","ec2:describeVpcEndpointConnectionNotifications","ec2:describeVpcEndpointConnections","ec2:describeVpcEndpointServiceConfigurations","ec2:describeVpcEndpointServicePermissions","ec2:describeVpcEndpointServices","ec2:describeVpcEndpoints","ec2:describeVpcPeeringConnections","ec2:describeVpcs","ec2:describeVpnConnections","ec2:describeVpnGateways","ec2:getCoipPoolUsage","ec2:getConsoleScreenshot","ec2:getReservedInstancesExchangeQuote","ec2:getTransitGatewayAttachmentPropagations","ec2:getTransitGatewayRouteTableAssociations","ec2:getTransitGatewayRouteTablePropagations","ec2:modifyReservedInstances","ec2:purchaseReservedInstancesOffering","ec2:searchLocalGatewayRoutes","ecr:batchCheckLayerAvailability","ecr:describeImages","ecr:describeRepositories","ecr:getRepositoryPolicy","ecr:listImages","ecs:describeClusters","ecs:describeContainerInstances","ecs:describeServices","ecs:describeTaskDefinition","ecs:describeTasks","ecs:listClusters","ecs:listContainerInstances","ecs:listServices","ecs:listTaskDefinitions","ecs:listTasks","eks:describeCluster","eks:describeFargateProfile","eks:describeNodegroup","eks:describeUpdate","eks:listClusters","eks:listFargateProfiles","eks:listNodegroups","eks:listUpdates","elasticache:describeCacheClusters","elasticache:describeCacheEngineVersions","elasticache:describeCacheParameterGroups","elasticache:describeCacheParameters","elasticache:describeCacheSecurityGroups","elasticache:describeCacheSubnetGroups","elasticache:describeEngineDefaultParameters","elasticache:describeEvents","elasticache:describeReplicationGroups","elasticache:describeReservedCacheNodes","elasticache:describeReservedCacheNodesOfferings","elasticache:describeSnapshots","elasticache:listAllowedNodeTypeModifications","elasticache:listTagsForResource","elasticbeanstalk:checkDNSAvailability","elasticbeanstalk:describeApplicationVersions","elasticbeanstalk:describeApplications","elasticbeanstalk:describeConfigurationOptions","elasticbeanstalk:describeConfigurationSettings","elasticbeanstalk:describeEnvironmentHealth","elasticbeanstalk:describeEnvironmentManagedActionHistory","elasticbeanstalk:describeEnvironmentManagedActions","elasticbeanstalk:describeEnvironmentResources","elasticbeanstalk:describeEnvironments","elasticbeanstalk:describeEvents","elasticbeanstalk:describeInstancesHealth","elasticbeanstalk:describePlatformVersion","elasticbeanstalk:listAvailableSolutionStacks","elasticbeanstalk:listPlatformVersions","elasticbeanstalk:validateConfigurationSettings","elasticfilesystem:describeAccessPoints","elasticfilesystem:describeFileSystemPolicy","elasticfilesystem:describeFileSystems","elasticfilesystem:describeLifecycleConfiguration","elasticfilesystem:describeMountTargetSecurityGroups","elasticfilesystem:describeMountTargets","elasticfilesystem:describeTags","elasticfilesystem:listTagsForResource","elasticloadbalancing:describeInstanceHealth","elasticloadbalancing:describeListenerCertificates","elasticloadbalancing:describeListeners","elasticloadbalancing:describeLoadBalancerAttributes","elasticloadbalancing:describeLoadBalancerPolicies","elasticloadbalancing:describeLoadBalancerPolicyTypes","elasticloadbalancing:describeLoadBalancers","elasticloadbalancing:describeRules","elasticloadbalancing:describeSSLPolicies","elasticloadbalancing:describeTags","elasticloadbalancing:describeTargetGroupAttributes","elasticloadbalancing:describeTargetGroups","elasticloadbalancing:describeTargetHealth","elasticmapreduce:describeCluster","elasticmapreduce:describeSecurityConfiguration","elasticmapreduce:describeStep","elasticmapreduce:listBootstrapActions","elasticmapreduce:listClusters","elasticmapreduce:listInstanceGroups","elasticmapreduce:listInstances","elasticmapreduce:listSecurityConfigurations","elasticmapreduce:listSteps","elastictranscoder:listJobsByPipeline","elastictranscoder:listJobsByStatus","elastictranscoder:listPipelines","elastictranscoder:listPresets","elastictranscoder:readPipeline","elastictranscoder:readPreset","es:describeElasticsearchDomain","es:describeElasticsearchDomainConfig","es:describeElasticsearchDomains","es:listDomainNames","es:listTags","events:describeEventBus","events:describeRule","events:listRuleNamesByTarget","events:listRules","events:listTargetsByRule","events:testEventPattern","firehose:describeDeliveryStream","firehose:listDeliveryStreams","fms:getAdminAccount","fms:getComplianceDetail","fms:getNotificationChannel","fms:getPolicy","fms:getProtectionStatus","fms:listComplianceStatus","fms:listMemberAccounts","fms:listPolicies","forecast:describeDataset","forecast:describeDatasetGroup","forecast:describeDatasetImportJob","forecast:describeForecast","forecast:describeForecastExportJob","forecast:describePredictor","forecast:getAccuracyMetrics","forecast:listDatasetGroups","forecast:listDatasetImportJobs","forecast:listDatasets","forecast:listForecastExportJobs","forecast:listForecasts","forecast:listPredictors","fsx:describeBackups","fsx:describeFileSystems","fsx:listTagsForResource","glacier:describeJob","glacier:describeVault","glacier:getDataRetrievalPolicy","glacier:getVaultAccessPolicy","glacier:getVaultLock","glacier:getVaultNotifications","glacier:listJobs","glacier:listTagsForVault","glacier:listVaults","globalaccelerator:describeAccelerator","globalaccelerator:describeAcceleratorAttributes","globalaccelerator:describeEndpointGroup","globalaccelerator:describeListener","globalaccelerator:listAccelerators","globalaccelerator:listEndpointGroups","globalaccelerator:listListeners","glue:batchGetPartition","glue:getCatalogImportStatus","glue:getClassifier","glue:getClassifiers","glue:getCrawler","glue:getCrawlerMetrics","glue:getCrawlers","glue:getDatabase","glue:getDatabases","glue:getDataflowGraph","glue:getDevEndpoint","glue:getDevEndpoints","glue:getJob","glue:getJobRun","glue:getJobRuns","glue:getJobs","glue:getMapping","glue:getPartition","glue:getPartitions","glue:getTable","glue:getTableVersions","glue:getTables","glue:getTrigger","glue:getTriggers","glue:getUserDefinedFunction","glue:getUserDefinedFunctions","greengrass:getConnectivityInfo","greengrass:getCoreDefinition","greengrass:getCoreDefinitionVersion","greengrass:getDeploymentStatus","greengrass:getDeviceDefinition","greengrass:getDeviceDefinitionVersion","greengrass:getFunctionDefinition","greengrass:getFunctionDefinitionVersion","greengrass:getGroup","greengrass:getGroupCertificateAuthority","greengrass:getGroupVersion","greengrass:getLoggerDefinition","greengrass:getLoggerDefinitionVersion","greengrass:getResourceDefinitionVersion","greengrass:getServiceRoleForAccount","greengrass:getSubscriptionDefinition","greengrass:getSubscriptionDefinitionVersion","greengrass:listCoreDefinitionVersions","greengrass:listCoreDefinitions","greengrass:listDeployments","greengrass:listDeviceDefinitionVersions","greengrass:listDeviceDefinitions","greengrass:listFunctionDefinitionVersions","greengrass:listFunctionDefinitions","greengrass:listGroupVersions","greengrass:listGroups","greengrass:listLoggerDefinitionVersions","greengrass:listLoggerDefinitions","greengrass:listResourceDefinitionVersions","greengrass:listResourceDefinitions","greengrass:listSubscriptionDefinitionVersions","greengrass:listSubscriptionDefinitions","guardduty:getDetector","guardduty:getFindings","guardduty:getFindingsStatistics","guardduty:getIPSet","guardduty:getInvitationsCount","guardduty:getMasterAccount","guardduty:getMembers","guardduty:getThreatIntelSet","guardduty:listDetectors","guardduty:listFindings","guardduty:listIPSets","guardduty:listInvitations","guardduty:listMembers","guardduty:listThreatIntelSets","health:describeAffectedEntities","health:describeEntityAggregates","health:describeEventAggregates","health:describeEventDetails","health:describeEventTypes","health:describeEvents","iam:getAccessKeyLastUsed","iam:getAccountAuthorizationDetails","iam:getAccountPasswordPolicy","iam:getAccountSummary","iam:getContextKeysForCustomPolicy","iam:getContextKeysForPrincipalPolicy","iam:getCredentialReport","iam:getGroup","iam:getGroupPolicy","iam:getInstanceProfile","iam:getLoginProfile","iam:getOpenIDConnectProvider","iam:getPolicy","iam:getPolicyVersion","iam:getRole","iam:getRolePolicy","iam:getSAMLProvider","iam:getSSHPublicKey","iam:getServerCertificate","iam:getUser","iam:getUserPolicy","iam:listAccessKeys","iam:listAccountAliases","iam:listAttachedGroupPolicies","iam:listAttachedRolePolicies","iam:listAttachedUserPolicies","iam:listEntitiesForPolicy","iam:listGroupPolicies","iam:listGroups","iam:listGroupsForUser","iam:listInstanceProfiles","iam:listInstanceProfilesForRole","iam:listMFADevices","iam:listOpenIDConnectProviders","iam:listPolicies","iam:listPolicyVersions","iam:listRolePolicies","iam:listRoles","iam:listSAMLProviders","iam:listSSHPublicKeys","iam:listServerCertificates","iam:listSigningCertificates","iam:listUserPolicies","iam:listUsers","iam:listVirtualMFADevices","iam:simulateCustomPolicy","iam:simulatePrincipalPolicy","imagebuilder:getComponent","imagebuilder:getComponentPolicy","imagebuilder:getDistributionConfiguration","imagebuilder:getImage","imagebuilder:getImagePipeline","imagebuilder:getImagePolicy","imagebuilder:getImageRecipe","imagebuilder:getImageRecipePolicy","imagebuilder:getInfrastructureConfiguration","imagebuilder:listComponentBuildVersions","imagebuilder:listComponents","imagebuilder:listDistributionConfigurations","imagebuilder:listImageBuildVersions","imagebuilder:listImagePipelineImages","imagebuilder:listImagePipelines","imagebuilder:listImageRecipes","imagebuilder:listImages","imagebuilder:listInfrastructureConfigurations","imagebuilder:listTagsForResource","importexport:getStatus","importexport:listJobs","inspector:describeAssessmentRuns","inspector:describeAssessmentTargets","inspector:describeAssessmentTemplates","inspector:describeCrossAccountAccessRole","inspector:describeResourceGroups","inspector:describeRulesPackages","inspector:getTelemetryMetadata","inspector:listAssessmentRunAgents","inspector:listAssessmentRuns","inspector:listAssessmentTargets","inspector:listAssessmentTemplates","inspector:listEventSubscriptions","inspector:listRulesPackages","inspector:listTagsForResource","iot:describeAuthorizer","iot:describeCACertificate","iot:describeCertificate","iot:describeDefaultAuthorizer","iot:describeEndpoint","iot:describeIndex","iot:describeJobExecution","iot:describeThing","iot:describeThingGroup","iot:describeTunnel","iot:getEffectivePolicies","iot:getIndexingConfiguration","iot:getLoggingOptions","iot:getPolicy","iot:getPolicyVersion","iot:getTopicRule","iot:getV2LoggingOptions","iot:listAttachedPolicies","iot:listAuthorizers","iot:listCACertificates","iot:listCertificates","iot:listCertificatesByCA","iot:listJobExecutionsForJob","iot:listJobExecutionsForThing","iot:listJobs","iot:listOutgoingCertificates","iot:listPolicies","iot:listPolicyPrincipals","iot:listPolicyVersions","iot:listPrincipalPolicies","iot:listPrincipalThings","iot:listRoleAliases","iot:listTargetsForPolicy","iot:listThingGroups","iot:listThingGroupsForThing","iot:listThingPrincipals","iot:listThingRegistrationTasks","iot:listThingTypes","iot:listThings","iot:listTopicRules","iot:listTunnels","iot:listV2LoggingLevels","iotevents:describeDetector","iotevents:describeDetectorModel","iotevents:describeInput","iotevents:describeLoggingOptions","iotevents:listDetectorModelVersions","iotevents:listDetectorModels","iotevents:listDetectors","iotevents:listInputs","iotsitewise:describeAccessPolicy","iotsitewise:describeAsset","iotsitewise:describeAssetModel","iotsitewise:describeAssetProperty","iotsitewise:describeDashboard","iotsitewise:describeGateway","iotsitewise:describeGatewayCapabilityConfiguration","iotsitewise:describeLoggingOptions","iotsitewise:describePortal","iotsitewise:describeProject","iotsitewise:listAccessPolicies","iotsitewise:listAssetModels","iotsitewise:listAssociatedAssets","iotsitewise:listDashboards","iotsitewise:listGateways","iotsitewise:listPortals","iotsitewise:listProjectAssets","iotsitewise:listProjects","kafka:describeCluster","kafka:getBootstrapBrokers","kafka:listClusters","kafka:listNodes","kendra:describeDataSource","kendra:describeFaq","kendra:describeIndex","kendra:getDataSourceSyncJobHistory","kendra:listDataSources","kendra:listFaqs","kendra:listIndices","kinesis:describeStream","kinesis:listStreams","kinesis:listTagsForStream","kinesisanalytics:describeApplication","kinesisanalytics:listApplications","kms:describeKey","kms:getKeyPolicy","kms:getKeyRotationStatus","kms:listAliases","kms:listGrants","kms:listKeyPolicies","kms:listKeys","kms:listResourceTags","kms:listRetirableGrants","lambda:getAccountSettings","lambda:getAlias","lambda:getEventSourceMapping","lambda:getFunction","lambda:getFunctionConcurrency","lambda:getFunctionConfiguration","lambda:getFunctionEventInvokeConfig","lambda:getLayerVersion","lambda:getLayerVersionPolicy","lambda:getPolicy","lambda:getProvisionedConcurrencyConfig","lambda:listAliases","lambda:listEventSourceMappings","lambda:listFunctionEventInvokeConfigs","lambda:listFunctions","lambda:listLayerVersions","lambda:listLayers","lambda:listProvisionedConcurrencyConfigs","lambda:listVersionsByFunction","launchwizard:describeProvisionedApp","launchwizard:describeProvisioningEvents","launchwizard:listProvisionedApps","lex:getBot","lex:getBotAlias","lex:getBotAliases","lex:getBotChannelAssociation","lex:getBotChannelAssociations","lex:getBotVersions","lex:getBots","lex:getBuiltinIntent","lex:getBuiltinIntents","lex:getBuiltinSlotTypes","lex:getIntent","lex:getIntentVersions","lex:getIntents","lex:getSlotType","lex:getSlotTypeVersions","lex:getSlotTypes","license-manager:getLicenseConfiguration","license-manager:getServiceSettings","license-manager:listAssociationsForLicenseConfiguration","license-manager:listFailuresForLicenseConfigurationOperations","license-manager:listLicenseConfigurations","license-manager:listLicenseSpecificationsForResource","license-manager:listResourceInventory","license-manager:listUsageForLicenseConfiguration","lightsail:getActiveNames","lightsail:getBlueprints","lightsail:getBundles","lightsail:getDomain","lightsail:getDomains","lightsail:getInstance","lightsail:getInstanceMetricData","lightsail:getInstancePortStates","lightsail:getInstanceSnapshot","lightsail:getInstanceSnapshots","lightsail:getInstanceState","lightsail:getInstances","lightsail:getKeyPair","lightsail:getKeyPairs","lightsail:getOperation","lightsail:getOperations","lightsail:getOperationsForResource","lightsail:getRegions","lightsail:getStaticIp","lightsail:getStaticIps","logs:describeDestinations","logs:describeExportTasks","logs:describeLogGroups","logs:describeLogStreams","logs:describeMetricFilters","logs:describeQueries","logs:describeSubscriptionFilters","logs:testMetricFilter","machinelearning:describeBatchPredictions","machinelearning:describeDataSources","machinelearning:describeEvaluations","machinelearning:describeMLModels","machinelearning:getBatchPrediction","machinelearning:getDataSource","machinelearning:getEvaluation","machinelearning:getMLModel","managedblockchain:getMember","managedblockchain:getNetwork","managedblockchain:getNode","managedblockchain:listMembers","managedblockchain:listNetworks","managedblockchain:listNodes","mediaconvert:describeEndpoints","mediaconvert:getJob","mediaconvert:getJobTemplate","mediaconvert:getPreset","mediaconvert:getQueue","mediaconvert:listJobTemplates","mediaconvert:listJobs","medialive:describeChannel","medialive:describeInput","medialive:describeInputDevice","medialive:describeInputSecurityGroup","medialive:describeMultiplex","medialive:describeOffering","medialive:describeReservation","medialive:describeSchedule","medialive:listChannels","medialive:listInputDevices","medialive:listInputSecurityGroups","medialive:listInputs","medialive:listMultiplexes","medialive:listOfferings","medialive:listReservations","mediapackage:describeChannel","mediapackage:describeOriginEndpoint","mediapackage:listChannels","mediapackage:listOriginEndpoints","mediastore:describeContainer","mediastore:describeObject","mediastore:getContainerPolicy","mediastore:getCorsPolicy","mediastore:listContainers","mediastore:listItems","mediatailor:getPlaybackConfiguration","mediatailor:listPlaybackConfigurations","mobiletargeting:getAdmChannel","mobiletargeting:getApnsChannel","mobiletargeting:getApnsSandboxChannel","mobiletargeting:getApnsVoipChannel","mobiletargeting:getApnsVoipSandboxChannel","mobiletargeting:getApp","mobiletargeting:getApplicationSettings","mobiletargeting:getApps","mobiletargeting:getBaiduChannel","mobiletargeting:getCampaign","mobiletargeting:getCampaignActivities","mobiletargeting:getCampaignVersion","mobiletargeting:getCampaignVersions","mobiletargeting:getCampaigns","mobiletargeting:getEmailChannel","mobiletargeting:getEndpoint","mobiletargeting:getEventStream","mobiletargeting:getExportJob","mobiletargeting:getExportJobs","mobiletargeting:getGcmChannel","mobiletargeting:getImportJob","mobiletargeting:getImportJobs","mobiletargeting:getSegment","mobiletargeting:getSegmentImportJobs","mobiletargeting:getSegmentVersion","mobiletargeting:getSegmentVersions","mobiletargeting:getSegments","mobiletargeting:getSmsChannel","mq:describeBroker","mq:describeConfiguration","mq:describeConfigurationRevision","mq:describeUser","mq:listBrokers","mq:listConfigurationRevisions","mq:listConfigurations","mq:listUsers","networkmanager:describeGlobalNetworks","networkmanager:getCustomerGatewayAssociations","networkmanager:getDevices","networkmanager:getLinkAssociations","networkmanager:getLinks","networkmanager:getSites","networkmanager:getTransitGatewayRegistrations","opsworks-cm:describeAccountAttributes","opsworks-cm:describeBackups","opsworks-cm:describeEvents","opsworks-cm:describeNodeAssociationStatus","opsworks-cm:describeServers","opsworks:describeAgentVersions","opsworks:describeApps","opsworks:describeCommands","opsworks:describeDeployments","opsworks:describeEcsClusters","opsworks:describeElasticIps","opsworks:describeElasticLoadBalancers","opsworks:describeInstances","opsworks:describeLayers","opsworks:describeLoadBasedAutoScaling","opsworks:describeMyUserProfile","opsworks:describePermissions","opsworks:describeRaidArrays","opsworks:describeRdsDbInstances","opsworks:describeServiceErrors","opsworks:describeStackProvisioningParameters","opsworks:describeStackSummary","opsworks:describeStacks","opsworks:describeTimeBasedAutoScaling","opsworks:describeUserProfiles","opsworks:describeVolumes","opsworks:getHostnameSuggestion","outposts:getOutpost","outposts:getOutpostInstanceTypes","outposts:listOutposts","outposts:listSites","personalize:describeAlgorithm","personalize:describeCampaign","personalize:describeDataset","personalize:describeDatasetGroup","personalize:describeDatasetImportJob","personalize:describeEventTracker","personalize:describeFeatureTransformation","personalize:describeRecipe","personalize:describeSchema","personalize:describeSolution","personalize:describeSolutionVersion","personalize:listCampaigns","personalize:listDatasetGroups","personalize:listDatasetImportJobs","personalize:listDatasets","personalize:listEventTrackers","personalize:listRecipes","personalize:listSchemas","personalize:listSolutionVersions","personalize:listSolutions","polly:describeVoices","polly:getLexicon","polly:listLexicons","pricing:describeServices","pricing:getAttributeValues","pricing:getProducts","quicksight:describeDashboard","quicksight:describeDashboardPermissions","quicksight:describeGroup","quicksight:describeIAMPolicyAssignment","quicksight:describeTemplate","quicksight:describeTemplateAlias","quicksight:describeTemplatePermissions","quicksight:describeUser","quicksight:listDashboards","quicksight:listGroupMemberships","quicksight:listGroups","quicksight:listIAMPolicyAssignments","quicksight:listIAMPolicyAssignmentsForUser","quicksight:listTemplateAliases","quicksight:listTemplateVersions","quicksight:listTemplates","quicksight:listUserGroups","quicksight:listUsers","rds:describeAccountAttributes","rds:describeCertificates","rds:describeDBClusterParameterGroups","rds:describeDBClusterParameters","rds:describeDBClusterSnapshots","rds:describeDBClusters","rds:describeDBEngineVersions","rds:describeDBInstances","rds:describeDBParameterGroups","rds:describeDBParameters","rds:describeDBSecurityGroups","rds:describeDBSnapshotAttributes","rds:describeDBSnapshots","rds:describeDBSubnetGroups","rds:describeEngineDefaultClusterParameters","rds:describeEngineDefaultParameters","rds:describeEventCategories","rds:describeEventSubscriptions","rds:describeEvents","rds:describeOptionGroupOptions","rds:describeOptionGroups","rds:describeOrderableDBInstanceOptions","rds:describePendingMaintenanceActions","rds:describeReservedDBInstances","rds:describeReservedDBInstancesOfferings","rds:listTagsForResource","redshift:describeClusterParameterGroups","redshift:describeClusterParameters","redshift:describeClusterSecurityGroups","redshift:describeClusterSnapshots","redshift:describeClusterSubnetGroups","redshift:describeClusterVersions","redshift:describeClusters","redshift:describeDefaultClusterParameters","redshift:describeEventCategories","redshift:describeEventSubscriptions","redshift:describeEvents","redshift:describeHsmClientCertificates","redshift:describeHsmConfigurations","redshift:describeLoggingStatus","redshift:describeOrderableClusterOptions","redshift:describeReservedNodeOfferings","redshift:describeReservedNodes","redshift:describeResize","redshift:describeSnapshotCopyGrants","redshift:describeStorage","redshift:describeTableRestoreStatus","redshift:describeTags","rekognition:listCollections","rekognition:listFaces","resource-groups:getGroup","resource-groups:getGroupQuery","resource-groups:getTags","resource-groups:listGroupResources","resource-groups:listGroups","resource-groups:searchResources","robomaker:batchDescribeSimulationJob","robomaker:describeDeploymentJob","robomaker:describeFleet","robomaker:describeRobot","robomaker:describeRobotApplication","robomaker:describeSimulationApplication","robomaker:describeSimulationJob","robomaker:listDeploymentJobs","robomaker:listFleets","robomaker:listRobotApplications","robomaker:listRobots","robomaker:listSimulationApplications","robomaker:listSimulationJobs","route53:getChange","route53:getCheckerIpRanges","route53:getGeoLocation","route53:getHealthCheck","route53:getHealthCheckCount","route53:getHealthCheckLastFailureReason","route53:getHealthCheckStatus","route53:getHostedZone","route53:getHostedZoneCount","route53:getReusableDelegationSet","route53:getTrafficPolicy","route53:getTrafficPolicyInstance","route53:getTrafficPolicyInstanceCount","route53:listGeoLocations","route53:listHealthChecks","route53:listHostedZones","route53:listHostedZonesByName","route53:listResourceRecordSets","route53:listReusableDelegationSets","route53:listTagsForResource","route53:listTagsForResources","route53:listTrafficPolicies","route53:listTrafficPolicyInstances","route53:listTrafficPolicyInstancesByHostedZone","route53:listTrafficPolicyInstancesByPolicy","route53:listTrafficPolicyVersions","route53domains:checkDomainAvailability","route53domains:getContactReachabilityStatus","route53domains:getDomainDetail","route53domains:getOperationDetail","route53domains:listDomains","route53domains:listOperations","route53domains:listTagsForDomain","route53domains:viewBilling","route53resolver:getResolverRulePolicy","route53resolver:listResolverEndpointIpAddresses","route53resolver:listResolverEndpoints","route53resolver:listResolverRuleAssociations","route53resolver:listResolverRules","route53resolver:listTagsForResource","s3:getAccelerateConfiguration","s3:getAnalyticsConfiguration","s3:getBucketAcl","s3:getBucketCORS","s3:getBucketLocation","s3:getBucketLogging","s3:getBucketNotification","s3:getBucketPolicy","s3:getBucketRequestPayment","s3:getBucketTagging","s3:getBucketVersioning","s3:getBucketWebsite","s3:getEncryptionConfiguration","s3:getInventoryConfiguration","s3:getLifecycleConfiguration","s3:getMetricsConfiguration","s3:getReplicationConfiguration","s3:listAllMyBuckets","s3:listBucket","s3:listBucketMultipartUploads","sagemaker:describeAlgorithm","sagemaker:describeApp","sagemaker:describeAutoMLJob","sagemaker:describeCompilationJob","sagemaker:describeDomain","sagemaker:describeEndpoint","sagemaker:describeEndpointConfig","sagemaker:describeExperiment","sagemaker:describeHumanTaskUi","sagemaker:describeHyperParameterTuningJob","sagemaker:describeLabelingJob","sagemaker:describeModel","sagemaker:describeModelPackage","sagemaker:describeMonitoringSchedule","sagemaker:describeNotebookInstance","sagemaker:describeNotebookInstanceLifecycleConfig","sagemaker:describeProcessingJob","sagemaker:describeSubscribedWorkteam","sagemaker:describeTrainingJob","sagemaker:describeTransformJob","sagemaker:describeTrial","sagemaker:describeTrialComponent","sagemaker:describeUserProfile","sagemaker:describeWorkteam","sagemaker:listAlgorithms","sagemaker:listApps","sagemaker:listAutoMLJobs","sagemaker:listCandidatesForAutoMLJob","sagemaker:listCodeRepositories","sagemaker:listCompilationJobs","sagemaker:listDomains","sagemaker:listEndpointConfigs","sagemaker:listEndpoints","sagemaker:listExperiments","sagemaker:listFlowDefinitions","sagemaker:listHumanTaskUis","sagemaker:listHyperParameterTuningJobs","sagemaker:listLabelingJobs","sagemaker:listLabelingJobsForWorkteam","sagemaker:listModelPackages","sagemaker:listModels","sagemaker:listMonitoringExecutions","sagemaker:listMonitoringSchedules","sagemaker:listNotebookInstanceLifecycleConfigs","sagemaker:listNotebookInstances","sagemaker:listProcessingJobs","sagemaker:listSubscribedWorkteams","sagemaker:listTags","sagemaker:listTrainingJobs","sagemaker:listTrainingJobsForHyperParameterTuningJob","sagemaker:listTransformJobs","sagemaker:listTrialComponents","sagemaker:listTrials","sagemaker:listUserProfiles","sagemaker:listWorkteams","sdb:domainMetadata","sdb:listDomains","secretsmanager:describeSecret","secretsmanager:getResourcePolicy","secretsmanager:listSecretVersionIds","secretsmanager:listSecrets","securityhub:getEnabledStandards","securityhub:getFindings","securityhub:getInsightResults","securityhub:getInsights","securityhub:getMasterAccount","securityhub:getMembers","securityhub:listEnabledProductsForImport","securityhub:listInvitations","securityhub:listMembers","servicecatalog:describeConstraint","servicecatalog:describePortfolio","servicecatalog:describeProduct","servicecatalog:describeProductAsAdmin","servicecatalog:describeProductView","servicecatalog:describeProvisioningArtifact","servicecatalog:describeProvisioningParameters","servicecatalog:describeRecord","servicecatalog:listAcceptedPortfolioShares","servicecatalog:listConstraintsForPortfolio","servicecatalog:listLaunchPaths","servicecatalog:listPortfolioAccess","servicecatalog:listPortfolios","servicecatalog:listPortfoliosForProduct","servicecatalog:listPrincipalsForPortfolio","servicecatalog:listProvisioningArtifacts","servicecatalog:listRecordHistory","servicecatalog:scanProvisionedProducts","servicecatalog:searchProducts","servicequotas:getAWSDefaultServiceQuota","servicequotas:getAssociationForServiceQuotaTemplate","servicequotas:getRequestedServiceQuotaChange","servicequotas:getServiceQuota","servicequotas:getServiceQuotaIncreaseRequestFromTemplate","servicequotas:listAWSDefaultServiceQuotas","servicequotas:listRequestedServiceQuotaChangeHistory","servicequotas:listRequestedServiceQuotaChangeHistoryByQuota","servicequotas:listServiceQuotaIncreaseRequestsInTemplate","servicequotas:listServiceQuotas","servicequotas:listServices","ses:describeActiveReceiptRuleSet","ses:describeReceiptRule","ses:describeReceiptRuleSet","ses:getAccount","ses:getBlacklistReports","ses:getConfigurationSet","ses:getConfigurationSetEventDestinations","ses:getDedicatedIp","ses:getDedicatedIps","ses:getDeliverabilityDashboardOptions","ses:getDeliverabilityTestReport","ses:getDomainDeliverabilityCampaign","ses:getDomainStatisticsReport","ses:getEmailIdentity","ses:getIdentityDkimAttributes","ses:getIdentityMailFromDomainAttributes","ses:getIdentityNotificationAttributes","ses:getIdentityPolicies","ses:getIdentityVerificationAttributes","ses:getSendQuota","ses:getSendStatistics","ses:listConfigurationSets","ses:listDedicatedIpPools","ses:listDeliverabilityTestReports","ses:listDomainDeliverabilityCampaigns","ses:listEmailIdentities","ses:listIdentities","ses:listIdentityPolicies","ses:listReceiptFilters","ses:listReceiptRuleSets","ses:listTagsForResource","ses:listVerifiedEmailAddresses","shield:describeAttack","shield:describeProtection","shield:describeSubscription","shield:listAttacks","shield:listProtections","sms-voice:getConfigurationSetEventDestinations","sms:getConnectors","sms:getReplicationJobs","sms:getReplicationRuns","sms:getServers","snowball:describeAddress","snowball:describeAddresses","snowball:describeJob","snowball:getSnowballUsage","snowball:listJobs","sns:checkIfPhoneNumberIsOptedOut","sns:getEndpointAttributes","sns:getPlatformApplicationAttributes","sns:getSMSAttributes","sns:getSubscriptionAttributes","sns:getTopicAttributes","sns:listEndpointsByPlatformApplication","sns:listPhoneNumbersOptedOut","sns:listPlatformApplications","sns:listSubscriptions","sns:listSubscriptionsByTopic","sns:listTopics","sqs:getQueueAttributes","sqs:getQueueUrl","sqs:listDeadLetterSourceQueues","sqs:listQueues","ssm:describeActivations","ssm:describeAssociation","ssm:describeAssociationExecutionTargets","ssm:describeAssociationExecutions","ssm:describeAutomationExecutions","ssm:describeAutomationStepExecutions","ssm:describeAvailablePatches","ssm:describeDocument","ssm:describeDocumentPermission","ssm:describeEffectiveInstanceAssociations","ssm:describeEffectivePatchesForPatchBaseline","ssm:describeInstanceAssociationsStatus","ssm:describeInstanceInformation","ssm:describeInstancePatchStates","ssm:describeInstancePatchStatesForPatchGroup","ssm:describeInstancePatches","ssm:describeInventoryDeletions","ssm:describeMaintenanceWindowExecutionTaskInvocations","ssm:describeMaintenanceWindowExecutionTasks","ssm:describeMaintenanceWindowExecutions","ssm:describeMaintenanceWindowSchedule","ssm:describeMaintenanceWindowTargets","ssm:describeMaintenanceWindowTasks","ssm:describeMaintenanceWindows","ssm:describeMaintenanceWindowsForTarget","ssm:describeParameters","ssm:describePatchBaselines","ssm:describePatchGroupState","ssm:describePatchGroups","ssm:describePatchProperties","ssm:describeSessions","ssm:getAutomationExecution","ssm:getCommandInvocation","ssm:getConnectionStatus","ssm:getDefaultPatchBaseline","ssm:getDeployablePatchSnapshotForInstance","ssm:getInventorySchema","ssm:getMaintenanceWindow","ssm:getMaintenanceWindowExecution","ssm:getMaintenanceWindowExecutionTask","ssm:getMaintenanceWindowExecutionTaskInvocation","ssm:getMaintenanceWindowTask","ssm:getPatchBaseline","ssm:getPatchBaselineForPatchGroup","ssm:getServiceSetting","ssm:labelParameterVersion","ssm:listAssociationVersions","ssm:listAssociations","ssm:listCommandInvocations","ssm:listCommands","ssm:listComplianceItems","ssm:listComplianceSummaries","ssm:listDocumentVersions","ssm:listDocuments","ssm:listResourceComplianceSummaries","ssm:listResourceDataSync","ssm:listTagsForResource","states:describeActivity","states:describeExecution","states:describeStateMachine","states:describeStateMachineForExecution","states:getExecutionHistory","states:listActivities","states:listExecutions","states:listStateMachines","storagegateway:describeBandwidthRateLimit","storagegateway:describeCache","storagegateway:describeCachediSCSIVolumes","storagegateway:describeGatewayInformation","storagegateway:describeMaintenanceStartTime","storagegateway:describeNFSFileShares","storagegateway:describeSMBFileShares","storagegateway:describeSMBSettings","storagegateway:describeSnapshotSchedule","storagegateway:describeStorediSCSIVolumes","storagegateway:describeTapeArchives","storagegateway:describeTapeRecoveryPoints","storagegateway:describeTapes","storagegateway:describeUploadBuffer","storagegateway:describeVTLDevices","storagegateway:describeWorkingStorage","storagegateway:listFileShares","storagegateway:listGateways","storagegateway:listLocalDisks","storagegateway:listTagsForResource","storagegateway:listTapes","storagegateway:listVolumeInitiators","storagegateway:listVolumeRecoveryPoints","storagegateway:listVolumes","swf:countClosedWorkflowExecutions","swf:countOpenWorkflowExecutions","swf:countPendingActivityTasks","swf:countPendingDecisionTasks","swf:describeActivityType","swf:describeDomain","swf:describeWorkflowExecution","swf:describeWorkflowType","swf:getWorkflowExecutionHistory","swf:listActivityTypes","swf:listClosedWorkflowExecutions","swf:listDomains","swf:listOpenWorkflowExecutions","swf:listWorkflowTypes","transfer:describeServer","transfer:describeUser","transfer:listServers","transfer:listTagsForResource","transfer:listUsers","waf-regional:getByteMatchSet","waf-regional:getChangeTokenStatus","waf-regional:getIPSet","waf-regional:getRule","waf-regional:getSqlInjectionMatchSet","waf-regional:getWebACL","waf-regional:getWebACLForResource","waf-regional:listByteMatchSets","waf-regional:listIPSets","waf-regional:listResourcesForWebACL","waf-regional:listRules","waf-regional:listSqlInjectionMatchSets","waf-regional:listWebACLs","waf:getByteMatchSet","waf:getChangeTokenStatus","waf:getIPSet","waf:getRule","waf:getSampledRequests","waf:getSizeConstraintSet","waf:getSqlInjectionMatchSet","waf:getWebACL","waf:getXssMatchSet","waf:listByteMatchSets","waf:listIPSets","waf:listRules","waf:listSizeConstraintSets","waf:listSqlInjectionMatchSets","waf:listWebACLs","waf:listXssMatchSets","wafv2:checkCapacity","wafv2:describeManagedRuleGroup","wafv2:getIPSet","wafv2:getLoggingConfiguration","wafv2:getPermissionPolicy","wafv2:getRateBasedStatementManagedKeys","wafv2:getRegexPatternSet","wafv2:getRuleGroup","wafv2:getSampledRequests","wafv2:getWebACL","wafv2:getWebACLForResource","wafv2:listAvailableManagedRuleGroups","wafv2:listIPSets","wafv2:listLoggingConfigurations","wafv2:listRegexPatternSets","wafv2:listResourcesForWebACL","wafv2:listRuleGroups","wafv2:listTagsForResource","wafv2:listWebACLs","workdocs:checkAlias","workdocs:describeAvailableDirectories","workdocs:describeInstances","worklink:describeAuditStreamConfiguration","worklink:describeCompanyNetworkConfiguration","worklink:describeDevice","worklink:describeDevicePolicyConfiguration","worklink:describeDomain","worklink:describeFleetMetadata","worklink:describeIdentityProviderConfiguration","worklink:describeWebsiteCertificateAuthority","worklink:listDevices","worklink:listDomains","worklink:listFleets","worklink:listWebsiteAuthorizationProviders","worklink:listWebsiteCertificateAuthorities","workmail:describeGroup","workmail:describeOrganization","workmail:describeResource","workmail:describeUser","workmail:listAliases","workmail:listGroupMembers","workmail:listGroups","workmail:listMailboxPermissions","workmail:listOrganizations","workmail:listResourceDelegates","workmail:listResources","workmail:listUsers","workspaces:describeAccount","workspaces:describeAccountModifications","workspaces:describeIpGroups","workspaces:describeTags","workspaces:describeWorkspaceBundles","workspaces:describeWorkspaceDirectories","workspaces:describeWorkspaceImages","workspaces:describeWorkspaces","workspaces:describeWorkspacesConnectionStatus"],"Effect": "Allow","Resource": ["*"]}],"Version": "2012-10-17"},"arn": "arn:aws:iam::aws:policy/aws-service-role/AWSSupportServiceRolePolicy","attached_to": {"roles": [{"id": "AROAJCXETX2ROIWUKOPGG","name": "AWSServiceRoleForSupport"}]},"id": "ANPAJ7W6266ELXF5MISDS","name": "AWSSupportServiceRolePolicy"},"ANPAJH4QJ2WMHBOB47BUE": {"PolicyDocument": {"Statement": [{"Action": ["autoscaling:DescribeAccountLimits","autoscaling:DescribeAutoScalingGroups","autoscaling:DescribeLaunchConfigurations","cloudformation:DescribeAccountLimits","cloudformation:DescribeStacks","cloudformation:ListStacks","cloudfront:ListDistributions","cloudtrail:DescribeTrails","cloudtrail:GetTrailStatus","dynamodb:DescribeLimits","dynamodb:DescribeTable","dynamodb:ListTables","ec2:DescribeAddresses","ec2:DescribeReservedInstances","ec2:DescribeInstances","ec2:DescribeVpcs","ec2:DescribeInternetGateways","ec2:DescribeImages","ec2:DescribeVolumes","ec2:DescribeSecurityGroups","ec2:DescribeReservedInstancesOfferings","ec2:DescribeSnapshots","ec2:DescribeVpnConnections","ec2:DescribeVpnGateways","ec2:DescribeLaunchTemplateVersions","elasticloadbalancing:DescribeAccountLimits","elasticloadbalancing:DescribeInstanceHealth","elasticloadbalancing:DescribeLoadBalancerAttributes","elasticloadbalancing:DescribeLoadBalancerPolicies","elasticloadbalancing:DescribeLoadBalancerPolicyTypes","elasticloadbalancing:DescribeLoadBalancers","iam:GenerateCredentialReport","iam:GetAccountPasswordPolicy","iam:GetAccountSummary","iam:GetCredentialReport","iam:GetServerCertificate","iam:ListServerCertificates","kinesis:DescribeLimits","rds:DescribeAccountAttributes","rds:DescribeDBClusters","rds:DescribeDBEngineVersions","rds:DescribeDBInstances","rds:DescribeDBParameterGroups","rds:DescribeDBParameters","rds:DescribeDBSecurityGroups","rds:DescribeDBSnapshots","rds:DescribeDBSubnetGroups","rds:DescribeEngineDefaultParameters","rds:DescribeEvents","rds:DescribeOptionGroupOptions","rds:DescribeOptionGroups","rds:DescribeOrderableDBInstanceOptions","rds:DescribeReservedDBInstances","rds:DescribeReservedDBInstancesOfferings","rds:ListTagsForResource","redshift:DescribeClusters","redshift:DescribeReservedNodeOfferings","redshift:DescribeReservedNodes","route53:GetAccountLimit","route53:GetHealthCheck","route53:GetHostedZone","route53:ListHealthChecks","route53:ListHostedZones","route53:ListHostedZonesByName","route53:ListResourceRecordSets","s3:GetBucketAcl","s3:GetBucketPolicy","s3:GetBucketPolicyStatus","s3:GetBucketLocation","s3:GetBucketLogging","s3:GetBucketVersioning","s3:GetBucketPublicAccessBlock","s3:ListBucket","s3:ListAllMyBuckets","ses:GetSendQuota","sqs:ListQueues","cloudwatch:GetMetricStatistics","ce:GetReservationPurchaseRecommendation","ce:GetSavingsPlansPurchaseRecommendation"],"Effect": "Allow","Resource": ["*"]}],"Version": "2012-10-17"},"arn": "arn:aws:iam::aws:policy/aws-service-role/AWSTrustedAdvisorServiceRolePolicy","attached_to": {"roles": [{"id": "AROAJCHEQKY4NYQFQWP5K","name": "AWSServiceRoleForTrustedAdvisor"}]},"id": "ANPAJH4QJ2WMHBOB47BUE","name": "AWSTrustedAdvisorServiceRolePolicy"},"ANPAJSVXG6QHPE6VHDZ4Q": {"PolicyDocument": {"Statement": [{"Action": ["cloudwatch:DescribeAlarms","elasticmapreduce:ListInstanceGroups","elasticmapreduce:ModifyInstanceGroups"],"Effect": "Allow","Resource": ["*"]}],"Version": "2012-10-17"},"arn": "arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceforAutoScalingRole","attached_to": {"roles": [{"id": "AROAIH747R37LKSEOZ2MA","name": "EMR_AutoScaling_DefaultRole"}]},"id": "ANPAJSVXG6QHPE6VHDZ4Q","name": "AmazonElasticMapReduceforAutoScalingRole"}},"policies_count": 8,"roles": {"AROAI265GPNVMDZAKJPPA": {"CreateDate": "2019-01-26 09:04:06+00:00","Path": "/","arn": "arn:aws:iam::430150006394:role/EMR_EC2_DefaultRole","assume_role_policy": {"PolicyDocument": {"Statement": [{"Action": ["sts:AssumeRole"],"Effect": "Allow","Principal": {"Service": "ec2.amazonaws.com"},"Sid": ""}],"Version": "2008-10-17"}},"id": "AROAI265GPNVMDZAKJPPA","inline_policies_count": 0,"instance_profiles": {"AIPAJLM3SI3PSXMHLNA24": {"arn": "arn:aws:iam::430150006394:instance-profile/EMR_EC2_DefaultRole","name": "EMR_EC2_DefaultRole"}},"instances_count": 0,"name": "EMR_EC2_DefaultRole","policies": ["ANPAIGALS5RCDLZLB3PGS"],"policies_counts": 1},"AROAIH747R37LKSEOZ2MA": {"CreateDate": "2019-01-26 09:04:06+00:00","Path": "/","arn": "arn:aws:iam::430150006394:role/EMR_AutoScaling_DefaultRole","assume_role_policy": {"PolicyDocument": {"Statement": [{"Action": ["sts:AssumeRole"],"Effect": "Allow","Principal": {"Service": ["application-autoscaling.amazonaws.com","elasticmapreduce.amazonaws.com"]}}],"Version": "2012-10-17"}},"id": "AROAIH747R37LKSEOZ2MA","inline_policies_count": 0,"instance_profiles": {},"instances_count": 0,"name": "EMR_AutoScaling_DefaultRole","policies": ["ANPAJSVXG6QHPE6VHDZ4Q"],"policies_counts": 1},"AROAIXBSWIKGEEDLMO53I": {"CreateDate": "2019-01-26 09:04:06+00:00","Path": "/","arn": "arn:aws:iam::430150006394:role/EMR_DefaultRole","assume_role_policy": {"PolicyDocument": {"Statement": [{"Action": ["sts:AssumeRole"],"Effect": "Allow","Principal": {"Service": "elasticmapreduce.amazonaws.com"},"Sid": ""}],"Version": "2008-10-17"}},"id": "AROAIXBSWIKGEEDLMO53I","inline_policies_count": 0,"instance_profiles": {},"instances_count": 0,"name": "EMR_DefaultRole","policies": ["ANPAIDI2BQT2LKXZG36TW"],"policies_counts": 1},"AROAJ2LRZXYT2USPF2ZTY": {"CreateDate": "2019-01-26 09:04:23+00:00","Path": "/aws-service-role/elasticmapreduce.amazonaws.com/","arn": "arn:aws:iam::430150006394:role/aws-service-role/elasticmapreduce.amazonaws.com/AWSServiceRoleForEMRCleanup","assume_role_policy": {"PolicyDocument": {"Statement": [{"Action": ["sts:AssumeRole"],"Effect": "Allow","Principal": {"Service": "elasticmapreduce.amazonaws.com"}}],"Version": "2012-10-17"}},"id": "AROAJ2LRZXYT2USPF2ZTY","inline_policies_count": 0,"instance_profiles": {},"instances_count": 0,"name": "AWSServiceRoleForEMRCleanup","policies": ["ANPAI4YEZURRMKACW56EA"],"policies_counts": 1},"AROAJCHEQKY4NYQFQWP5K": {"CreateDate": "2018-08-15 22:08:26+00:00","Path": "/aws-service-role/trustedadvisor.amazonaws.com/","arn": "arn:aws:iam::430150006394:role/aws-service-role/trustedadvisor.amazonaws.com/AWSServiceRoleForTrustedAdvisor","assume_role_policy": {"PolicyDocument": {"Statement": [{"Action": ["sts:AssumeRole"],"Effect": "Allow","Principal": {"Service": "trustedadvisor.amazonaws.com"}}],"Version": "2012-10-17"}},"id": "AROAJCHEQKY4NYQFQWP5K","inline_policies_count": 0,"instance_profiles": {},"instances_count": 0,"name": "AWSServiceRoleForTrustedAdvisor","policies": ["ANPAJH4QJ2WMHBOB47BUE"],"policies_counts": 1},"AROAJCXETX2ROIWUKOPGG": {"CreateDate": "2018-08-09 19:34:27+00:00","Path": "/aws-service-role/support.amazonaws.com/","arn": "arn:aws:iam::430150006394:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport","assume_role_policy": {"PolicyDocument": {"Statement": [{"Action": ["sts:AssumeRole"],"Effect": "Allow","Principal": {"Service": "support.amazonaws.com"}}],"Version": "2012-10-17"}},"id": "AROAJCXETX2ROIWUKOPGG","inline_policies_count": 0,"instance_profiles": {},"instances_count": 0,"name": "AWSServiceRoleForSupport","policies": ["ANPAJ7W6266ELXF5MISDS"],"policies_counts": 1},"AROAJY5MNJYDKGD2UIATQ": {"CreateDate": "2019-01-23 17:01:24+00:00","Path": "/service-role/","arn": "arn:aws:iam::430150006394:role/service-role/load-wikipedia","assume_role_policy": {"PolicyDocument": {"Statement": [{"Action": ["sts:AssumeRole"],"Effect": "Allow","Principal": {"Service": "lambda.amazonaws.com"}}],"Version": "2012-10-17"}},"id": "AROAJY5MNJYDKGD2UIATQ","inline_policies_count": 0,"instance_profiles": {},"instances_count": 0,"name": "load-wikipedia","policies": ["ANPAIDFYJXP7KKG7FLVWO"],"policies_counts": 1}},"roles_count": 7,"service": "iam","thread_config": {"list": 10,"parse": 20},"users": {"AIDAJUK77MEJCW5J3DWZU": {"AccessKeys": [{"AccessKeyId": "AKIAJA4OP6C7FVAIIK6A","CreateDate": "2013-12-19 09:13:40+00:00","Status": "Active","UserName": "dams"},{"AccessKeyId": "AKIAI6RSA3TKSH5RFPJQ","CreateDate": "2019-01-25 17:58:41+00:00","Status": "Active","UserName": "dams"}],"CreateDate": "2013-12-19 09:13:40+00:00","MFADevices": [],"Path": "/","arn": "arn:aws:iam::430150006394:user/dams","groups": ["devs"],"id": "AIDAJUK77MEJCW5J3DWZU","inline_policies_count": 0,"name": "dams"}},"users_count": 1},"rds": {"filters": {},"findings": {"rds-instance-backup-disabled": {"checked_items": 0,"dashboard_name": "Instances","description": "Backup disabled","flagged_items": 0,"id_suffix": "BackupRetentionPeriod","items": [],"level": "danger","path": "rds.regions.id.vpcs.id.instances.id","rationale": "N/A","service": "RDS"},"rds-instance-no-minor-upgrade": {"checked_items": 0,"dashboard_name": "Instances","description": "Auto minor version upgrade disabled","flagged_items": 0,"id_suffix": "AutoMinorVersionUpgrade","items": [],"level": "danger","path": "rds.regions.id.vpcs.id.instances.id","rationale": "N/A","service": "RDS"},"rds-instance-short-backup-retention-period": {"checked_items": 0,"dashboard_name": "Instances","description": "Short backup retention period","flagged_items": 0,"id_suffix": "BackupRetentionPeriod","items": [],"level": "warning","path": "rds.regions.id.vpcs.id.instances.id","rationale": "N/A","service": "RDS"},"rds-instance-single-az": {"checked_items": 0,"dashboard_name": "Instances","description": "Single AZ RDS instance","flagged_items": 0,"id_suffix": "MultiAZ","items": [],"level": "danger","path": "rds.regions.id.vpcs.id.instances.id","rationale": "N/A","service": "RDS"},"rds-instance-storage-not-encrypted": {"checked_items": 0,"dashboard_name": "Instances","description": "Instance storage not encrypted","flagged_items": 0,"id_suffix": "StorageEncrypted","items": [],"level": "warning","path": "rds.regions.id.vpcs.id.instances.id","rationale": "N/A","service": "RDS"},"rds-security-group-allows-all": {"checked_items": 0,"dashboard_name": "Security Groups","description": "Security group allows all IP addresses","display_path": "rds.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "rds.regions.id.vpcs.id.security_groups.id.ip_ranges","rationale": "N/A","service": "RDS"},"rds-snapshot-public": {"checked_items": 0,"dashboard_name": "Snapshots","description": "Publicly accessible snapshot","display_path": "rds.regions.id.vpcs.id.snapshots.id","flagged_items": 0,"items": [],"level": "danger","path": "rds.regions.id.vpcs.id.snapshots.id.attributes.id","rationale": "N/A","service": "RDS"}},"instances_count": 0,"parameter_groups_count": 0,"regions": {"af-south-1": {"instances_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "af-south-1","security_groups": {},"security_groups_count": 0,"snapshots_count": 0,"subnet_groups_count": 0,"vpc_resource_types": ["instances","snapshots","subnet_groups"],"vpcs": {}},"ap-east-1": {"instances_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ap-east-1","security_groups": {},"security_groups_count": 0,"snapshots_count": 0,"subnet_groups_count": 0,"vpc_resource_types": ["instances","snapshots","subnet_groups"],"vpcs": {}},"ap-northeast-1": {"instances_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ap-northeast-1","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:ap-northeast-1:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpc_resource_types": ["instances","snapshots","subnet_groups"],"vpcs": {}},"ap-northeast-2": {"instances_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ap-northeast-2","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:ap-northeast-2:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpc_resource_types": ["instances","snapshots","subnet_groups"],"vpcs": {}},"ap-northeast-3": {"instances_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ap-northeast-3","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:ap-northeast-3:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpc_resource_types": ["instances","snapshots","subnet_groups"],"vpcs": {}},"ap-south-1": {"instances_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ap-south-1","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:ap-south-1:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpc_resource_types": ["instances","snapshots","subnet_groups"],"vpcs": {}},"ap-southeast-1": {"instances_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ap-southeast-1","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:ap-southeast-1:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpc_resource_types": ["instances","snapshots","subnet_groups"],"vpcs": {}},"ap-southeast-2": {"instances_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ap-southeast-2","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:ap-southeast-2:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpc_resource_types": ["instances","snapshots","subnet_groups"],"vpcs": {}},"ca-central-1": {"instances_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ca-central-1","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:ca-central-1:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpc_resource_types": ["instances","snapshots","subnet_groups"],"vpcs": {}},"eu-central-1": {"instances_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "eu-central-1","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:eu-central-1:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpc_resource_types": ["instances","snapshots","subnet_groups"],"vpcs": {}},"eu-north-1": {"instances_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "eu-north-1","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:eu-north-1:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpc_resource_types": ["instances","snapshots","subnet_groups"],"vpcs": {}},"eu-south-1": {"instances_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "eu-south-1","security_groups": {},"security_groups_count": 0,"snapshots_count": 0,"subnet_groups_count": 0,"vpc_resource_types": ["instances","snapshots","subnet_groups"],"vpcs": {}},"eu-west-1": {"instances_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "eu-west-1","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:eu-west-1:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpc_resource_types": ["instances","snapshots","subnet_groups"],"vpcs": {}},"eu-west-2": {"instances_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "eu-west-2","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:eu-west-2:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpc_resource_types": ["instances","snapshots","subnet_groups"],"vpcs": {}},"eu-west-3": {"instances_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "eu-west-3","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:eu-west-3:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpc_resource_types": ["instances","snapshots","subnet_groups"],"vpcs": {}},"me-south-1": {"instances_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "me-south-1","security_groups": {},"security_groups_count": 0,"snapshots_count": 0,"subnet_groups_count": 0,"vpc_resource_types": ["instances","snapshots","subnet_groups"],"vpcs": {}},"sa-east-1": {"instances_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "sa-east-1","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:sa-east-1:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpc_resource_types": ["instances","snapshots","subnet_groups"],"vpcs": {}},"us-east-1": {"instances_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "us-east-1","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:us-east-1:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpc_resource_types": ["instances","snapshots","subnet_groups"],"vpcs": {}},"us-east-2": {"instances_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "us-east-2","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:us-east-2:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpc_resource_types": ["instances","snapshots","subnet_groups"],"vpcs": {}},"us-west-1": {"instances_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "us-west-1","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:us-west-1:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpc_resource_types": ["instances","snapshots","subnet_groups"],"vpcs": {}},"us-west-2": {"instances_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "us-west-2","security_groups": {"default": {"DBSecurityGroupDescription": "default","EC2SecurityGroups": [],"IPRanges": [],"OwnerId": "430150006394","arn": "arn:aws:rds:us-west-2:430150006394:secgrp:default","name": "default"}},"security_groups_count": 1,"snapshots_count": 0,"subnet_groups_count": 0,"vpc_resource_types": ["instances","snapshots","subnet_groups"],"vpcs": {}}},"regions_count": 21,"resource_types": {"global": [],"region": ["security_groups","parameter_groups"],"vpc": ["instances","snapshots","subnet_groups"]},"security_groups_count": 17,"service": "rds","snapshots_count": 0,"subnet_groups_count": 0,"targets": {"first_region": [["instances","DBInstances","describe_db_instances",{},false],["security_groups","DBSecurityGroups","describe_db_security_groups",{},true],["snapshots","DBSnapshots","describe_db_snapshots",{},false],["parameter_groups","DBParameterGroups","describe_db_parameter_groups",{},false],["subnet_groups","DBSubnetGroups","describe_db_subnet_groups",{},false]],"other_regions": [["instances","DBInstances","describe_db_instances",{},false],["security_groups","DBSecurityGroups","describe_db_security_groups",{},true],["snapshots","DBSnapshots","describe_db_snapshots",{},false],["parameter_groups","DBParameterGroups","describe_db_parameter_groups",{},false],["subnet_groups","DBSubnetGroups","describe_db_subnet_groups",{},false]]},"thread_config": {"list": 10,"parse": 20}},"redshift": {"clusters_count": 0,"filters": {},"findings": {"redshift-cluster-database-not-encrypted": {"checked_items": 0,"dashboard_name": "Clusters","description": "Cluster database encryption disabled","flagged_items": 0,"id_suffix": "Encrypted","items": [],"level": "warning","path": "redshift.regions.id.vpcs.id.clusters.id","rationale": "N/A","service": "RedShift"},"redshift-cluster-no-version-upgrade": {"checked_items": 0,"dashboard_name": "Clusters","description": "Version upgrade disabled","flagged_items": 0,"id_suffix": "AllowVersionUpgrade","items": [],"level": "danger","path": "redshift.regions.id.vpcs.id.clusters.id","rationale": "N/A","service": "RedShift"},"redshift-cluster-publicly-accessible": {"checked_items": 0,"dashboard_name": "Clusters","description": "Cluster publicly accessible","flagged_items": 0,"id_suffix": "PubliclyAccessible","items": [],"level": "warning","path": "redshift.regions.id.vpcs.id.clusters.id","rationale": "N/A","service": "RedShift"},"redshift-parameter-group-logging-disabled": {"checked_items": 0,"dashboard_name": "Parameter Groups","description": "User activity logging disabled","flagged_items": 0,"id_suffix": "enable_user_activity_logging","items": [],"level": "warning","path": "redshift.regions.id.parameter_groups.id","rationale": "N/A","service": "RedShift"},"redshift-parameter-group-ssl-not-required": {"checked_items": 0,"dashboard_name": "Parameter Groups","description": "SSL not required","flagged_items": 0,"id_suffix": "require_ssl","items": [],"level": "danger","path": "redshift.regions.id.parameter_groups.id","rationale": "N/A","service": "RedShift"},"redshift-security-group-whitelists-all": {"checked_items": 0,"dashboard_name": "Security Groups","description": "Security group allows all","display_path": "redshift.regions.id.vpcs.id.security_groups.id","flagged_items": 0,"items": [],"level": "danger","path": "redshift.regions.id.vpcs.id.security_groups.id.IPRanges.id.CIDRIP","rationale": "N/A","service": "RedShift"}},"parameter_groups_count": 0,"regions": {"af-south-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "af-south-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters"],"vpcs": {}},"ap-east-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ap-east-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters"],"vpcs": {}},"ap-northeast-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ap-northeast-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters"],"vpcs": {}},"ap-northeast-2": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ap-northeast-2","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters"],"vpcs": {}},"ap-northeast-3": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ap-northeast-3","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters"],"vpcs": {}},"ap-south-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ap-south-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters"],"vpcs": {}},"ap-southeast-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ap-southeast-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters"],"vpcs": {}},"ap-southeast-2": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ap-southeast-2","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters"],"vpcs": {}},"ca-central-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "ca-central-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters"],"vpcs": {}},"eu-central-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "eu-central-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters"],"vpcs": {}},"eu-north-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "eu-north-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters"],"vpcs": {}},"eu-south-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "eu-south-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters"],"vpcs": {}},"eu-west-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "eu-west-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters"],"vpcs": {}},"eu-west-2": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "eu-west-2","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters"],"vpcs": {}},"eu-west-3": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "eu-west-3","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters"],"vpcs": {}},"me-south-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "me-south-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters"],"vpcs": {}},"sa-east-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "sa-east-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters"],"vpcs": {}},"us-east-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "us-east-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters"],"vpcs": {}},"us-east-2": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "us-east-2","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters"],"vpcs": {}},"us-west-1": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "us-west-1","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters"],"vpcs": {}},"us-west-2": {"clusters_count": 0,"parameter_groups": {},"parameter_groups_count": 0,"region": "us-west-2","security_groups": {},"security_groups_count": 0,"vpc_resource_types": ["clusters"],"vpcs": {}}},"regions_count": 21,"resource_types": {"global": [],"region": ["parameter_groups","security_groups"],"vpc": ["clusters"]},"security_groups_count": 0,"service": "redshift","targets": {"first_region": [["clusters","Clusters","describe_clusters",{},false],["parameter_groups","ParameterGroups","describe_cluster_parameter_groups",{},false],["security_groups","ClusterSecurityGroups","describe_cluster_security_groups",{},true]],"other_regions": [["clusters","Clusters","describe_clusters",{},false],["parameter_groups","ParameterGroups","describe_cluster_parameter_groups",{},false],["security_groups","ClusterSecurityGroups","describe_cluster_security_groups",{},true]]},"thread_config": {"list": 10,"parse": 20}},"route53": {"domains": {},"domains_count": 0,"filters": {},"findings": {"route53-domain-no-autorenew": {"checked_items": 0,"dashboard_name": "Domains","description": "Domain not set to autorenew","flagged_items": 0,"id_suffix": "AutoRenew","items": [],"level": "danger","path": "route53.domains.id","rationale": "N/A","service": "Route53"},"route53-domain-no-transferlock": {"checked_items": 0,"dashboard_name": "Domains","description": "Domain transfer not locked","flagged_items": 0,"id_suffix": "TransferLock","items": [],"level": "danger","path": "route53.domains.id","rationale": "N/A","service": "Route53"},"route53-domain-transferlock-not-authorized": {"checked_items": 0,"dashboard_name": "Domains","description": "Domain transfer lock not supported by TLD","flagged_items": 0,"id_suffix": "TransferLockNotAuthorized","items": [],"level": "danger","path": "route53.domains.id","rationale": "","service": "Route53"}},"hosted_zones": {},"hosted_zones_count": 0,"service": "route53domains","thread_config": {"list": 10,"parse": 20}},"s3": {"buckets": {},"buckets_count": 0,"filters": {"s3-bucket-website-enabled": {"checked_items": 0,"dashboard_name": "Buckets","description": "Bucket with static website enabled","flagged_items": 0,"id_suffix": "web_hosting","items": [],"level": "","path": "s3.buckets.id","rationale": "N/A","service": "S3"}},"findings": {"s3-bucket-AllUsers-read": {"checked_items": 0,"dashboard_name": "Bucket ACLs","description": "Bucket world-listable (anonymous)","display_path": "s3.buckets.id","flagged_items": 0,"id_suffix": "read","items": [],"level": "warning","path": "s3.buckets.id.grantees.id","rationale": "N/A","service": "S3"},"s3-bucket-AllUsers-read_acp": {"checked_items": 0,"dashboard_name": "Bucket ACLs","description": "Bucket's permissions world-readable (anonymous)","display_path": "s3.buckets.id","flagged_items": 0,"id_suffix": "read_acp","items": [],"level": "warning","path": "s3.buckets.id.grantees.id","rationale": "N/A","service": "S3"},"s3-bucket-AllUsers-write": {"checked_items": 0,"dashboard_name": "Bucket ACLs","description": "Bucket world-writable (anonymous)","display_path": "s3.buckets.id","flagged_items": 0,"id_suffix": "write","items": [],"level": "danger","path": "s3.buckets.id.grantees.id","rationale": "N/A","service": "S3"},"s3-bucket-AllUsers-write_acp": {"checked_items": 0,"dashboard_name": "Bucket ACLs","description": "Bucket's permissions world-writable (anonymous)","display_path": "s3.buckets.id","flagged_items": 0,"id_suffix": "write_acp","items": [],"level": "danger","path": "s3.buckets.id.grantees.id","rationale": "N/A","service": "S3"},"s3-bucket-AuthenticatedUsers-read": {"checked_items": 0,"dashboard_name": "Bucket ACLs","description": "Bucket world-listable","display_path": "s3.buckets.id","flagged_items": 0,"id_suffix": "read","items": [],"level": "danger","path": "s3.buckets.id.grantees.id","rationale": "N/A","service": "S3"},"s3-bucket-AuthenticatedUsers-read_acp": {"checked_items": 0,"dashboard_name": "Bucket ACLs","description": "Bucket's permissions world-readable","display_path": "s3.buckets.id","flagged_items": 0,"id_suffix": "read_acp","items": [],"level": "warning","path": "s3.buckets.id.grantees.id","rationale": "N/A","service": "S3"},"s3-bucket-AuthenticatedUsers-write": {"checked_items": 0,"dashboard_name": "Bucket ACLs","description": "Bucket world-writable","display_path": "s3.buckets.id","flagged_items": 0,"id_suffix": "write","items": [],"level": "danger","path": "s3.buckets.id.grantees.id","rationale": "N/A","service": "S3"},"s3-bucket-AuthenticatedUsers-write_acp": {"checked_items": 0,"dashboard_name": "Bucket ACLs","description": "Bucket's permissions world-writable","display_path": "s3.buckets.id","flagged_items": 0,"id_suffix": "write_acp","items": [],"level": "danger","path": "s3.buckets.id.grantees.id","rationale": "N/A","service": "S3"},"s3-bucket-allowing-cleartext": {"checked_items": 0,"dashboard_name": "Buckets","description": "Bucket allowing clear text (HTTP) communication","flagged_items": 0,"id_suffix": "secure_transport","items": [],"level": "warning","path": "s3.buckets.id","rationale": "If HTTPS is not enforced on the bucket policy, communication between clients and S3 buckets can use unencrypted HTTP. As a result, sensitive information could be transmitted in clear text over the network|Internet.","service": "S3"},"s3-bucket-no-default-encryption": {"checked_items": 0,"dashboard_name": "Buckets","description": "Bucket without default encryption enabled","flagged_items": 0,"id_suffix": "default_encryption","items": [],"level": "warning","path": "s3.buckets.id","rationale": "N/A","service": "S3"},"s3-bucket-no-logging": {"checked_items": 0,"dashboard_name": "Buckets","description": "Bucket access logging disabled","flagged_items": 0,"id_suffix": "logging","items": [],"level": "warning","path": "s3.buckets.id","rationale": "N/A","service": "S3"},"s3-bucket-no-mfa-delete": {"checked_items": 0,"dashboard_name": "Buckets","description": "Versioned bucket without MFA delete","flagged_items": 0,"id_suffix": "mfa_delete","items": [],"level": "warning","path": "s3.buckets.id","rationale": "N/A","service": "S3"},"s3-bucket-no-versioning": {"checked_items": 0,"dashboard_name": "Buckets","description": "Bucket without versioning","flagged_items": 0,"id_suffix": "versioning","items": [],"level": "warning","path": "s3.buckets.id","rationale": "N/A","service": "S3"},"s3-bucket-world-Delete-policy": {"checked_items": 0,"dashboard_name": "Buckets","description": "Delete actions authorized to all principals","display_path": "s3.buckets.id","flagged_items": 0,"items": [],"level": "danger","path": "s3.buckets.id.policy.Statement.id","rationale": "N/A","service": "S3"},"s3-bucket-world-Get-policy": {"checked_items": 0,"dashboard_name": "Buckets","description": "Get actions authorized to all principals","display_path": "s3.buckets.id","flagged_items": 0,"items": [],"level": "danger","path": "s3.buckets.id.policy.Statement.id","rationale": "N/A","service": "S3"},"s3-bucket-world-List-policy": {"checked_items": 0,"dashboard_name": "Buckets","description": "List actions authorized to all principals","display_path": "s3.buckets.id","flagged_items": 0,"items": [],"level": "danger","path": "s3.buckets.id.policy.Statement.id","rationale": "N/A","service": "S3"},"s3-bucket-world-Manage-policy": {"checked_items": 0,"dashboard_name": "Buckets","description": "Manage actions authorized to all principals","display_path": "s3.buckets.id","flagged_items": 0,"items": [],"level": "danger","path": "s3.buckets.id.policy.Statement.id","rationale": "N/A","service": "S3"},"s3-bucket-world-Put-policy": {"checked_items": 0,"dashboard_name": "Buckets","description": "Put actions authorized to all principals","display_path": "s3.buckets.id","flagged_items": 0,"items": [],"level": "danger","path": "s3.buckets.id.policy.Statement.id","rationale": "N/A","service": "S3"},"s3-bucket-world-policy-star": {"checked_items": 0,"dashboard_name": "Buckets","description": "All actions authorized to all principals","display_path": "s3.buckets.id","flagged_items": 0,"items": [],"level": "danger","path": "s3.buckets.id.policy.Statement.id","rationale": "N/A","service": "S3"}},"service": "s3","thread_config": {"list": 10,"parse": 20}},"ses": {"filters": {},"findings": {"ses-identity-world-SendEmail-policy": {"checked_items": 0,"dashboard_name": "Statements","description": "SendEmail authorized to all principals","display_path": "ses.regions.id.identities.id","flagged_items": 0,"items": [],"level": "danger","path": "ses.regions.id.identities.id.policies.id.Statement.id","rationale": "N/A","service": "SES"},"ses-identity-world-SendRawEmail-policy": {"checked_items": 0,"dashboard_name": "Statements","description": "SendRawEmail authorized to all principals","display_path": "ses.regions.id.identities.id","flagged_items": 0,"items": [],"level": "danger","path": "ses.regions.id.identities.id.policies.id.Statement.id","rationale": "N/A","service": "SES"}},"identities_count": 0,"regions": {"ap-south-1": {"identities": {},"identities_count": 0,"region": "ap-south-1"},"ap-southeast-2": {"identities": {},"identities_count": 0,"region": "ap-southeast-2"},"eu-central-1": {"identities": {},"identities_count": 0,"region": "eu-central-1"},"eu-west-1": {"identities": {},"identities_count": 0,"region": "eu-west-1"},"us-east-1": {"identities": {},"identities_count": 0,"region": "us-east-1"},"us-west-2": {"identities": {},"identities_count": 0,"region": "us-west-2"}},"regions_count": 6,"resource_types": {"global": [],"region": ["identities"],"vpc": []},"service": "ses","targets": {"first_region": [["identities","Identities","list_identities",{},false]],"other_regions": [["identities","Identities","list_identities",{},false]]},"thread_config": {"list": 10,"parse": 20}},"sns": {"filters": {},"findings": {"sns-topic-world-AddPermission-policy": {"checked_items": 0,"dashboard_name": "Statements","description": "AddPermission authorized to all principals","display_path": "sns.regions.id.topics.id","flagged_items": 0,"items": [],"level": "danger","path": "sns.regions.id.topics.id.Policy.Statement.id","rationale": "N/A","service": "SNS"},"sns-topic-world-DeleteTopic-policy": {"checked_items": 0,"dashboard_name": "Statements","description": "DeleteTopic authorized to all principals","display_path": "sns.regions.id.topics.id","flagged_items": 0,"items": [],"level": "danger","path": "sns.regions.id.topics.id.Policy.Statement.id","rationale": "N/A","service": "SNS"},"sns-topic-world-Publish-policy": {"checked_items": 0,"dashboard_name": "Statements","description": "Publish authorized to all principals","display_path": "sns.regions.id.topics.id","flagged_items": 0,"items": [],"level": "danger","path": "sns.regions.id.topics.id.Policy.Statement.id","rationale": "N/A","service": "SNS"},"sns-topic-world-Receive-policy": {"checked_items": 0,"dashboard_name": "Statements","description": "Receive authorized to all principals","display_path": "sns.regions.id.topics.id","flagged_items": 0,"items": [],"level": "danger","path": "sns.regions.id.topics.id.Policy.Statement.id","rationale": "N/A","service": "SNS"},"sns-topic-world-RemovePermission-policy": {"checked_items": 0,"dashboard_name": "Statements","description": "RemovePermission authorized to all principals","display_path": "sns.regions.id.topics.id","flagged_items": 0,"items": [],"level": "danger","path": "sns.regions.id.topics.id.Policy.Statement.id","rationale": "N/A","service": "SNS"},"sns-topic-world-SetTopicAttributes-policy": {"checked_items": 0,"dashboard_name": "Statements","description": "SetTopicAttributes authorized to all principals","display_path": "sns.regions.id.topics.id","flagged_items": 0,"items": [],"level": "danger","path": "sns.regions.id.topics.id.Policy.Statement.id","rationale": "N/A","service": "SNS"},"sns-topic-world-Subscribe-policy": {"checked_items": 0,"dashboard_name": "Statements","description": "Subscribe authorized to all principals","display_path": "sns.regions.id.topics.id","flagged_items": 0,"items": [],"level": "danger","path": "sns.regions.id.topics.id.Policy.Statement.id","rationale": "N/A","service": "SNS"}},"regions": {"af-south-1": {"region": "af-south-1","subscriptions": {},"subscriptions_count": 0,"topics": {},"topics_count": 0},"ap-east-1": {"region": "ap-east-1","subscriptions": {},"subscriptions_count": 0,"topics": {},"topics_count": 0},"ap-northeast-1": {"region": "ap-northeast-1","subscriptions": {},"subscriptions_count": 0,"topics": {},"topics_count": 0},"ap-northeast-2": {"region": "ap-northeast-2","subscriptions": {},"subscriptions_count": 0,"topics": {},"topics_count": 0},"ap-northeast-3": {"region": "ap-northeast-3","subscriptions": {},"subscriptions_count": 0,"topics": {},"topics_count": 0},"ap-south-1": {"region": "ap-south-1","subscriptions": {},"subscriptions_count": 0,"topics": {},"topics_count": 0},"ap-southeast-1": {"region": "ap-southeast-1","subscriptions": {},"subscriptions_count": 0,"topics": {},"topics_count": 0},"ap-southeast-2": {"region": "ap-southeast-2","subscriptions": {},"subscriptions_count": 0,"topics": {},"topics_count": 0},"ca-central-1": {"region": "ca-central-1","subscriptions": {},"subscriptions_count": 0,"topics": {},"topics_count": 0},"eu-central-1": {"region": "eu-central-1","subscriptions": {},"subscriptions_count": 0,"topics": {},"topics_count": 0},"eu-north-1": {"region": "eu-north-1","subscriptions": {},"subscriptions_count": 0,"topics": {},"topics_count": 0},"eu-south-1": {"region": "eu-south-1","subscriptions": {},"subscriptions_count": 0,"topics": {},"topics_count": 0},"eu-west-1": {"region": "eu-west-1","subscriptions": {},"subscriptions_count": 0,"topics": {},"topics_count": 0},"eu-west-2": {"region": "eu-west-2","subscriptions": {},"subscriptions_count": 0,"topics": {},"topics_count": 0},"eu-west-3": {"region": "eu-west-3","subscriptions": {},"subscriptions_count": 0,"topics": {},"topics_count": 0},"me-south-1": {"region": "me-south-1","subscriptions": {},"subscriptions_count": 0,"topics": {},"topics_count": 0},"sa-east-1": {"region": "sa-east-1","subscriptions": {},"subscriptions_count": 0,"topics": {},"topics_count": 0},"us-east-1": {"region": "us-east-1","subscriptions": {},"subscriptions_count": 0,"topics": {},"topics_count": 0},"us-east-2": {"region": "us-east-2","subscriptions": {},"subscriptions_count": 0,"topics": {},"topics_count": 0},"us-west-1": {"region": "us-west-1","subscriptions": {},"subscriptions_count": 0,"topics": {},"topics_count": 0},"us-west-2": {"region": "us-west-2","subscriptions": {},"subscriptions_count": 0,"topics": {},"topics_count": 0}},"regions_count": 21,"resource_types": {"global": [],"region": ["topics","subscriptions"],"vpc": []},"service": "sns","subscriptions_count": 0,"targets": {"first_region": [["topics","Topics","list_topics",{},false],["subscriptions","Subscriptions","list_subscriptions",{"NextToken": "AAGgHpese+bpGYiJlIAtfSFQ3wnBMec1+obBXagxEqgsVg=="},false]],"other_regions": [["topics","Topics","list_topics",{},false],["subscriptions","Subscriptions","list_subscriptions",{"NextToken": "AAGgHpese+bpGYiJlIAtfSFQ3wnBMec1+obBXagxEqgsVg=="},false]]},"thread_config": {"list": 10,"parse": 20},"topics_count": 0},"sqs": {"filters": {},"findings": {"sqs-queue-world-ChangeMessageVisibility-policy": {"checked_items": 0,"dashboard_name": "Statements","description": "ChangeMessageVisibility authorized to all principals","display_path": "sqs.regions.id.queues.id","flagged_items": 0,"items": [],"level": "danger","path": "sqs.regions.id.queues.id.Policy.Statement.id","rationale": "N/A","service": "SQS"},"sqs-queue-world-DeleteMessage-policy": {"checked_items": 0,"dashboard_name": "Statements","description": "DeleteMessage authorized to all principals","display_path": "sqs.regions.id.queues.id","flagged_items": 0,"items": [],"level": "danger","path": "sqs.regions.id.queues.id.Policy.Statement.id","rationale": "N/A","service": "SQS"},"sqs-queue-world-GetQueueAttributes-policy": {"checked_items": 0,"dashboard_name": "Statements","description": "GetQueueAttributes authorized to all principals","display_path": "sqs.regions.id.queues.id","flagged_items": 0,"items": [],"level": "warning","path": "sqs.regions.id.queues.id.Policy.Statement.id","rationale": "N/A","service": "SQS"},"sqs-queue-world-GetQueueUrl-policy": {"checked_items": 0,"dashboard_name": "Statements","description": "GetQueueUrl authorized to all principals","display_path": "sqs.regions.id.queues.id","flagged_items": 0,"items": [],"level": "warning","path": "sqs.regions.id.queues.id.Policy.Statement.id","rationale": "N/A","service": "SQS"},"sqs-queue-world-PurgeQueue-policy": {"checked_items": 0,"dashboard_name": "Statements","description": "PurgeQueue authorized to all principals","display_path": "sqs.regions.id.queues.id","flagged_items": 0,"items": [],"level": "danger","path": "sqs.regions.id.queues.id.Policy.Statement.id","rationale": "N/A","service": "SQS"},"sqs-queue-world-ReceiveMessage-policy": {"checked_items": 0,"dashboard_name": "Statements","description": "ReceiveMessage authorized to all principals","display_path": "sqs.regions.id.queues.id","flagged_items": 0,"items": [],"level": "danger","path": "sqs.regions.id.queues.id.Policy.Statement.id","rationale": "N/A","service": "SQS"},"sqs-queue-world-SendMessage-policy": {"checked_items": 0,"dashboard_name": "Statements","description": "SendMessage authorized to all principals","display_path": "sqs.regions.id.queues.id","flagged_items": 0,"items": [],"level": "danger","path": "sqs.regions.id.queues.id.Policy.Statement.id","rationale": "N/A","service": "SQS"}},"queues_count": 0,"regions": {"af-south-1": {"queues": {},"queues_count": 0,"region": "af-south-1"},"ap-east-1": {"queues": {},"queues_count": 0,"region": "ap-east-1"},"ap-northeast-1": {"queues": {},"queues_count": 0,"region": "ap-northeast-1"},"ap-northeast-2": {"queues": {},"queues_count": 0,"region": "ap-northeast-2"},"ap-northeast-3": {"queues": {},"queues_count": 0,"region": "ap-northeast-3"},"ap-south-1": {"queues": {},"queues_count": 0,"region": "ap-south-1"},"ap-southeast-1": {"queues": {},"queues_count": 0,"region": "ap-southeast-1"},"ap-southeast-2": {"queues": {},"queues_count": 0,"region": "ap-southeast-2"},"ca-central-1": {"queues": {},"queues_count": 0,"region": "ca-central-1"},"eu-central-1": {"queues": {},"queues_count": 0,"region": "eu-central-1"},"eu-north-1": {"queues": {},"queues_count": 0,"region": "eu-north-1"},"eu-south-1": {"queues": {},"queues_count": 0,"region": "eu-south-1"},"eu-west-1": {"queues": {},"queues_count": 0,"region": "eu-west-1"},"eu-west-2": {"queues": {},"queues_count": 0,"region": "eu-west-2"},"eu-west-3": {"queues": {},"queues_count": 0,"region": "eu-west-3"},"me-south-1": {"queues": {},"queues_count": 0,"region": "me-south-1"},"sa-east-1": {"queues": {},"queues_count": 0,"region": "sa-east-1"},"us-east-1": {"queues": {},"queues_count": 0,"region": "us-east-1"},"us-east-2": {"queues": {},"queues_count": 0,"region": "us-east-2"},"us-west-1": {"queues": {},"queues_count": 0,"region": "us-west-1"},"us-west-2": {"queues": {},"queues_count": 0,"region": "us-west-2"}},"regions_count": 21,"resource_types": {"global": [],"region": ["queues"],"vpc": []},"service": "sqs","targets": {"first_region": [["queues","QueueUrls","list_queues",{},false]],"other_regions": [["queues","QueueUrls","list_queues",{},false]]},"thread_config": {"list": 10,"parse": 20}},"vpc": {"customer_gateways_count": 0,"filters": {},"findings": {"vpc-custom-network-acls-allow-all-egress": {"checked_items": 17,"dashboard_name": "Network ACLs","description": "Network ACLs allow all egress traffic (custom)","flagged_items": 0,"id_suffix": "egress._GET_VALUE_AT_(vpc.regions.id.vpcs.id.network_acls.id.allow_all_egress_traffic)","items": [],"level": "warning","path": "vpc.regions.id.vpcs.id.network_acls.id","rationale": "Network ACLs are designed to provide a secondary layer of security. Adding a rule that allows all network traffic (all protocols, IPs, and destination) prior to any deny rule defeats the purpose of network ACLs.","service": "VPC"},"vpc-custom-network-acls-allow-all-ingress": {"checked_items": 17,"dashboard_name": "Network ACLs","description": "Network ACLs allow all ingress traffic (custom)","flagged_items": 0,"id_suffix": "ingress._GET_VALUE_AT_(vpc.regions.id.vpcs.id.network_acls.id.allow_all_ingress_traffic)","items": [],"level": "warning","path": "vpc.regions.id.vpcs.id.network_acls.id","rationale": "Network ACLs are designed to provide a secondary layer of security. Adding a rule that allows all network traffic (all protocols, IPs, and source) prior to any deny rule defeats the purpose of network ACLs.","service": "VPC"},"vpc-default-network-acls-allow-all-egress": {"checked_items": 17,"dashboard_name": "Network ACLs","description": "Network ACLs allow all egress traffic (default)","flagged_items": 17,"id_suffix": "egress._GET_VALUE_AT_(vpc.regions.id.vpcs.id.network_acls.id.allow_all_egress_traffic)","items": ["vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.network_acls.acl-c777e5a1.egress.100","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.network_acls.acl-75e1951e.egress.100","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.network_acls.acl-bb1b62d2.egress.100","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.network_acls.acl-a676adcd.egress.100","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.network_acls.acl-8787e0e1.egress.100","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.network_acls.acl-4e4dc228.egress.100","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.network_acls.acl-63e1ed0b.egress.100","vpc.regions.eu-central-1.vpcs.vpc-78b43312.network_acls.acl-6ebcec04.egress.100","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.network_acls.acl-dfb10ab6.egress.100","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.network_acls.acl-ed4be494.egress.100","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.network_acls.acl-003d0768.egress.100","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.network_acls.acl-c74e7dae.egress.100","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.network_acls.acl-43816e25.egress.100","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.network_acls.acl-f1a6ae8c.egress.100","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.network_acls.acl-b06507db.egress.100","vpc.regions.us-west-1.vpcs.vpc-6e6fa508.network_acls.acl-14a0c772.egress.100","vpc.regions.us-west-2.vpcs.vpc-d45709ac.network_acls.acl-f76adc8c.egress.100"],"level": "warning","path": "vpc.regions.id.vpcs.id.network_acls.id","rationale": "Network ACLs are designed to provide a secondary layer of security. Adding a rule that allows all network traffic (all protocols, IPs, and destination) prior to any deny rule defeats the purpose of network ACLs.","service": "VPC"},"vpc-default-network-acls-allow-all-ingress": {"checked_items": 17,"dashboard_name": "Network ACLs","description": "Network ACLs allow all ingress traffic (default)","flagged_items": 17,"id_suffix": "ingress._GET_VALUE_AT_(vpc.regions.id.vpcs.id.network_acls.id.allow_all_ingress_traffic)","items": ["vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.network_acls.acl-c777e5a1.ingress.100","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.network_acls.acl-75e1951e.ingress.100","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.network_acls.acl-bb1b62d2.ingress.100","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.network_acls.acl-a676adcd.ingress.100","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.network_acls.acl-8787e0e1.ingress.100","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.network_acls.acl-4e4dc228.ingress.100","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.network_acls.acl-63e1ed0b.ingress.100","vpc.regions.eu-central-1.vpcs.vpc-78b43312.network_acls.acl-6ebcec04.ingress.100","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.network_acls.acl-dfb10ab6.ingress.100","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.network_acls.acl-ed4be494.ingress.100","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.network_acls.acl-003d0768.ingress.100","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.network_acls.acl-c74e7dae.ingress.100","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.network_acls.acl-43816e25.ingress.100","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.network_acls.acl-f1a6ae8c.ingress.100","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.network_acls.acl-b06507db.ingress.100","vpc.regions.us-west-1.vpcs.vpc-6e6fa508.network_acls.acl-14a0c772.ingress.100","vpc.regions.us-west-2.vpcs.vpc-d45709ac.network_acls.acl-f76adc8c.ingress.100"],"level": "warning","path": "vpc.regions.id.vpcs.id.network_acls.id","rationale": "Network ACLs are designed to provide a secondary layer of security. Adding a rule that allows all network traffic (all protocols, IPs, and source) prior to any deny rule defeats the purpose of network ACLs.","service": "VPC"},"vpc-network-acl-not-used": {"checked_items": 17,"dashboard_name": "Network ACLs","description": "Unused network ACLs","flagged_items": 0,"id_suffix": "unused","items": [],"level": "warning","path": "vpc.regions.id.vpcs.id.network_acls.id","rationale": "Maintaining unused resources increases risks of misconfigurations and increases the difficulty of audits.","service": "VPC"},"vpc-subnet-with-allow-all-egress-acls": {"checked_items": 55,"dashboard_name": "Subnets","description": "Subnet with allow all egress NACLs","flagged_items": 55,"id_suffix": "bad_nacls","items": ["vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-7f50e154.bad_nacls","vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-a668c6ee.bad_nacls","vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-593d2502.bad_nacls","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-e6ad198d.bad_nacls","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-af6809d4.bad_nacls","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-8447addb.bad_nacls","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-cf001883.bad_nacls","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-4dcc0924.bad_nacls","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-546a8e2f.bad_nacls","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-c1b6118c.bad_nacls","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-f0fde498.bad_nacls","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-d3c151a8.bad_nacls","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-7d5a1431.bad_nacls","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-2506d06d.bad_nacls","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-a448d5fd.bad_nacls","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-b73197d1.bad_nacls","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-b3fe86eb.bad_nacls","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-0c0bc26a.bad_nacls","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-6cb44e24.bad_nacls","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-1cd98b74.bad_nacls","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-4f896210.bad_nacls","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-85711fff.bad_nacls","vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-ecc66390.bad_nacls","vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-55d77f19.bad_nacls","vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-292d4343.bad_nacls","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-1d972e74.bad_nacls","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-fe16ce85.bad_nacls","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-c98e7484.bad_nacls","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-b3a000e9.bad_nacls","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-b1c2a5d7.bad_nacls","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-214f3969.bad_nacls","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-edaf13a1.bad_nacls","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-e682ec9c.bad_nacls","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-43bf9d2a.bad_nacls","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-b309b8fe.bad_nacls","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-762a450d.bad_nacls","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-e9e1b480.bad_nacls","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-6a4dd723.bad_nacls","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-9aa5c1fc.bad_nacls","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-aaddbef1.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-6e61f24f.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-8c27ffbd.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-30be2f6f.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-77e07411.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-cbefcb86.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-7056187e.bad_nacls","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-fac76891.bad_nacls","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-81a1eccd.bad_nacls","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-18e60365.bad_nacls","vpc.regions.us-west-1.vpcs.vpc-6e6fa508.subnets.subnet-3162b36b.bad_nacls","vpc.regions.us-west-1.vpcs.vpc-6e6fa508.subnets.subnet-64f07402.bad_nacls","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-64dae84f.bad_nacls","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-113ce95b.bad_nacls","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-25f65d5d.bad_nacls","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-1075cf4d.bad_nacls"],"level": "warning","path": "vpc.regions.id.vpcs.id.subnets.id","rationale": "Network ACLs associated with subnets and VPCs should not allow all egress traffic.","service": "VPC"},"vpc-subnet-with-allow-all-ingress-acls": {"checked_items": 55,"dashboard_name": "Subnets","description": "Subnet with allow all ingress NACLs","flagged_items": 55,"id_suffix": "bad_nacls","items": ["vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-7f50e154.bad_nacls","vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-a668c6ee.bad_nacls","vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-593d2502.bad_nacls","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-e6ad198d.bad_nacls","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-af6809d4.bad_nacls","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-8447addb.bad_nacls","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-cf001883.bad_nacls","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-4dcc0924.bad_nacls","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-546a8e2f.bad_nacls","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-c1b6118c.bad_nacls","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-f0fde498.bad_nacls","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-d3c151a8.bad_nacls","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-7d5a1431.bad_nacls","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-2506d06d.bad_nacls","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-a448d5fd.bad_nacls","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-b73197d1.bad_nacls","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-b3fe86eb.bad_nacls","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-0c0bc26a.bad_nacls","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-6cb44e24.bad_nacls","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-1cd98b74.bad_nacls","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-4f896210.bad_nacls","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-85711fff.bad_nacls","vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-ecc66390.bad_nacls","vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-55d77f19.bad_nacls","vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-292d4343.bad_nacls","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-1d972e74.bad_nacls","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-fe16ce85.bad_nacls","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-c98e7484.bad_nacls","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-b3a000e9.bad_nacls","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-b1c2a5d7.bad_nacls","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-214f3969.bad_nacls","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-edaf13a1.bad_nacls","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-e682ec9c.bad_nacls","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-43bf9d2a.bad_nacls","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-b309b8fe.bad_nacls","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-762a450d.bad_nacls","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-e9e1b480.bad_nacls","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-6a4dd723.bad_nacls","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-9aa5c1fc.bad_nacls","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-aaddbef1.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-6e61f24f.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-8c27ffbd.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-30be2f6f.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-77e07411.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-cbefcb86.bad_nacls","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-7056187e.bad_nacls","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-fac76891.bad_nacls","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-81a1eccd.bad_nacls","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-18e60365.bad_nacls","vpc.regions.us-west-1.vpcs.vpc-6e6fa508.subnets.subnet-3162b36b.bad_nacls","vpc.regions.us-west-1.vpcs.vpc-6e6fa508.subnets.subnet-64f07402.bad_nacls","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-64dae84f.bad_nacls","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-113ce95b.bad_nacls","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-25f65d5d.bad_nacls","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-1075cf4d.bad_nacls"],"level": "warning","path": "vpc.regions.id.vpcs.id.subnets.id","rationale": "Network ACLs associated with subnets and VPCs should not allow all ingress traffic.","service": "VPC"},"vpc-subnet-without-flow-log": {"checked_items": 55,"dashboard_name": "Subnets","description": "Subnet without a flow log","flagged_items": 55,"id_suffix": "NoFlowLog","items": ["vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-7f50e154.NoFlowLog","vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-a668c6ee.NoFlowLog","vpc.regions.ap-northeast-1.vpcs.vpc-0cbc506a.subnets.subnet-593d2502.NoFlowLog","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-e6ad198d.NoFlowLog","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-af6809d4.NoFlowLog","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-8447addb.NoFlowLog","vpc.regions.ap-northeast-2.vpcs.vpc-73f44e18.subnets.subnet-cf001883.NoFlowLog","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-4dcc0924.NoFlowLog","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-546a8e2f.NoFlowLog","vpc.regions.ap-northeast-3.vpcs.vpc-47b7dd2e.subnets.subnet-c1b6118c.NoFlowLog","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-f0fde498.NoFlowLog","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-d3c151a8.NoFlowLog","vpc.regions.ap-south-1.vpcs.vpc-2651a14d.subnets.subnet-7d5a1431.NoFlowLog","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-2506d06d.NoFlowLog","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-a448d5fd.NoFlowLog","vpc.regions.ap-southeast-1.vpcs.vpc-04ed1062.subnets.subnet-b73197d1.NoFlowLog","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-b3fe86eb.NoFlowLog","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-0c0bc26a.NoFlowLog","vpc.regions.ap-southeast-2.vpcs.vpc-5d22c33b.subnets.subnet-6cb44e24.NoFlowLog","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-1cd98b74.NoFlowLog","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-4f896210.NoFlowLog","vpc.regions.ca-central-1.vpcs.vpc-b5113ddd.subnets.subnet-85711fff.NoFlowLog","vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-ecc66390.NoFlowLog","vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-55d77f19.NoFlowLog","vpc.regions.eu-central-1.vpcs.vpc-78b43312.subnets.subnet-292d4343.NoFlowLog","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-1d972e74.NoFlowLog","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-fe16ce85.NoFlowLog","vpc.regions.eu-north-1.vpcs.vpc-fa259d93.subnets.subnet-c98e7484.NoFlowLog","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-b3a000e9.NoFlowLog","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-b1c2a5d7.NoFlowLog","vpc.regions.eu-west-1.vpcs.vpc-f24c7994.subnets.subnet-214f3969.NoFlowLog","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-edaf13a1.NoFlowLog","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-e682ec9c.NoFlowLog","vpc.regions.eu-west-2.vpcs.vpc-3fa2fa57.subnets.subnet-43bf9d2a.NoFlowLog","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-b309b8fe.NoFlowLog","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-762a450d.NoFlowLog","vpc.regions.eu-west-3.vpcs.vpc-87d3fdee.subnets.subnet-e9e1b480.NoFlowLog","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-6a4dd723.NoFlowLog","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-9aa5c1fc.NoFlowLog","vpc.regions.sa-east-1.vpcs.vpc-b14fa4d7.subnets.subnet-aaddbef1.NoFlowLog","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-6e61f24f.NoFlowLog","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-8c27ffbd.NoFlowLog","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-30be2f6f.NoFlowLog","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-77e07411.NoFlowLog","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-cbefcb86.NoFlowLog","vpc.regions.us-east-1.vpcs.vpc-ba1cbdc7.subnets.subnet-7056187e.NoFlowLog","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-fac76891.NoFlowLog","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-81a1eccd.NoFlowLog","vpc.regions.us-east-2.vpcs.vpc-e429ad8f.subnets.subnet-18e60365.NoFlowLog","vpc.regions.us-west-1.vpcs.vpc-6e6fa508.subnets.subnet-3162b36b.NoFlowLog","vpc.regions.us-west-1.vpcs.vpc-6e6fa508.subnets.subnet-64f07402.NoFlowLog","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-64dae84f.NoFlowLog","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-113ce95b.NoFlowLog","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-25f65d5d.NoFlowLog","vpc.regions.us-west-2.vpcs.vpc-d45709ac.subnets.subnet-1075cf4d.NoFlowLog"],"level": "warning","path": "vpc.regions.id.vpcs.id.subnets.id","rationale": "Flow logs enable the investigatation of incidents involving unauthorized network traffic, such as an attacker exfiltrating data or pivoting to other hosts.","service": "VPC"}},"flow_logs_count": 0,"network_acls_count": 17,"peering_connections_count": 0,"regions": {"af-south-1": {"customer_gateways": {},"customer_gateways_count": 0,"flow_logs": {},"flow_logs_count": 0,"network_acls_count": 0,"peering_connections": {},"peering_connections_count": 0,"region": "af-south-1","route_tables_count": 0,"subnets_count": 0,"vpc_resource_types": ["network_acls","subnets","route_tables"],"vpcs": {},"vpcs_count": 0,"vpn_connections": {},"vpn_connections_count": 0,"vpn_gateways": {},"vpn_gateways_count": 0},"ap-east-1": {"customer_gateways": {},"customer_gateways_count": 0,"flow_logs": {},"flow_logs_count": 0,"network_acls_count": 0,"peering_connections": {},"peering_connections_count": 0,"region": "ap-east-1","route_tables_count": 0,"subnets_count": 0,"vpc_resource_types": ["network_acls","subnets","route_tables"],"vpcs": {},"vpcs_count": 0,"vpn_connections": {},"vpn_connections_count": 0,"vpn_gateways": {},"vpn_gateways_count": 0},"ap-northeast-1": {"customer_gateways": {},"customer_gateways_count": 0,"flow_logs": {},"flow_logs_count": 0,"network_acls_count": 1,"peering_connections": {},"peering_connections_count": 0,"region": "ap-northeast-1","route_tables_count": 1,"subnets_count": 3,"vpc_resource_types": ["network_acls","subnets","route_tables"],"vpcs": {"vpc-0cbc506a": {"name": "vpc-0cbc506a","network_acls": {"acl-c777e5a1": {"Associations": [{"NetworkAclAssociationId": "aclassoc-31486e40","NetworkAclId": "acl-c777e5a1","SubnetId": "subnet-a668c6ee"},{"NetworkAclAssociationId": "aclassoc-4e486e3f","NetworkAclId": "acl-c777e5a1","SubnetId": "subnet-7f50e154"},{"NetworkAclAssociationId": "aclassoc-4f486e3e","NetworkAclId": "acl-c777e5a1","SubnetId": "subnet-593d2502"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-0cbc506a","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-c777e5a1","name": "acl-c777e5a1","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"route_tables": {"rtb-a3490cc5": {"Associations": [{"AssociationState": {"State": "associated"},"Main": true,"RouteTableAssociationId": "rtbassoc-0389c27a","RouteTableId": "rtb-a3490cc5"}],"PropagatingVgws": [],"Routes": [{"DestinationCidrBlock": "172.31.0.0/16","GatewayId": "local","Origin": "CreateRouteTable","State": "active"},{"DestinationCidrBlock": "0.0.0.0/0","GatewayId": "igw-c330d8a4","Origin": "CreateRoute","State": "active"}],"name": "vpc-0cbc506a"}},"subnets": {"subnet-593d2502": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-northeast-1c","AvailabilityZoneId": "apne1-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-northeast-1:430150006394:subnet/subnet-593d2502","SubnetId": "subnet-593d2502","VpcId": "vpc-0cbc506a","flow_logs": [],"name": "subnet-593d2502","network_acl": "acl-c777e5a1"},"subnet-7f50e154": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-northeast-1d","AvailabilityZoneId": "apne1-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-northeast-1:430150006394:subnet/subnet-7f50e154","SubnetId": "subnet-7f50e154","VpcId": "vpc-0cbc506a","flow_logs": [],"name": "subnet-7f50e154","network_acl": "acl-c777e5a1"},"subnet-a668c6ee": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-northeast-1a","AvailabilityZoneId": "apne1-az4","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-northeast-1:430150006394:subnet/subnet-a668c6ee","SubnetId": "subnet-a668c6ee","VpcId": "vpc-0cbc506a","flow_logs": [],"name": "subnet-a668c6ee","network_acl": "acl-c777e5a1"}}}},"vpcs_count": 1,"vpn_connections": {},"vpn_connections_count": 0,"vpn_gateways": {},"vpn_gateways_count": 0},"ap-northeast-2": {"customer_gateways": {},"customer_gateways_count": 0,"flow_logs": {},"flow_logs_count": 0,"network_acls_count": 1,"peering_connections": {},"peering_connections_count": 0,"region": "ap-northeast-2","route_tables_count": 1,"subnets_count": 4,"vpc_resource_types": ["network_acls","subnets","route_tables"],"vpcs": {"vpc-73f44e18": {"name": "vpc-73f44e18","network_acls": {"acl-75e1951e": {"Associations": [{"NetworkAclAssociationId": "aclassoc-37937854","NetworkAclId": "acl-75e1951e","SubnetId": "subnet-e6ad198d"},{"NetworkAclAssociationId": "aclassoc-35937856","NetworkAclId": "acl-75e1951e","SubnetId": "subnet-cf001883"},{"NetworkAclAssociationId": "aclassoc-36937855","NetworkAclId": "acl-75e1951e","SubnetId": "subnet-af6809d4"},{"NetworkAclAssociationId": "aclassoc-34937857","NetworkAclId": "acl-75e1951e","SubnetId": "subnet-8447addb"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-73f44e18","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-75e1951e","name": "acl-75e1951e","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"route_tables": {"rtb-80d292eb": {"Associations": [{"AssociationState": {"State": "associated"},"Main": true,"RouteTableAssociationId": "rtbassoc-c9e06ea3","RouteTableId": "rtb-80d292eb"}],"PropagatingVgws": [],"Routes": [{"DestinationCidrBlock": "172.31.0.0/16","GatewayId": "local","Origin": "CreateRouteTable","State": "active"},{"DestinationCidrBlock": "0.0.0.0/0","GatewayId": "igw-053d546d","Origin": "CreateRoute","State": "active"}],"name": "vpc-73f44e18"}},"subnets": {"subnet-8447addb": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-northeast-2d","AvailabilityZoneId": "apne2-az4","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.48.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-northeast-2:430150006394:subnet/subnet-8447addb","SubnetId": "subnet-8447addb","VpcId": "vpc-73f44e18","flow_logs": [],"name": "subnet-8447addb","network_acl": "acl-75e1951e"},"subnet-af6809d4": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-northeast-2b","AvailabilityZoneId": "apne2-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-northeast-2:430150006394:subnet/subnet-af6809d4","SubnetId": "subnet-af6809d4","VpcId": "vpc-73f44e18","flow_logs": [],"name": "subnet-af6809d4","network_acl": "acl-75e1951e"},"subnet-cf001883": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-northeast-2c","AvailabilityZoneId": "apne2-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-northeast-2:430150006394:subnet/subnet-cf001883","SubnetId": "subnet-cf001883","VpcId": "vpc-73f44e18","flow_logs": [],"name": "subnet-cf001883","network_acl": "acl-75e1951e"},"subnet-e6ad198d": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-northeast-2a","AvailabilityZoneId": "apne2-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-northeast-2:430150006394:subnet/subnet-e6ad198d","SubnetId": "subnet-e6ad198d","VpcId": "vpc-73f44e18","flow_logs": [],"name": "subnet-e6ad198d","network_acl": "acl-75e1951e"}}}},"vpcs_count": 1,"vpn_connections": {},"vpn_connections_count": 0,"vpn_gateways": {},"vpn_gateways_count": 0},"ap-northeast-3": {"customer_gateways": {},"customer_gateways_count": 0,"flow_logs": {},"flow_logs_count": 0,"network_acls_count": 1,"peering_connections": {},"peering_connections_count": 0,"region": "ap-northeast-3","route_tables_count": 1,"subnets_count": 3,"vpc_resource_types": ["network_acls","subnets","route_tables"],"vpcs": {"vpc-47b7dd2e": {"name": "vpc-47b7dd2e","network_acls": {"acl-bb1b62d2": {"Associations": [{"NetworkAclAssociationId": "aclassoc-1953e271","NetworkAclId": "acl-bb1b62d2","SubnetId": "subnet-c1b6118c"},{"NetworkAclAssociationId": "aclassoc-1853e270","NetworkAclId": "acl-bb1b62d2","SubnetId": "subnet-4dcc0924"},{"NetworkAclAssociationId": "aclassoc-0753e26f","NetworkAclId": "acl-bb1b62d2","SubnetId": "subnet-546a8e2f"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-47b7dd2e","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-bb1b62d2","name": "acl-bb1b62d2","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"route_tables": {"rtb-18286671": {"Associations": [{"AssociationState": {"State": "associated"},"Main": true,"RouteTableAssociationId": "rtbassoc-85fd86ec","RouteTableId": "rtb-18286671"}],"PropagatingVgws": [],"Routes": [{"DestinationCidrBlock": "172.31.0.0/16","GatewayId": "local","Origin": "CreateRouteTable","State": "active"},{"DestinationCidrBlock": "0.0.0.0/0","GatewayId": "igw-334bca5a","Origin": "CreateRoute","State": "active"}],"name": "vpc-47b7dd2e"}},"subnets": {"subnet-4dcc0924": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-northeast-3b","AvailabilityZoneId": "apne3-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-northeast-3:430150006394:subnet/subnet-4dcc0924","SubnetId": "subnet-4dcc0924","VpcId": "vpc-47b7dd2e","flow_logs": [],"name": "subnet-4dcc0924","network_acl": "acl-bb1b62d2"},"subnet-546a8e2f": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-northeast-3c","AvailabilityZoneId": "apne3-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-northeast-3:430150006394:subnet/subnet-546a8e2f","SubnetId": "subnet-546a8e2f","VpcId": "vpc-47b7dd2e","flow_logs": [],"name": "subnet-546a8e2f","network_acl": "acl-bb1b62d2"},"subnet-c1b6118c": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-northeast-3a","AvailabilityZoneId": "apne3-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-northeast-3:430150006394:subnet/subnet-c1b6118c","SubnetId": "subnet-c1b6118c","VpcId": "vpc-47b7dd2e","flow_logs": [],"name": "subnet-c1b6118c","network_acl": "acl-bb1b62d2"}}}},"vpcs_count": 1,"vpn_connections": {},"vpn_connections_count": 0,"vpn_gateways": {},"vpn_gateways_count": 0},"ap-south-1": {"customer_gateways": {},"customer_gateways_count": 0,"flow_logs": {},"flow_logs_count": 0,"network_acls_count": 1,"peering_connections": {},"peering_connections_count": 0,"region": "ap-south-1","route_tables_count": 1,"subnets_count": 3,"vpc_resource_types": ["network_acls","subnets","route_tables"],"vpcs": {"vpc-2651a14d": {"name": "vpc-2651a14d","network_acls": {"acl-a676adcd": {"Associations": [{"NetworkAclAssociationId": "aclassoc-c9d2b0a8","NetworkAclId": "acl-a676adcd","SubnetId": "subnet-d3c151a8"},{"NetworkAclAssociationId": "aclassoc-c6d2b0a7","NetworkAclId": "acl-a676adcd","SubnetId": "subnet-7d5a1431"},{"NetworkAclAssociationId": "aclassoc-c8d2b0a9","NetworkAclId": "acl-a676adcd","SubnetId": "subnet-f0fde498"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-2651a14d","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-a676adcd","name": "acl-a676adcd","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"route_tables": {"rtb-f3d26398": {"Associations": [{"AssociationState": {"State": "associated"},"Main": true,"RouteTableAssociationId": "rtbassoc-645c5d0f","RouteTableId": "rtb-f3d26398"}],"PropagatingVgws": [],"Routes": [{"DestinationCidrBlock": "172.31.0.0/16","GatewayId": "local","Origin": "CreateRouteTable","State": "active"},{"DestinationCidrBlock": "0.0.0.0/0","GatewayId": "igw-c8ee63a0","Origin": "CreateRoute","State": "active"}],"name": "vpc-2651a14d"}},"subnets": {"subnet-7d5a1431": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-south-1b","AvailabilityZoneId": "aps1-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-south-1:430150006394:subnet/subnet-7d5a1431","SubnetId": "subnet-7d5a1431","VpcId": "vpc-2651a14d","flow_logs": [],"name": "subnet-7d5a1431","network_acl": "acl-a676adcd"},"subnet-d3c151a8": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-south-1c","AvailabilityZoneId": "aps1-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-south-1:430150006394:subnet/subnet-d3c151a8","SubnetId": "subnet-d3c151a8","VpcId": "vpc-2651a14d","flow_logs": [],"name": "subnet-d3c151a8","network_acl": "acl-a676adcd"},"subnet-f0fde498": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-south-1a","AvailabilityZoneId": "aps1-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-south-1:430150006394:subnet/subnet-f0fde498","SubnetId": "subnet-f0fde498","VpcId": "vpc-2651a14d","flow_logs": [],"name": "subnet-f0fde498","network_acl": "acl-a676adcd"}}}},"vpcs_count": 1,"vpn_connections": {},"vpn_connections_count": 0,"vpn_gateways": {},"vpn_gateways_count": 0},"ap-southeast-1": {"customer_gateways": {},"customer_gateways_count": 0,"flow_logs": {},"flow_logs_count": 0,"network_acls_count": 1,"peering_connections": {},"peering_connections_count": 0,"region": "ap-southeast-1","route_tables_count": 1,"subnets_count": 3,"vpc_resource_types": ["network_acls","subnets","route_tables"],"vpcs": {"vpc-04ed1062": {"name": "vpc-04ed1062","network_acls": {"acl-8787e0e1": {"Associations": [{"NetworkAclAssociationId": "aclassoc-a6b2e6d8","NetworkAclId": "acl-8787e0e1","SubnetId": "subnet-2506d06d"},{"NetworkAclAssociationId": "aclassoc-a8b2e6d6","NetworkAclId": "acl-8787e0e1","SubnetId": "subnet-a448d5fd"},{"NetworkAclAssociationId": "aclassoc-a9b2e6d7","NetworkAclId": "acl-8787e0e1","SubnetId": "subnet-b73197d1"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-04ed1062","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-8787e0e1","name": "acl-8787e0e1","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"route_tables": {"rtb-cd6d2cab": {"Associations": [{"AssociationState": {"State": "associated"},"Main": true,"RouteTableAssociationId": "rtbassoc-35394a4c","RouteTableId": "rtb-cd6d2cab"}],"PropagatingVgws": [],"Routes": [{"DestinationCidrBlock": "172.31.0.0/16","GatewayId": "local","Origin": "CreateRouteTable","State": "active"},{"DestinationCidrBlock": "0.0.0.0/0","GatewayId": "igw-3aced35e","Origin": "CreateRoute","State": "active"}],"name": "vpc-04ed1062"}},"subnets": {"subnet-2506d06d": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-southeast-1a","AvailabilityZoneId": "apse1-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-southeast-1:430150006394:subnet/subnet-2506d06d","SubnetId": "subnet-2506d06d","VpcId": "vpc-04ed1062","flow_logs": [],"name": "subnet-2506d06d","network_acl": "acl-8787e0e1"},"subnet-a448d5fd": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-southeast-1c","AvailabilityZoneId": "apse1-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-southeast-1:430150006394:subnet/subnet-a448d5fd","SubnetId": "subnet-a448d5fd","VpcId": "vpc-04ed1062","flow_logs": [],"name": "subnet-a448d5fd","network_acl": "acl-8787e0e1"},"subnet-b73197d1": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-southeast-1b","AvailabilityZoneId": "apse1-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-southeast-1:430150006394:subnet/subnet-b73197d1","SubnetId": "subnet-b73197d1","VpcId": "vpc-04ed1062","flow_logs": [],"name": "subnet-b73197d1","network_acl": "acl-8787e0e1"}}}},"vpcs_count": 1,"vpn_connections": {},"vpn_connections_count": 0,"vpn_gateways": {},"vpn_gateways_count": 0},"ap-southeast-2": {"customer_gateways": {},"customer_gateways_count": 0,"flow_logs": {},"flow_logs_count": 0,"network_acls_count": 1,"peering_connections": {},"peering_connections_count": 0,"region": "ap-southeast-2","route_tables_count": 1,"subnets_count": 3,"vpc_resource_types": ["network_acls","subnets","route_tables"],"vpcs": {"vpc-5d22c33b": {"name": "vpc-5d22c33b","network_acls": {"acl-4e4dc228": {"Associations": [{"NetworkAclAssociationId": "aclassoc-fdeb7a8d","NetworkAclId": "acl-4e4dc228","SubnetId": "subnet-6cb44e24"},{"NetworkAclAssociationId": "aclassoc-fbeb7a8b","NetworkAclId": "acl-4e4dc228","SubnetId": "subnet-0c0bc26a"},{"NetworkAclAssociationId": "aclassoc-fceb7a8c","NetworkAclId": "acl-4e4dc228","SubnetId": "subnet-b3fe86eb"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-5d22c33b","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-4e4dc228","name": "acl-4e4dc228","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"route_tables": {"rtb-098ee56f": {"Associations": [{"AssociationState": {"State": "associated"},"Main": true,"RouteTableAssociationId": "rtbassoc-e9d1e490","RouteTableId": "rtb-098ee56f"}],"PropagatingVgws": [],"Routes": [{"DestinationCidrBlock": "172.31.0.0/16","GatewayId": "local","Origin": "CreateRouteTable","State": "active"},{"DestinationCidrBlock": "0.0.0.0/0","GatewayId": "igw-a4d127c3","Origin": "CreateRoute","State": "active"}],"name": "vpc-5d22c33b"}},"subnets": {"subnet-0c0bc26a": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-southeast-2b","AvailabilityZoneId": "apse2-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-southeast-2:430150006394:subnet/subnet-0c0bc26a","SubnetId": "subnet-0c0bc26a","VpcId": "vpc-5d22c33b","flow_logs": [],"name": "subnet-0c0bc26a","network_acl": "acl-4e4dc228"},"subnet-6cb44e24": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-southeast-2a","AvailabilityZoneId": "apse2-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-southeast-2:430150006394:subnet/subnet-6cb44e24","SubnetId": "subnet-6cb44e24","VpcId": "vpc-5d22c33b","flow_logs": [],"name": "subnet-6cb44e24","network_acl": "acl-4e4dc228"},"subnet-b3fe86eb": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ap-southeast-2c","AvailabilityZoneId": "apse2-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ap-southeast-2:430150006394:subnet/subnet-b3fe86eb","SubnetId": "subnet-b3fe86eb","VpcId": "vpc-5d22c33b","flow_logs": [],"name": "subnet-b3fe86eb","network_acl": "acl-4e4dc228"}}}},"vpcs_count": 1,"vpn_connections": {},"vpn_connections_count": 0,"vpn_gateways": {},"vpn_gateways_count": 0},"ca-central-1": {"customer_gateways": {},"customer_gateways_count": 0,"flow_logs": {},"flow_logs_count": 0,"network_acls_count": 1,"peering_connections": {},"peering_connections_count": 0,"region": "ca-central-1","route_tables_count": 1,"subnets_count": 3,"vpc_resource_types": ["network_acls","subnets","route_tables"],"vpcs": {"vpc-b5113ddd": {"name": "vpc-b5113ddd","network_acls": {"acl-63e1ed0b": {"Associations": [{"NetworkAclAssociationId": "aclassoc-31d33c50","NetworkAclId": "acl-63e1ed0b","SubnetId": "subnet-85711fff"},{"NetworkAclAssociationId": "aclassoc-33d33c52","NetworkAclId": "acl-63e1ed0b","SubnetId": "subnet-4f896210"},{"NetworkAclAssociationId": "aclassoc-30d33c51","NetworkAclId": "acl-63e1ed0b","SubnetId": "subnet-1cd98b74"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-b5113ddd","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-63e1ed0b","name": "acl-63e1ed0b","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"route_tables": {"rtb-cc2e36a4": {"Associations": [{"AssociationState": {"State": "associated"},"Main": true,"RouteTableAssociationId": "rtbassoc-a462e9cf","RouteTableId": "rtb-cc2e36a4"}],"PropagatingVgws": [],"Routes": [{"DestinationCidrBlock": "172.31.0.0/16","GatewayId": "local","Origin": "CreateRouteTable","State": "active"},{"DestinationCidrBlock": "0.0.0.0/0","GatewayId": "igw-fa509a92","Origin": "CreateRoute","State": "active"}],"name": "vpc-b5113ddd"}},"subnets": {"subnet-1cd98b74": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ca-central-1a","AvailabilityZoneId": "cac1-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ca-central-1:430150006394:subnet/subnet-1cd98b74","SubnetId": "subnet-1cd98b74","VpcId": "vpc-b5113ddd","flow_logs": [],"name": "subnet-1cd98b74","network_acl": "acl-63e1ed0b"},"subnet-4f896210": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ca-central-1d","AvailabilityZoneId": "cac1-az4","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ca-central-1:430150006394:subnet/subnet-4f896210","SubnetId": "subnet-4f896210","VpcId": "vpc-b5113ddd","flow_logs": [],"name": "subnet-4f896210","network_acl": "acl-63e1ed0b"},"subnet-85711fff": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "ca-central-1b","AvailabilityZoneId": "cac1-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:ca-central-1:430150006394:subnet/subnet-85711fff","SubnetId": "subnet-85711fff","VpcId": "vpc-b5113ddd","flow_logs": [],"name": "subnet-85711fff","network_acl": "acl-63e1ed0b"}}}},"vpcs_count": 1,"vpn_connections": {},"vpn_connections_count": 0,"vpn_gateways": {},"vpn_gateways_count": 0},"eu-central-1": {"customer_gateways": {},"customer_gateways_count": 0,"flow_logs": {},"flow_logs_count": 0,"network_acls_count": 1,"peering_connections": {},"peering_connections_count": 0,"region": "eu-central-1","route_tables_count": 1,"subnets_count": 3,"vpc_resource_types": ["network_acls","subnets","route_tables"],"vpcs": {"vpc-78b43312": {"name": "vpc-78b43312","network_acls": {"acl-6ebcec04": {"Associations": [{"NetworkAclAssociationId": "aclassoc-36773353","NetworkAclId": "acl-6ebcec04","SubnetId": "subnet-55d77f19"},{"NetworkAclAssociationId": "aclassoc-31773354","NetworkAclId": "acl-6ebcec04","SubnetId": "subnet-292d4343"},{"NetworkAclAssociationId": "aclassoc-30773355","NetworkAclId": "acl-6ebcec04","SubnetId": "subnet-ecc66390"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-78b43312","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-6ebcec04","name": "acl-6ebcec04","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"route_tables": {"rtb-50be873a": {"Associations": [{"AssociationState": {"State": "associated"},"Main": true,"RouteTableAssociationId": "rtbassoc-059c9468","RouteTableId": "rtb-50be873a"}],"PropagatingVgws": [],"Routes": [{"DestinationCidrBlock": "172.31.0.0/16","GatewayId": "local","Origin": "CreateRouteTable","State": "active"},{"DestinationCidrBlock": "0.0.0.0/0","GatewayId": "igw-6d7fc506","Origin": "CreateRoute","State": "active"}],"name": "vpc-78b43312"}},"subnets": {"subnet-292d4343": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-central-1a","AvailabilityZoneId": "euc1-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-central-1:430150006394:subnet/subnet-292d4343","SubnetId": "subnet-292d4343","VpcId": "vpc-78b43312","flow_logs": [],"name": "subnet-292d4343","network_acl": "acl-6ebcec04"},"subnet-55d77f19": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-central-1c","AvailabilityZoneId": "euc1-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-central-1:430150006394:subnet/subnet-55d77f19","SubnetId": "subnet-55d77f19","VpcId": "vpc-78b43312","flow_logs": [],"name": "subnet-55d77f19","network_acl": "acl-6ebcec04"},"subnet-ecc66390": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-central-1b","AvailabilityZoneId": "euc1-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-central-1:430150006394:subnet/subnet-ecc66390","SubnetId": "subnet-ecc66390","VpcId": "vpc-78b43312","flow_logs": [],"name": "subnet-ecc66390","network_acl": "acl-6ebcec04"}}}},"vpcs_count": 1,"vpn_connections": {},"vpn_connections_count": 0,"vpn_gateways": {},"vpn_gateways_count": 0},"eu-north-1": {"customer_gateways": {},"customer_gateways_count": 0,"flow_logs": {},"flow_logs_count": 0,"network_acls_count": 1,"peering_connections": {},"peering_connections_count": 0,"region": "eu-north-1","route_tables_count": 1,"subnets_count": 3,"vpc_resource_types": ["network_acls","subnets","route_tables"],"vpcs": {"vpc-fa259d93": {"name": "vpc-fa259d93","network_acls": {"acl-dfb10ab6": {"Associations": [{"NetworkAclAssociationId": "aclassoc-8ed1b4e3","NetworkAclId": "acl-dfb10ab6","SubnetId": "subnet-1d972e74"},{"NetworkAclAssociationId": "aclassoc-89d1b4e4","NetworkAclId": "acl-dfb10ab6","SubnetId": "subnet-fe16ce85"},{"NetworkAclAssociationId": "aclassoc-8fd1b4e2","NetworkAclId": "acl-dfb10ab6","SubnetId": "subnet-c98e7484"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-fa259d93","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-dfb10ab6","name": "acl-dfb10ab6","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"route_tables": {"rtb-fd6dd694": {"Associations": [{"AssociationState": {"State": "associated"},"Main": true,"RouteTableAssociationId": "rtbassoc-3e813a57","RouteTableId": "rtb-fd6dd694"}],"PropagatingVgws": [],"Routes": [{"DestinationCidrBlock": "172.31.0.0/16","GatewayId": "local","Origin": "CreateRouteTable","State": "active"},{"DestinationCidrBlock": "0.0.0.0/0","GatewayId": "igw-05da646c","Origin": "CreateRoute","State": "active"}],"name": "vpc-fa259d93"}},"subnets": {"subnet-1d972e74": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-north-1a","AvailabilityZoneId": "eun1-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-north-1:430150006394:subnet/subnet-1d972e74","SubnetId": "subnet-1d972e74","VpcId": "vpc-fa259d93","flow_logs": [],"name": "subnet-1d972e74","network_acl": "acl-dfb10ab6"},"subnet-c98e7484": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-north-1c","AvailabilityZoneId": "eun1-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-north-1:430150006394:subnet/subnet-c98e7484","SubnetId": "subnet-c98e7484","VpcId": "vpc-fa259d93","flow_logs": [],"name": "subnet-c98e7484","network_acl": "acl-dfb10ab6"},"subnet-fe16ce85": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-north-1b","AvailabilityZoneId": "eun1-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-north-1:430150006394:subnet/subnet-fe16ce85","SubnetId": "subnet-fe16ce85","VpcId": "vpc-fa259d93","flow_logs": [],"name": "subnet-fe16ce85","network_acl": "acl-dfb10ab6"}}}},"vpcs_count": 1,"vpn_connections": {},"vpn_connections_count": 0,"vpn_gateways": {},"vpn_gateways_count": 0},"eu-south-1": {"customer_gateways": {},"customer_gateways_count": 0,"flow_logs": {},"flow_logs_count": 0,"network_acls_count": 0,"peering_connections": {},"peering_connections_count": 0,"region": "eu-south-1","route_tables_count": 0,"subnets_count": 0,"vpc_resource_types": ["network_acls","subnets","route_tables"],"vpcs": {},"vpcs_count": 0,"vpn_connections": {},"vpn_connections_count": 0,"vpn_gateways": {},"vpn_gateways_count": 0},"eu-west-1": {"customer_gateways": {},"customer_gateways_count": 0,"flow_logs": {},"flow_logs_count": 0,"network_acls_count": 1,"peering_connections": {},"peering_connections_count": 0,"region": "eu-west-1","route_tables_count": 1,"subnets_count": 3,"vpc_resource_types": ["network_acls","subnets","route_tables"],"vpcs": {"vpc-f24c7994": {"name": "vpc-f24c7994","network_acls": {"acl-ed4be494": {"Associations": [{"NetworkAclAssociationId": "aclassoc-5a508624","NetworkAclId": "acl-ed4be494","SubnetId": "subnet-b3a000e9"},{"NetworkAclAssociationId": "aclassoc-5d508623","NetworkAclId": "acl-ed4be494","SubnetId": "subnet-214f3969"},{"NetworkAclAssociationId": "aclassoc-5c508622","NetworkAclId": "acl-ed4be494","SubnetId": "subnet-b1c2a5d7"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-f24c7994","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-ed4be494","name": "acl-ed4be494","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"route_tables": {"rtb-d3b1edaa": {"Associations": [{"AssociationState": {"State": "associated"},"Main": true,"RouteTableAssociationId": "rtbassoc-ad17b7d6","RouteTableId": "rtb-d3b1edaa"}],"PropagatingVgws": [],"Routes": [{"DestinationCidrBlock": "172.31.0.0/16","GatewayId": "local","Origin": "CreateRouteTable","State": "active"},{"DestinationCidrBlock": "0.0.0.0/0","GatewayId": "igw-1c7b5d7b","Origin": "CreateRoute","State": "active"}],"name": "vpc-f24c7994"}},"subnets": {"subnet-214f3969": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-west-1a","AvailabilityZoneId": "euw1-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-west-1:430150006394:subnet/subnet-214f3969","SubnetId": "subnet-214f3969","VpcId": "vpc-f24c7994","flow_logs": [],"name": "subnet-214f3969","network_acl": "acl-ed4be494"},"subnet-b1c2a5d7": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-west-1c","AvailabilityZoneId": "euw1-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-west-1:430150006394:subnet/subnet-b1c2a5d7","SubnetId": "subnet-b1c2a5d7","VpcId": "vpc-f24c7994","flow_logs": [],"name": "subnet-b1c2a5d7","network_acl": "acl-ed4be494"},"subnet-b3a000e9": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-west-1b","AvailabilityZoneId": "euw1-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-west-1:430150006394:subnet/subnet-b3a000e9","SubnetId": "subnet-b3a000e9","VpcId": "vpc-f24c7994","flow_logs": [],"name": "subnet-b3a000e9","network_acl": "acl-ed4be494"}}}},"vpcs_count": 1,"vpn_connections": {},"vpn_connections_count": 0,"vpn_gateways": {},"vpn_gateways_count": 0},"eu-west-2": {"customer_gateways": {},"customer_gateways_count": 0,"flow_logs": {},"flow_logs_count": 0,"network_acls_count": 1,"peering_connections": {},"peering_connections_count": 0,"region": "eu-west-2","route_tables_count": 1,"subnets_count": 3,"vpc_resource_types": ["network_acls","subnets","route_tables"],"vpcs": {"vpc-3fa2fa57": {"name": "vpc-3fa2fa57","network_acls": {"acl-003d0768": {"Associations": [{"NetworkAclAssociationId": "aclassoc-e73eff86","NetworkAclId": "acl-003d0768","SubnetId": "subnet-43bf9d2a"},{"NetworkAclAssociationId": "aclassoc-e93eff88","NetworkAclId": "acl-003d0768","SubnetId": "subnet-edaf13a1"},{"NetworkAclAssociationId": "aclassoc-e63eff87","NetworkAclId": "acl-003d0768","SubnetId": "subnet-e682ec9c"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-3fa2fa57","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-003d0768","name": "acl-003d0768","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"route_tables": {"rtb-355f4b5d": {"Associations": [{"AssociationState": {"State": "associated"},"Main": true,"RouteTableAssociationId": "rtbassoc-0d980b66","RouteTableId": "rtb-355f4b5d"}],"PropagatingVgws": [],"Routes": [{"DestinationCidrBlock": "172.31.0.0/16","GatewayId": "local","Origin": "CreateRouteTable","State": "active"},{"DestinationCidrBlock": "0.0.0.0/0","GatewayId": "igw-02599a6a","Origin": "CreateRoute","State": "active"}],"name": "vpc-3fa2fa57"}},"subnets": {"subnet-43bf9d2a": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-west-2c","AvailabilityZoneId": "euw2-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-west-2:430150006394:subnet/subnet-43bf9d2a","SubnetId": "subnet-43bf9d2a","VpcId": "vpc-3fa2fa57","flow_logs": [],"name": "subnet-43bf9d2a","network_acl": "acl-003d0768"},"subnet-e682ec9c": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-west-2a","AvailabilityZoneId": "euw2-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-west-2:430150006394:subnet/subnet-e682ec9c","SubnetId": "subnet-e682ec9c","VpcId": "vpc-3fa2fa57","flow_logs": [],"name": "subnet-e682ec9c","network_acl": "acl-003d0768"},"subnet-edaf13a1": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-west-2b","AvailabilityZoneId": "euw2-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-west-2:430150006394:subnet/subnet-edaf13a1","SubnetId": "subnet-edaf13a1","VpcId": "vpc-3fa2fa57","flow_logs": [],"name": "subnet-edaf13a1","network_acl": "acl-003d0768"}}}},"vpcs_count": 1,"vpn_connections": {},"vpn_connections_count": 0,"vpn_gateways": {},"vpn_gateways_count": 0},"eu-west-3": {"customer_gateways": {},"customer_gateways_count": 0,"flow_logs": {},"flow_logs_count": 0,"network_acls_count": 1,"peering_connections": {},"peering_connections_count": 0,"region": "eu-west-3","route_tables_count": 1,"subnets_count": 3,"vpc_resource_types": ["network_acls","subnets","route_tables"],"vpcs": {"vpc-87d3fdee": {"name": "vpc-87d3fdee","network_acls": {"acl-c74e7dae": {"Associations": [{"NetworkAclAssociationId": "aclassoc-de1211b6","NetworkAclId": "acl-c74e7dae","SubnetId": "subnet-762a450d"},{"NetworkAclAssociationId": "aclassoc-dd1211b5","NetworkAclId": "acl-c74e7dae","SubnetId": "subnet-e9e1b480"},{"NetworkAclAssociationId": "aclassoc-df1211b7","NetworkAclId": "acl-c74e7dae","SubnetId": "subnet-b309b8fe"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-87d3fdee","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-c74e7dae","name": "acl-c74e7dae","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"route_tables": {"rtb-7f447a16": {"Associations": [{"AssociationState": {"State": "associated"},"Main": true,"RouteTableAssociationId": "rtbassoc-8eaa41e6","RouteTableId": "rtb-7f447a16"}],"PropagatingVgws": [],"Routes": [{"DestinationCidrBlock": "172.31.0.0/16","GatewayId": "local","Origin": "CreateRouteTable","State": "active"},{"DestinationCidrBlock": "0.0.0.0/0","GatewayId": "igw-54caa73d","Origin": "CreateRoute","State": "active"}],"name": "vpc-87d3fdee"}},"subnets": {"subnet-762a450d": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-west-3b","AvailabilityZoneId": "euw3-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-west-3:430150006394:subnet/subnet-762a450d","SubnetId": "subnet-762a450d","VpcId": "vpc-87d3fdee","flow_logs": [],"name": "subnet-762a450d","network_acl": "acl-c74e7dae"},"subnet-b309b8fe": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-west-3c","AvailabilityZoneId": "euw3-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-west-3:430150006394:subnet/subnet-b309b8fe","SubnetId": "subnet-b309b8fe","VpcId": "vpc-87d3fdee","flow_logs": [],"name": "subnet-b309b8fe","network_acl": "acl-c74e7dae"},"subnet-e9e1b480": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "eu-west-3a","AvailabilityZoneId": "euw3-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:eu-west-3:430150006394:subnet/subnet-e9e1b480","SubnetId": "subnet-e9e1b480","VpcId": "vpc-87d3fdee","flow_logs": [],"name": "subnet-e9e1b480","network_acl": "acl-c74e7dae"}}}},"vpcs_count": 1,"vpn_connections": {},"vpn_connections_count": 0,"vpn_gateways": {},"vpn_gateways_count": 0},"me-south-1": {"customer_gateways": {},"customer_gateways_count": 0,"flow_logs": {},"flow_logs_count": 0,"network_acls_count": 0,"peering_connections": {},"peering_connections_count": 0,"region": "me-south-1","route_tables_count": 0,"subnets_count": 0,"vpc_resource_types": ["network_acls","subnets","route_tables"],"vpcs": {},"vpcs_count": 0,"vpn_connections": {},"vpn_connections_count": 0,"vpn_gateways": {},"vpn_gateways_count": 0},"sa-east-1": {"customer_gateways": {},"customer_gateways_count": 0,"flow_logs": {},"flow_logs_count": 0,"network_acls_count": 1,"peering_connections": {},"peering_connections_count": 0,"region": "sa-east-1","route_tables_count": 1,"subnets_count": 3,"vpc_resource_types": ["network_acls","subnets","route_tables"],"vpcs": {"vpc-b14fa4d7": {"name": "vpc-b14fa4d7","network_acls": {"acl-43816e25": {"Associations": [{"NetworkAclAssociationId": "aclassoc-7477890a","NetworkAclId": "acl-43816e25","SubnetId": "subnet-9aa5c1fc"},{"NetworkAclAssociationId": "aclassoc-7277890c","NetworkAclId": "acl-43816e25","SubnetId": "subnet-aaddbef1"},{"NetworkAclAssociationId": "aclassoc-7577890b","NetworkAclId": "acl-43816e25","SubnetId": "subnet-6a4dd723"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-b14fa4d7","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-43816e25","name": "acl-43816e25","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"route_tables": {"rtb-6744ba01": {"Associations": [{"AssociationState": {"State": "associated"},"Main": true,"RouteTableAssociationId": "rtbassoc-f18b5288","RouteTableId": "rtb-6744ba01"}],"PropagatingVgws": [],"Routes": [{"DestinationCidrBlock": "172.31.0.0/16","GatewayId": "local","Origin": "CreateRouteTable","State": "active"},{"DestinationCidrBlock": "0.0.0.0/0","GatewayId": "igw-440e2e20","Origin": "CreateRoute","State": "active"}],"name": "vpc-b14fa4d7"}},"subnets": {"subnet-6a4dd723": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "sa-east-1b","AvailabilityZoneId": "sae1-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:sa-east-1:430150006394:subnet/subnet-6a4dd723","SubnetId": "subnet-6a4dd723","VpcId": "vpc-b14fa4d7","flow_logs": [],"name": "subnet-6a4dd723","network_acl": "acl-43816e25"},"subnet-9aa5c1fc": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "sa-east-1a","AvailabilityZoneId": "sae1-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:sa-east-1:430150006394:subnet/subnet-9aa5c1fc","SubnetId": "subnet-9aa5c1fc","VpcId": "vpc-b14fa4d7","flow_logs": [],"name": "subnet-9aa5c1fc","network_acl": "acl-43816e25"},"subnet-aaddbef1": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "sa-east-1c","AvailabilityZoneId": "sae1-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:sa-east-1:430150006394:subnet/subnet-aaddbef1","SubnetId": "subnet-aaddbef1","VpcId": "vpc-b14fa4d7","flow_logs": [],"name": "subnet-aaddbef1","network_acl": "acl-43816e25"}}}},"vpcs_count": 1,"vpn_connections": {},"vpn_connections_count": 0,"vpn_gateways": {},"vpn_gateways_count": 0},"us-east-1": {"customer_gateways": {},"customer_gateways_count": 0,"flow_logs": {},"flow_logs_count": 0,"network_acls_count": 1,"peering_connections": {},"peering_connections_count": 0,"region": "us-east-1","route_tables_count": 1,"subnets_count": 6,"vpc_resource_types": ["network_acls","subnets","route_tables"],"vpcs": {"vpc-ba1cbdc7": {"name": "vpc-ba1cbdc7","network_acls": {"acl-f1a6ae8c": {"Associations": [{"NetworkAclAssociationId": "aclassoc-ad34c3ff","NetworkAclId": "acl-f1a6ae8c","SubnetId": "subnet-7056187e"},{"NetworkAclAssociationId": "aclassoc-af34c3fd","NetworkAclId": "acl-f1a6ae8c","SubnetId": "subnet-30be2f6f"},{"NetworkAclAssociationId": "aclassoc-ac34c3fe","NetworkAclId": "acl-f1a6ae8c","SubnetId": "subnet-8c27ffbd"},{"NetworkAclAssociationId": "aclassoc-5233c400","NetworkAclId": "acl-f1a6ae8c","SubnetId": "subnet-6e61f24f"},{"NetworkAclAssociationId": "aclassoc-ae34c3fc","NetworkAclId": "acl-f1a6ae8c","SubnetId": "subnet-cbefcb86"},{"NetworkAclAssociationId": "aclassoc-a934c3fb","NetworkAclId": "acl-f1a6ae8c","SubnetId": "subnet-77e07411"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-ba1cbdc7","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-f1a6ae8c","name": "acl-f1a6ae8c","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"route_tables": {"rtb-5988a427": {"Associations": [{"AssociationState": {"State": "associated"},"Main": true,"RouteTableAssociationId": "rtbassoc-6d069a1c","RouteTableId": "rtb-5988a427"}],"PropagatingVgws": [],"Routes": [{"DestinationCidrBlock": "172.31.0.0/16","GatewayId": "local","Origin": "CreateRouteTable","State": "active"},{"DestinationCidrBlock": "0.0.0.0/0","GatewayId": "igw-65b4a01e","Origin": "CreateRoute","State": "active"}],"name": "vpc-ba1cbdc7"}},"subnets": {"subnet-30be2f6f": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-east-1c","AvailabilityZoneId": "use1-az6","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-east-1:430150006394:subnet/subnet-30be2f6f","SubnetId": "subnet-30be2f6f","VpcId": "vpc-ba1cbdc7","flow_logs": [],"name": "subnet-30be2f6f","network_acl": "acl-f1a6ae8c"},"subnet-6e61f24f": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-east-1a","AvailabilityZoneId": "use1-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.80.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-east-1:430150006394:subnet/subnet-6e61f24f","SubnetId": "subnet-6e61f24f","VpcId": "vpc-ba1cbdc7","flow_logs": [],"name": "subnet-6e61f24f","network_acl": "acl-f1a6ae8c"},"subnet-7056187e": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-east-1f","AvailabilityZoneId": "use1-az5","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.64.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-east-1:430150006394:subnet/subnet-7056187e","SubnetId": "subnet-7056187e","VpcId": "vpc-ba1cbdc7","flow_logs": [],"name": "subnet-7056187e","network_acl": "acl-f1a6ae8c"},"subnet-77e07411": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-east-1d","AvailabilityZoneId": "use1-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-east-1:430150006394:subnet/subnet-77e07411","SubnetId": "subnet-77e07411","VpcId": "vpc-ba1cbdc7","flow_logs": [],"name": "subnet-77e07411","network_acl": "acl-f1a6ae8c"},"subnet-8c27ffbd": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-east-1e","AvailabilityZoneId": "use1-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.48.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-east-1:430150006394:subnet/subnet-8c27ffbd","SubnetId": "subnet-8c27ffbd","VpcId": "vpc-ba1cbdc7","flow_logs": [],"name": "subnet-8c27ffbd","network_acl": "acl-f1a6ae8c"},"subnet-cbefcb86": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-east-1b","AvailabilityZoneId": "use1-az4","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-east-1:430150006394:subnet/subnet-cbefcb86","SubnetId": "subnet-cbefcb86","VpcId": "vpc-ba1cbdc7","flow_logs": [],"name": "subnet-cbefcb86","network_acl": "acl-f1a6ae8c"}}}},"vpcs_count": 1,"vpn_connections": {},"vpn_connections_count": 0,"vpn_gateways": {},"vpn_gateways_count": 0},"us-east-2": {"customer_gateways": {},"customer_gateways_count": 0,"flow_logs": {},"flow_logs_count": 0,"network_acls_count": 1,"peering_connections": {},"peering_connections_count": 0,"region": "us-east-2","route_tables_count": 1,"subnets_count": 3,"vpc_resource_types": ["network_acls","subnets","route_tables"],"vpcs": {"vpc-e429ad8f": {"name": "vpc-e429ad8f","network_acls": {"acl-b06507db": {"Associations": [{"NetworkAclAssociationId": "aclassoc-164f9a74","NetworkAclId": "acl-b06507db","SubnetId": "subnet-81a1eccd"},{"NetworkAclAssociationId": "aclassoc-114f9a73","NetworkAclId": "acl-b06507db","SubnetId": "subnet-18e60365"},{"NetworkAclAssociationId": "aclassoc-104f9a72","NetworkAclId": "acl-b06507db","SubnetId": "subnet-fac76891"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-e429ad8f","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-b06507db","name": "acl-b06507db","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"route_tables": {"rtb-20703c4b": {"Associations": [{"AssociationState": {"State": "associated"},"Main": true,"RouteTableAssociationId": "rtbassoc-d94acab3","RouteTableId": "rtb-20703c4b"}],"PropagatingVgws": [],"Routes": [{"DestinationCidrBlock": "172.31.0.0/16","GatewayId": "local","Origin": "CreateRouteTable","State": "active"},{"DestinationCidrBlock": "0.0.0.0/0","GatewayId": "igw-402d0c28","Origin": "CreateRoute","State": "active"}],"name": "vpc-e429ad8f"}},"subnets": {"subnet-18e60365": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-east-2b","AvailabilityZoneId": "use2-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-east-2:430150006394:subnet/subnet-18e60365","SubnetId": "subnet-18e60365","VpcId": "vpc-e429ad8f","flow_logs": [],"name": "subnet-18e60365","network_acl": "acl-b06507db"},"subnet-81a1eccd": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-east-2c","AvailabilityZoneId": "use2-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-east-2:430150006394:subnet/subnet-81a1eccd","SubnetId": "subnet-81a1eccd","VpcId": "vpc-e429ad8f","flow_logs": [],"name": "subnet-81a1eccd","network_acl": "acl-b06507db"},"subnet-fac76891": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-east-2a","AvailabilityZoneId": "use2-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-east-2:430150006394:subnet/subnet-fac76891","SubnetId": "subnet-fac76891","VpcId": "vpc-e429ad8f","flow_logs": [],"name": "subnet-fac76891","network_acl": "acl-b06507db"}}}},"vpcs_count": 1,"vpn_connections": {},"vpn_connections_count": 0,"vpn_gateways": {},"vpn_gateways_count": 0},"us-west-1": {"customer_gateways": {},"customer_gateways_count": 0,"flow_logs": {},"flow_logs_count": 0,"network_acls_count": 1,"peering_connections": {},"peering_connections_count": 0,"region": "us-west-1","route_tables_count": 1,"subnets_count": 2,"vpc_resource_types": ["network_acls","subnets","route_tables"],"vpcs": {"vpc-6e6fa508": {"name": "vpc-6e6fa508","network_acls": {"acl-14a0c772": {"Associations": [{"NetworkAclAssociationId": "aclassoc-a9f7b7d5","NetworkAclId": "acl-14a0c772","SubnetId": "subnet-64f07402"},{"NetworkAclAssociationId": "aclassoc-a8f7b7d4","NetworkAclId": "acl-14a0c772","SubnetId": "subnet-3162b36b"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-6e6fa508","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-14a0c772","name": "acl-14a0c772","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"route_tables": {"rtb-e3adec85": {"Associations": [{"AssociationState": {"State": "associated"},"Main": true,"RouteTableAssociationId": "rtbassoc-8c22b9f5","RouteTableId": "rtb-e3adec85"}],"PropagatingVgws": [],"Routes": [{"DestinationCidrBlock": "172.31.0.0/16","GatewayId": "local","Origin": "CreateRouteTable","State": "active"},{"DestinationCidrBlock": "0.0.0.0/0","GatewayId": "igw-05fa3162","Origin": "CreateRoute","State": "active"}],"name": "vpc-6e6fa508"}},"subnets": {"subnet-3162b36b": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-west-1c","AvailabilityZoneId": "usw1-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-west-1:430150006394:subnet/subnet-3162b36b","SubnetId": "subnet-3162b36b","VpcId": "vpc-6e6fa508","flow_logs": [],"name": "subnet-3162b36b","network_acl": "acl-14a0c772"},"subnet-64f07402": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-west-1a","AvailabilityZoneId": "usw1-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-west-1:430150006394:subnet/subnet-64f07402","SubnetId": "subnet-64f07402","VpcId": "vpc-6e6fa508","flow_logs": [],"name": "subnet-64f07402","network_acl": "acl-14a0c772"}}}},"vpcs_count": 1,"vpn_connections": {},"vpn_connections_count": 0,"vpn_gateways": {},"vpn_gateways_count": 0},"us-west-2": {"customer_gateways": {},"customer_gateways_count": 0,"flow_logs": {},"flow_logs_count": 0,"network_acls_count": 1,"peering_connections": {},"peering_connections_count": 0,"region": "us-west-2","route_tables_count": 1,"subnets_count": 4,"vpc_resource_types": ["network_acls","subnets","route_tables"],"vpcs": {"vpc-d45709ac": {"name": "vpc-d45709ac","network_acls": {"acl-f76adc8c": {"Associations": [{"NetworkAclAssociationId": "aclassoc-5edb3d1c","NetworkAclId": "acl-f76adc8c","SubnetId": "subnet-1075cf4d"},{"NetworkAclAssociationId": "aclassoc-5ddb3d1f","NetworkAclId": "acl-f76adc8c","SubnetId": "subnet-64dae84f"},{"NetworkAclAssociationId": "aclassoc-5fdb3d1d","NetworkAclId": "acl-f76adc8c","SubnetId": "subnet-25f65d5d"},{"NetworkAclAssociationId": "aclassoc-5cdb3d1e","NetworkAclId": "acl-f76adc8c","SubnetId": "subnet-113ce95b"}],"IsDefault": true,"OwnerId": "430150006394","Tags": [],"VpcId": "vpc-d45709ac","allow_all_egress_traffic": "100","allow_all_ingress_traffic": "100","id": "acl-f76adc8c","name": "acl-f76adc8c","rules": {"egress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}},"ingress": {"100": {"CidrBlock": "0.0.0.0/0","RuleAction": "allow","port_range": "1-65535","protocol": "ALL"},"32767": {"CidrBlock": "0.0.0.0/0","RuleAction": "deny","port_range": "1-65535","protocol": "ALL"}}},"use_default_egress_rules": true,"use_default_ingress_rules": true}},"route_tables": {"rtb-2a87bf51": {"Associations": [{"AssociationState": {"State": "associated"},"Main": true,"RouteTableAssociationId": "rtbassoc-28eff655","RouteTableId": "rtb-2a87bf51"}],"PropagatingVgws": [],"Routes": [{"DestinationCidrBlock": "172.31.0.0/16","GatewayId": "local","Origin": "CreateRouteTable","State": "active"},{"DestinationCidrBlock": "0.0.0.0/0","GatewayId": "igw-a31e9eda","Origin": "CreateRoute","State": "active"}],"name": "vpc-d45709ac"}},"subnets": {"subnet-1075cf4d": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-west-2c","AvailabilityZoneId": "usw2-az3","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.0.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-west-2:430150006394:subnet/subnet-1075cf4d","SubnetId": "subnet-1075cf4d","VpcId": "vpc-d45709ac","flow_logs": [],"name": "subnet-1075cf4d","network_acl": "acl-f76adc8c"},"subnet-113ce95b": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-west-2b","AvailabilityZoneId": "usw2-az2","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.32.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-west-2:430150006394:subnet/subnet-113ce95b","SubnetId": "subnet-113ce95b","VpcId": "vpc-d45709ac","flow_logs": [],"name": "subnet-113ce95b","network_acl": "acl-f76adc8c"},"subnet-25f65d5d": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-west-2a","AvailabilityZoneId": "usw2-az1","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.16.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-west-2:430150006394:subnet/subnet-25f65d5d","SubnetId": "subnet-25f65d5d","VpcId": "vpc-d45709ac","flow_logs": [],"name": "subnet-25f65d5d","network_acl": "acl-f76adc8c"},"subnet-64dae84f": {"AssignIpv6AddressOnCreation": false,"AvailabilityZone": "us-west-2d","AvailabilityZoneId": "usw2-az4","AvailableIpAddressCount": 4091,"CidrBlock": "172.31.48.0/20","DefaultForAz": true,"Ipv6CidrBlockAssociationSet": [],"MapCustomerOwnedIpOnLaunch": false,"MapPublicIpOnLaunch": true,"OwnerId": "430150006394","State": "available","SubnetArn": "arn:aws:ec2:us-west-2:430150006394:subnet/subnet-64dae84f","SubnetId": "subnet-64dae84f","VpcId": "vpc-d45709ac","flow_logs": [],"name": "subnet-64dae84f","network_acl": "acl-f76adc8c"}}}},"vpcs_count": 1,"vpn_connections": {},"vpn_connections_count": 0,"vpn_gateways": {},"vpn_gateways_count": 0}},"regions_count": 21,"resource_types": {"global": [],"region": ["vpcs","flow_logs","customer_gateways","vpn_gateways","vpn_connections","peering_connections"],"vpc": ["network_acls","subnets","route_tables"]},"route_tables_count": 17,"service": "vpc","subnets_count": 55,"targets": {"first_region": [["network_acls","NetworkAcls","describe_network_acls",{},false],["vpcs","Vpcs","describe_vpcs",{},false],["flow_logs","FlowLogs","describe_flow_logs",{},false],["subnets","Subnets","describe_subnets",{},false],["customer_gateways","CustomerGateways","describe_customer_gateways",{},false],["vpn_gateways","VpnGateways","describe_vpn_gateways",{},false],["vpn_connections","VpnConnections","describe_vpn_connections",{},false],["route_tables","RouteTables","describe_route_tables",{},false],["peering_connections","VpcPeeringConnections","describe_vpc_peering_connections",{},false]],"other_regions": [["network_acls","NetworkAcls","describe_network_acls",{},false],["vpcs","Vpcs","describe_vpcs",{},false],["flow_logs","FlowLogs","describe_flow_logs",{},false],["subnets","Subnets","describe_subnets",{},false],["customer_gateways","CustomerGateways","describe_customer_gateways",{},false],["vpn_gateways","VpnGateways","describe_vpn_gateways",{},false],["vpn_connections","VpnConnections","describe_vpn_connections",{},false],["route_tables","RouteTables","describe_route_tables",{},false],["peering_connections","VpcPeeringConnections","describe_vpc_peering_connections",{},false]]},"thread_config": {"list": 10,"parse": 20},"vpcs_count": 17,"vpn_connections_count": 0,"vpn_gateways_count": 0}}} diff --git a/unittests/tools/test_aws_scout2_parser.py b/unittests/tools/test_aws_scout2_parser.py deleted file mode 100644 index 309f0eb853..0000000000 --- a/unittests/tools/test_aws_scout2_parser.py +++ /dev/null @@ -1,48 +0,0 @@ -from django.utils import timezone - -from dojo.models import Engagement, Product, Product_Type, Test, Test_Type -from dojo.tools.aws_scout2.parser import AWSScout2Parser - -from ..dojo_test_case import DojoTestCase - - -class TestAwsProwlerParser(DojoTestCase): - def setup(self, testfile): - product_type = Product_Type(critical_product=True, key_product=False) - product_type.save() - - test_type = Test_Type(static_tool=True, dynamic_tool=False) - test_type.save() - - product = Product(prod_type=product_type) - product.save() - - engagement = Engagement( - product=product, target_start=timezone.now(), target_end=timezone.now() - ) - engagement.save() - - parser = AWSScout2Parser() - findings = parser.get_findings( - testfile, - Test( - engagement=engagement, - test_type=test_type, - target_start=timezone.now(), - target_end=timezone.now(), - ), - ) - - testfile.close() - - return findings - - def test_parser_with_critical_vuln_has_one_findings(self): - findings = self.setup(open("unittests/scans/aws_scout2/aws_config.js")) - self.assertEqual(21, len(findings)) - self.assertEqual("Global services logging disabled", findings[0].title) - self.assertEqual("Critical", findings[0].severity) - self.assertEqual(1032, findings[0].cwe) - self.assertEqual("Unused security groups", findings[6].title) - self.assertEqual("Medium", findings[6].severity) - self.assertEqual(1032, findings[6].cwe) From ab34598956086e062a7079c2304bcab56c42f468 Mon Sep 17 00:00:00 2001 From: Ahmad Khan Date: Tue, 30 Apr 2024 21:50:54 -0500 Subject: [PATCH 111/138] Newlines in SARIF parser code blocks (#9932) * code delimiters on separate lines * update unit tests --- dojo/tools/sarif/parser.py | 2 +- unittests/tools/test_sarif_parser.py | 94 +++++++++++++++++----------- 2 files changed, 59 insertions(+), 37 deletions(-) diff --git a/dojo/tools/sarif/parser.py b/dojo/tools/sarif/parser.py index d3fa31f742..59dae7da29 100644 --- a/dojo/tools/sarif/parser.py +++ b/dojo/tools/sarif/parser.py @@ -271,7 +271,7 @@ def get_description(result, rule): ) description += f"**Result message:** {message}\n" if get_snippet(result) is not None: - description += f"**Snippet:**\n```{get_snippet(result)}```\n" + description += f"**Snippet:**\n```\n{get_snippet(result)}\n```\n" if rule is not None: if "name" in rule: description += f"**{_('Rule name')}:** {rule.get('name')}\n" diff --git a/unittests/tools/test_sarif_parser.py b/unittests/tools/test_sarif_parser.py index b4ceb56927..dcc4d41e23 100644 --- a/unittests/tools/test_sarif_parser.py +++ b/unittests/tools/test_sarif_parser.py @@ -52,8 +52,10 @@ def test_example2_report(self): self.assertEqual("High", item.severity) description = """**Result message:** Variable "ptr" was used without being initialized. It was declared [here](0). **Snippet:** -```add_core(ptr, offset, val); - return;``` +``` +add_core(ptr, offset, val); + return; +``` **Rule short description:** A variable was used without being initialized. **Rule full description:** A variable was used without being initialized. This can result in runtime errors such as null reference exceptions. **Code flow:** @@ -329,36 +331,42 @@ def test_gitleaks(self): self.assertEqual("Medium", finding.severity) description = """**Result message:** AWS Access Key secret detected **Snippet:** -``` \"raw_source_code_extract\": \"AKIAIOSFODNN7EXAMPLE\",```""" - self.assertEqual(description, finding.description) - self.assertEqual( - "dojo/unittests/scans/gitlab_secret_detection_report/gitlab_secret_detection_report_1_vuln.json", - finding.file_path, - ) - self.assertEqual(13, finding.line) - with self.subTest(i=3): - finding = findings[3] - self.assertEqual("AWS Access Key secret detected", finding.title) - self.assertEqual("Medium", finding.severity) - description = """**Result message:** AWS Access Key secret detected +``` + \"raw_source_code_extract\": \"AKIAIOSFODNN7EXAMPLE\", +```""" + self.assertEqual(description, finding.description) + self.assertEqual( + "dojo/unittests/scans/gitlab_secret_detection_report/gitlab_secret_detection_report_1_vuln.json", + finding.file_path, + ) + self.assertEqual(13, finding.line) + with self.subTest(i=3): + finding = findings[3] + self.assertEqual("AWS Access Key secret detected", finding.title) + self.assertEqual("Medium", finding.severity) + description = """**Result message:** AWS Access Key secret detected **Snippet:** -``` \"raw_source_code_extract\": \"AKIAIOSFODNN7EXAMPLE\",```""" - self.assertEqual(description, finding.description) - self.assertEqual( - "dojo/unittests/scans/gitlab_secret_detection_report/gitlab_secret_detection_report_3_vuln.json", - finding.file_path, - ) - self.assertEqual(44, finding.line) - with self.subTest(i=7): - finding = findings[7] - self.assertEqual("AWS Access Key secret detected", finding.title) - self.assertEqual("Medium", finding.severity) - description = """**Result message:** AWS Access Key secret detected +``` + \"raw_source_code_extract\": \"AKIAIOSFODNN7EXAMPLE\", +```""" + self.assertEqual(description, finding.description) + self.assertEqual( + "dojo/unittests/scans/gitlab_secret_detection_report/gitlab_secret_detection_report_3_vuln.json", + finding.file_path, + ) + self.assertEqual(44, finding.line) + with self.subTest(i=7): + finding = findings[7] + self.assertEqual("AWS Access Key secret detected", finding.title) + self.assertEqual("Medium", finding.severity) + description = """**Result message:** AWS Access Key secret detected **Snippet:** -``` self.assertEqual(\"AWS\\nAKIAIOSFODNN7EXAMPLE\", first_finding.description)```""" - self.assertEqual(description, finding.description) - self.assertEqual("dojo/unittests/tools/test_gitlab_secret_detection_report_parser.py", finding.file_path) - self.assertEqual(37, finding.line) +``` + self.assertEqual(\"AWS\\nAKIAIOSFODNN7EXAMPLE\", first_finding.description) +```""" + self.assertEqual(description, finding.description) + self.assertEqual("dojo/unittests/tools/test_gitlab_secret_detection_report_parser.py", finding.file_path) + self.assertEqual(37, finding.line) def test_flawfinder(self): with open(path.join(path.dirname(__file__), "../scans/sarif/flawfinder.sarif")) as testfile: @@ -376,7 +384,9 @@ def test_flawfinder(self): self.assertEqual("High", finding.severity) description = """**Result message:** random/setstate:This function is not sufficiently random for security-related functions such as key and nonce creation (CWE-327). **Snippet:** -``` is.setstate(std::ios::failbit);``` +``` + is.setstate(std::ios::failbit); +``` **Rule name:** random/setstate **Rule short description:** This function is not sufficiently random for security-related functions such as key and nonce creation (CWE-327).""" self.assertEqual(description, finding.description) @@ -397,7 +407,9 @@ def test_flawfinder(self): self.assertEqual("Info", finding.severity) description = """**Result message:** buffer/memcpy:Does not check for buffer overflows when copying to destination (CWE-120). **Snippet:** -``` std::memcpy(dptr, dmlc::BeginPtr(buffer_) + buffer_ptr_, size);``` +``` + std::memcpy(dptr, dmlc::BeginPtr(buffer_) + buffer_ptr_, size); +``` **Rule name:** buffer/memcpy **Rule short description:** Does not check for buffer overflows when copying to destination (CWE-120).""" self.assertEqual(description, finding.description) @@ -418,7 +430,9 @@ def test_flawfinder(self): self.assertEqual("High", finding.severity) description = """**Result message:** buffer/sscanf:The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20). **Snippet:** -``` if (sscanf(argv[i], "%[^=]=%s", name, val) == 2) {``` +``` + if (sscanf(argv[i], "%[^=]=%s", name, val) == 2) { +``` **Rule name:** buffer/sscanf **Rule short description:** The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20).""" self.assertEqual(description, finding.description) @@ -448,7 +462,9 @@ def test_flawfinder_interfacev2(self): self.assertEqual("High", finding.severity) description = """**Result message:** random/setstate:This function is not sufficiently random for security-related functions such as key and nonce creation (CWE-327). **Snippet:** -``` is.setstate(std::ios::failbit);``` +``` + is.setstate(std::ios::failbit); +``` **Rule name:** random/setstate **Rule short description:** This function is not sufficiently random for security-related functions such as key and nonce creation (CWE-327).""" self.assertEqual(description, finding.description) @@ -466,7 +482,9 @@ def test_flawfinder_interfacev2(self): self.assertEqual("Info", finding.severity) description = """**Result message:** buffer/memcpy:Does not check for buffer overflows when copying to destination (CWE-120). **Snippet:** -``` std::memcpy(dptr, dmlc::BeginPtr(buffer_) + buffer_ptr_, size);``` +``` + std::memcpy(dptr, dmlc::BeginPtr(buffer_) + buffer_ptr_, size); +``` **Rule name:** buffer/memcpy **Rule short description:** Does not check for buffer overflows when copying to destination (CWE-120).""" self.assertEqual(description, finding.description) @@ -484,7 +502,9 @@ def test_flawfinder_interfacev2(self): self.assertEqual("High", finding.severity) description = """**Result message:** buffer/sscanf:The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20). **Snippet:** -``` if (sscanf(argv[i], "%[^=]=%s", name, val) == 2) {``` +``` + if (sscanf(argv[i], "%[^=]=%s", name, val) == 2) { +``` **Rule name:** buffer/sscanf **Rule short description:** The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20).""" self.assertEqual(description, finding.description) @@ -521,10 +541,12 @@ def test_codeql_snippet_report(self): description = """**Result message:** Keyword argument 'request' is not a supported parameter name of [function create](1). **Snippet:** ``` + response = make_response(redirect('/')) response = libsession.create(request=request, response=response, username=username) return response + ``` **Rule name:** py/call/wrong-named-argument **Rule short description:** Wrong name for an argument in a call From ea7102d037371c0a29cf196382cd197a8167b375 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 14:19:44 -0500 Subject: [PATCH 112/138] Bump boto3 from 1.34.94 to 1.34.95 (#10079) Bumps [boto3](https://github.com/boto/boto3) from 1.34.94 to 1.34.95. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.34.94...1.34.95) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 48b63397ff..301577114f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -75,7 +75,7 @@ django-ratelimit==4.1.0 argon2-cffi==23.1.0 blackduck==1.1.3 pycurl==7.45.3 # Required for Celery Broker AWS (SQS) support -boto3==1.34.94 # Required for Celery Broker AWS (SQS) support +boto3==1.34.95 # Required for Celery Broker AWS (SQS) support netaddr==1.2.1 vulners==2.1.5 fontawesomefree==6.5.1 From 8768cd56551904b60d2bcfcd4aedd59a13686582 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 14:28:27 -0500 Subject: [PATCH 113/138] Bump drf-spectacular-sidecar from 2024.4.1 to 2024.5.1 (#10080) Bumps [drf-spectacular-sidecar](https://github.com/tfranzel/drf-spectacular-sidecar) from 2024.4.1 to 2024.5.1. - [Commits](https://github.com/tfranzel/drf-spectacular-sidecar/compare/2024.4.1...2024.5.1) --- updated-dependencies: - dependency-name: drf-spectacular-sidecar dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 301577114f..41a4d946cc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -70,7 +70,7 @@ hyperlink==21.0.0 django-test-migrations==1.3.0 djangosaml2==1.9.2 drf-spectacular==0.27.2 -drf-spectacular-sidecar==2024.4.1 +drf-spectacular-sidecar==2024.5.1 django-ratelimit==4.1.0 argon2-cffi==23.1.0 blackduck==1.1.3 From 4d2e94a1c585ff810f89dc4f1919ac62b254aff8 Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Thu, 2 May 2024 05:19:10 +0200 Subject: [PATCH 114/138] Update Release Notes for 2.34.0 (#10077) * Update Release Notes for 2.34.0 * udpate --- docs/content/en/getting_started/upgrading/2.34.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/content/en/getting_started/upgrading/2.34.md b/docs/content/en/getting_started/upgrading/2.34.md index 7b0f7d266f..1a35861ed1 100644 --- a/docs/content/en/getting_started/upgrading/2.34.md +++ b/docs/content/en/getting_started/upgrading/2.34.md @@ -2,6 +2,11 @@ title: 'Upgrading to DefectDojo Version 2.34.x' toc_hide: true weight: -20240402 -description: No special instructions. +description: Breaking Change for AWS_Scout2. --- -There are no special instructions for upgrading to 2.34.x. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.34.0) for the contents of the release. + +**Breaking Change** + + - AWS_Scout2 has been removed. This parser was already disactivated by default in releases >= 2.3.1. and has been replaced with ScoutSuite (https://github.com/nccgroup/ScoutSuite) upstream. Please switch to ScoutSuite now if you haven't done it yet. + +For all other changes, check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.34.0) for the contents of the release. \ No newline at end of file From a1bf40f12329a0aa86c8f6c785170465f28e48cb Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Thu, 2 May 2024 05:20:36 +0200 Subject: [PATCH 115/138] :sparkles: implement yarn2 parser (#9985) * :sparkles: implement yarn2 parser * fix bug * Update dojo/tools/yarn_audit/parser.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * thank you for the review @cneill * fix ruff --------- Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> --- dojo/tools/yarn_audit/parser.py | 37 +++++++++++++++++++ .../yarn_audit/yarn2_audit_issue9911.json | 4 ++ .../yarn_audit/yarn_audit_multiple_cwes.json | 22 +++++------ unittests/tools/test_yarn_audit_parser.py | 10 +++++ 4 files changed, 62 insertions(+), 11 deletions(-) create mode 100644 unittests/scans/yarn_audit/yarn2_audit_issue9911.json diff --git a/dojo/tools/yarn_audit/parser.py b/dojo/tools/yarn_audit/parser.py index 97da05a71b..ff26ba37b4 100644 --- a/dojo/tools/yarn_audit/parser.py +++ b/dojo/tools/yarn_audit/parser.py @@ -25,6 +25,10 @@ def get_findings(self, json_output, test): lines = lines.split('\n') tree = (json.loads(line) for line in lines if "{" in line) return self.get_items_yarn(tree, test) + elif '"value"' in lines: + lines = lines.split('\n') + tree = (json.loads(line) for line in lines if "{" in line) + return self.get_items_yarn2(tree, test) else: tree = json.loads(lines) return self.get_items_auditci(tree, test) @@ -43,6 +47,39 @@ def get_items_yarn(self, tree, test): raise ValueError(msg, error) return list(items.values()) + def get_items_yarn2(self, tree, test): + items = [] + for element in tree: + value = element.get("value", None) + child = element.get("children") + description = "" + childid = child.get("ID") + childissue = child.get("Issue") + childseverity = child.get("Severity") + child_vuln_version = child.get("Vulnerable Versions") + child_tree_versions = ', '.join(set(child.get("Tree Versions"))) + child_dependents = ', '.join(set(child.get("Dependents"))) + description += childissue + "\n" + description += "**Vulnerable Versions:** " + child_vuln_version + "\n" + description += "**Dependents:** " + child_dependents + "\n" + dojo_finding = Finding( + title=str(childid), + test=test, + severity=self.severitytranslator(severity=childseverity), + description=description, + component_version=str(child_tree_versions), + false_p=False, + duplicate=False, + out_of_scope=False, + mitigated=None, + static_finding=True, + dynamic_finding=False, + ) + items.append(dojo_finding) + if value is not None: + dojo_finding.component_name = value + return items + def get_items_auditci(self, tree, test): # https://github.com/DefectDojo/django-DefectDojo/issues/6495 items = [] for element in tree.get("advisories"): diff --git a/unittests/scans/yarn_audit/yarn2_audit_issue9911.json b/unittests/scans/yarn_audit/yarn2_audit_issue9911.json new file mode 100644 index 0000000000..7963bbcfdd --- /dev/null +++ b/unittests/scans/yarn_audit/yarn2_audit_issue9911.json @@ -0,0 +1,4 @@ +{"value":"@babel/plugin-proposal-class-properties","children":{"ID":"@babel/plugin-proposal-class-properties (deprecation)","Issue":"This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.","Severity":"moderate","Vulnerable Versions":"7.18.6","Tree Versions":["7.18.6"],"Dependents":["jscodeshift@virtual:95986a29f66ea5c154da709639e46d9f25ab769cdc542a6076b371e193f79e407bbee37bc9d3845bfa503bd700408966c85b5a74356facf4da9a113fd4ce89d9#npm:0.14.0"]}} +{"value":"@babel/plugin-proposal-nullish-coalescing-operator","children":{"ID":"@babel/plugin-proposal-nullish-coalescing-operator (deprecation)","Issue":"This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.","Severity":"moderate","Vulnerable Versions":"7.18.6","Tree Versions":["7.18.6"],"Dependents":["jscodeshift@virtual:95986a29f66ea5c154da709639e46d9f25ab769cdc542a6076b371e193f79e407bbee37bc9d3845bfa503bd700408966c85b5a74356facf4da9a113fd4ce89d9#npm:0.14.0"]}} +{"value":"@babel/plugin-proposal-optional-chaining","children":{"ID":"@babel/plugin-proposal-optional-chaining (deprecation)","Issue":"This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.","Severity":"moderate","Vulnerable Versions":"7.21.0","Tree Versions":["7.21.0"],"Dependents":["jscodeshift@virtual:95986a29f66ea5c154da709639e46d9f25ab769cdc542a6076b371e193f79e407bbee37bc9d3845bfa503bd700408966c85b5a74356facf4da9a113fd4ce89d9#npm:0.14.0"]}} +{"value":"transformers","children":{"ID":1096536,"Issue":"Transformers Deserialization of Untrusted Data vulnerability","URL":"https://github.com/advisories/GHSA-37q5-v5qm-c9v8","Severity":"low","Vulnerable Versions":"< 4.38.0","Tree Versions":["4.38"],"Dependents":["test@npm:1.13.0"]}} \ No newline at end of file diff --git a/unittests/scans/yarn_audit/yarn_audit_multiple_cwes.json b/unittests/scans/yarn_audit/yarn_audit_multiple_cwes.json index ae94444f8c..6670b66991 100644 --- a/unittests/scans/yarn_audit/yarn_audit_multiple_cwes.json +++ b/unittests/scans/yarn_audit/yarn_audit_multiple_cwes.json @@ -1,12 +1,12 @@ {"type":"auditAdvisory","data":{"resolution":{"id":1028248,"path":"react-native-svg>css-select>nth-check","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"1.0.2","paths":["react-native-svg>css-select>nth-check"]}],"metadata":null,"vulnerable_versions":"<2.0.1","module_name":"nth-check","severity":"moderate","github_advisory_id":"GHSA-rp65-9cf3-cjxr","cves":["CVE-2021-3803"],"access":"public","patched_versions":">=2.0.1","cvss":{"score":7.5,"vectorString":"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"},"updated":"2021-09-20T20:15:09.000Z","recommendation":"Upgrade to version 2.0.1 or later","cwe":"[\"CWE-1333\"]","found_by":null,"deleted":null,"id":1028248,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-3803\n- https://github.com/fb55/nth-check/commit/9894c1d2010870c351f66c6f6efcf656e26bb726\n- https://huntr.dev/bounties/8cf8cc06-d2cf-4b4e-b42c-99fafb0b04d0\n- https://github.com/advisories/GHSA-rp65-9cf3-cjxr","created":"2022-03-06T16:00:42.621Z","reported_by":null,"title":"Inefficient Regular Expression Complexity in nth-check","npm_advisory_id":null,"overview":"nth-check is vulnerable to Inefficient Regular Expression Complexity","url":"https://github.com/advisories/GHSA-rp65-9cf3-cjxr"}}} - {"type":"auditAdvisory","data":{"resolution":{"id":1028029,"path":"react-native>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.6.5","paths":["react-native>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-tools>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch"]},{"version":"2.6.5","paths":["react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro-config>metro>node-fetch"]}],"metadata":null,"vulnerable_versions":"<2.6.7","module_name":"node-fetch","severity":"high","github_advisory_id":"GHSA-r683-j2x4-v87g","cves":["CVE-2022-0235"],"access":"public","patched_versions":">=2.6.7","cvss":{"score":8.8,"vectorString":"CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"},"updated":"2022-01-23T01:52:43.000Z","recommendation":"Upgrade to version 2.6.7 or later","cwe":"[\"CWE-173\",\"CWE-200\",\"CWE-601\"]","found_by":null,"deleted":null,"id":1028029,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2022-0235\n- https://github.com/node-fetch/node-fetch/commit/36e47e8a6406185921e4985dcbeff140d73eaa10\n- https://huntr.dev/bounties/d26ab655-38d6-48b3-be15-f9ad6b6ae6f7\n- https://github.com/node-fetch/node-fetch/pull/1453\n- https://github.com/advisories/GHSA-r683-j2x4-v87g","created":"2022-03-06T16:00:42.588Z","reported_by":null,"title":"node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor","npm_advisory_id":null,"overview":"node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor","url":"https://github.com/advisories/GHSA-r683-j2x4-v87g"}}} - {"type":"auditAdvisory","data":{"resolution":{"id":1028029,"path":"react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-tools>node-fetch","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.6.5","paths":["react-native>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-tools>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch"]},{"version":"2.6.5","paths":["react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro-config>metro>node-fetch"]}],"metadata":null,"vulnerable_versions":"<2.6.7","module_name":"node-fetch","severity":"high","github_advisory_id":"GHSA-r683-j2x4-v87g","cves":["CVE-2022-0235"],"access":"public","patched_versions":">=2.6.7","cvss":{"score":8.8,"vectorString":"CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"},"updated":"2022-01-23T01:52:43.000Z","recommendation":"Upgrade to version 2.6.7 or later","cwe":"[\"CWE-173\",\"CWE-200\",\"CWE-601\"]","found_by":null,"deleted":null,"id":1028029,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2022-0235\n- https://github.com/node-fetch/node-fetch/commit/36e47e8a6406185921e4985dcbeff140d73eaa10\n- https://huntr.dev/bounties/d26ab655-38d6-48b3-be15-f9ad6b6ae6f7\n- https://github.com/node-fetch/node-fetch/pull/1453\n- https://github.com/advisories/GHSA-r683-j2x4-v87g","created":"2022-03-06T16:00:42.588Z","reported_by":null,"title":"node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor","npm_advisory_id":null,"overview":"node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor","url":"https://github.com/advisories/GHSA-r683-j2x4-v87g"}}} - {"type":"auditAdvisory","data":{"resolution":{"id":1028029,"path":"react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.6.5","paths":["react-native>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-tools>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch"]},{"version":"2.6.5","paths":["react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro-config>metro>node-fetch"]}],"metadata":null,"vulnerable_versions":"<2.6.7","module_name":"node-fetch","severity":"high","github_advisory_id":"GHSA-r683-j2x4-v87g","cves":["CVE-2022-0235"],"access":"public","patched_versions":">=2.6.7","cvss":{"score":8.8,"vectorString":"CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"},"updated":"2022-01-23T01:52:43.000Z","recommendation":"Upgrade to version 2.6.7 or later","cwe":"[\"CWE-173\",\"CWE-200\",\"CWE-601\"]","found_by":null,"deleted":null,"id":1028029,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2022-0235\n- https://github.com/node-fetch/node-fetch/commit/36e47e8a6406185921e4985dcbeff140d73eaa10\n- https://huntr.dev/bounties/d26ab655-38d6-48b3-be15-f9ad6b6ae6f7\n- https://github.com/node-fetch/node-fetch/pull/1453\n- https://github.com/advisories/GHSA-r683-j2x4-v87g","created":"2022-03-06T16:00:42.588Z","reported_by":null,"title":"node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor","npm_advisory_id":null,"overview":"node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor","url":"https://github.com/advisories/GHSA-r683-j2x4-v87g"}}} - {"type":"auditAdvisory","data":{"resolution":{"id":1028029,"path":"react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro>node-fetch","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.6.5","paths":["react-native>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-tools>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch"]},{"version":"2.6.5","paths":["react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro-config>metro>node-fetch"]}],"metadata":null,"vulnerable_versions":"<2.6.7","module_name":"node-fetch","severity":"high","github_advisory_id":"GHSA-r683-j2x4-v87g","cves":["CVE-2022-0235"],"access":"public","patched_versions":">=2.6.7","cvss":{"score":8.8,"vectorString":"CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"},"updated":"2022-01-23T01:52:43.000Z","recommendation":"Upgrade to version 2.6.7 or later","cwe":"[\"CWE-173\",\"CWE-200\",\"CWE-601\"]","found_by":null,"deleted":null,"id":1028029,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2022-0235\n- https://github.com/node-fetch/node-fetch/commit/36e47e8a6406185921e4985dcbeff140d73eaa10\n- https://huntr.dev/bounties/d26ab655-38d6-48b3-be15-f9ad6b6ae6f7\n- https://github.com/node-fetch/node-fetch/pull/1453\n- https://github.com/advisories/GHSA-r683-j2x4-v87g","created":"2022-03-06T16:00:42.588Z","reported_by":null,"title":"node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor","npm_advisory_id":null,"overview":"node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor","url":"https://github.com/advisories/GHSA-r683-j2x4-v87g"}}} - {"type":"auditAdvisory","data":{"resolution":{"id":1028029,"path":"react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro-config>metro>node-fetch","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.6.5","paths":["react-native>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-tools>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch"]},{"version":"2.6.5","paths":["react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro-config>metro>node-fetch"]}],"metadata":null,"vulnerable_versions":"<2.6.7","module_name":"node-fetch","severity":"high","github_advisory_id":"GHSA-r683-j2x4-v87g","cves":["CVE-2022-0235"],"access":"public","patched_versions":">=2.6.7","cvss":{"score":8.8,"vectorString":"CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"},"updated":"2022-01-23T01:52:43.000Z","recommendation":"Upgrade to version 2.6.7 or later","cwe":"[\"CWE-173\",\"CWE-200\",\"CWE-601\"]","found_by":null,"deleted":null,"id":1028029,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2022-0235\n- https://github.com/node-fetch/node-fetch/commit/36e47e8a6406185921e4985dcbeff140d73eaa10\n- https://huntr.dev/bounties/d26ab655-38d6-48b3-be15-f9ad6b6ae6f7\n- https://github.com/node-fetch/node-fetch/pull/1453\n- https://github.com/advisories/GHSA-r683-j2x4-v87g","created":"2022-03-06T16:00:42.588Z","reported_by":null,"title":"node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor","npm_advisory_id":null,"overview":"node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor","url":"https://github.com/advisories/GHSA-r683-j2x4-v87g"}}} - {"type":"auditAdvisory","data":{"resolution":{"id":1028226,"path":"react-native>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"4.1.0","paths":["react-native>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-native>@react-native-community/cli>ora>strip-ansi>ansi-regex","react-native>@react-native-community/cli>@react-native-community/cli-types>ora>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-native>@react-native-community/cli>strip-ansi>ansi-regex"]}],"metadata":null,"vulnerable_versions":">2.1.1 <5.0.1","module_name":"ansi-regex","severity":"moderate","github_advisory_id":"GHSA-93q8-gq69-wqmw","cves":["CVE-2021-3807"],"access":"public","patched_versions":">=5.0.1","cvss":{"score":7.5,"vectorString":"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"},"updated":"2021-09-23T15:45:50.000Z","recommendation":"Upgrade to version 5.0.1 or later","cwe":"[\"CWE-918\",\"CWE-1333\"]","found_by":null,"deleted":null,"id":1028226,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-3807\n- https://github.com/chalk/ansi-regex/commit/8d1d7cdb586269882c4bdc1b7325d0c58c8f76f9\n- https://huntr.dev/bounties/5b3cf33b-ede0-4398-9974-800876dfd994\n- https://github.com/chalk/ansi-regex/issues/38#issuecomment-924086311\n- https://app.snyk.io/vuln/SNYK-JS-ANSIREGEX-1583908\n- https://github.com/chalk/ansi-regex/issues/38#issuecomment-925924774\n- https://github.com/advisories/GHSA-93q8-gq69-wqmw","created":"2022-03-06T16:00:42.619Z","reported_by":null,"title":" Inefficient Regular Expression Complexity in chalk/ansi-regex","npm_advisory_id":null,"overview":"ansi-regex is vulnerable to Inefficient Regular Expression Complexity","url":"https://github.com/advisories/GHSA-93q8-gq69-wqmw"}}} - {"type":"auditAdvisory","data":{"resolution":{"id":1028226,"path":"react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"4.1.0","paths":["react-native>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-native>@react-native-community/cli>ora>strip-ansi>ansi-regex","react-native>@react-native-community/cli>@react-native-community/cli-types>ora>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-native>@react-native-community/cli>strip-ansi>ansi-regex"]}],"metadata":null,"vulnerable_versions":">2.1.1 <5.0.1","module_name":"ansi-regex","severity":"moderate","github_advisory_id":"GHSA-93q8-gq69-wqmw","cves":["CVE-2021-3807"],"access":"public","patched_versions":">=5.0.1","cvss":{"score":7.5,"vectorString":"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"},"updated":"2021-09-23T15:45:50.000Z","recommendation":"Upgrade to version 5.0.1 or later","cwe":"[\"CWE-918\",\"CWE-1333\"]","found_by":null,"deleted":null,"id":1028226,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-3807\n- https://github.com/chalk/ansi-regex/commit/8d1d7cdb586269882c4bdc1b7325d0c58c8f76f9\n- https://huntr.dev/bounties/5b3cf33b-ede0-4398-9974-800876dfd994\n- https://github.com/chalk/ansi-regex/issues/38#issuecomment-924086311\n- https://app.snyk.io/vuln/SNYK-JS-ANSIREGEX-1583908\n- https://github.com/chalk/ansi-regex/issues/38#issuecomment-925924774\n- https://github.com/advisories/GHSA-93q8-gq69-wqmw","created":"2022-03-06T16:00:42.619Z","reported_by":null,"title":" Inefficient Regular Expression Complexity in chalk/ansi-regex","npm_advisory_id":null,"overview":"ansi-regex is vulnerable to Inefficient Regular Expression Complexity","url":"https://github.com/advisories/GHSA-93q8-gq69-wqmw"}}} - {"type":"auditAdvisory","data":{"resolution":{"id":1028226,"path":"react-native>@react-native-community/cli>ora>strip-ansi>ansi-regex","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"4.1.0","paths":["react-native>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-native>@react-native-community/cli>ora>strip-ansi>ansi-regex","react-native>@react-native-community/cli>@react-native-community/cli-types>ora>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-native>@react-native-community/cli>strip-ansi>ansi-regex"]}],"metadata":null,"vulnerable_versions":">2.1.1 <5.0.1","module_name":"ansi-regex","severity":"moderate","github_advisory_id":"GHSA-93q8-gq69-wqmw","cves":["CVE-2021-3807"],"access":"public","patched_versions":">=5.0.1","cvss":{"score":7.5,"vectorString":"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"},"updated":"2021-09-23T15:45:50.000Z","recommendation":"Upgrade to version 5.0.1 or later","cwe":"[\"CWE-918\",\"CWE-1333\"]","found_by":null,"deleted":null,"id":1028226,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-3807\n- https://github.com/chalk/ansi-regex/commit/8d1d7cdb586269882c4bdc1b7325d0c58c8f76f9\n- https://huntr.dev/bounties/5b3cf33b-ede0-4398-9974-800876dfd994\n- https://github.com/chalk/ansi-regex/issues/38#issuecomment-924086311\n- https://app.snyk.io/vuln/SNYK-JS-ANSIREGEX-1583908\n- https://github.com/chalk/ansi-regex/issues/38#issuecomment-925924774\n- https://github.com/advisories/GHSA-93q8-gq69-wqmw","created":"2022-03-06T16:00:42.619Z","reported_by":null,"title":" Inefficient Regular Expression Complexity in chalk/ansi-regex","npm_advisory_id":null,"overview":"ansi-regex is vulnerable to Inefficient Regular Expression Complexity","url":"https://github.com/advisories/GHSA-93q8-gq69-wqmw"}}} - {"type":"auditAdvisory","data":{"resolution":{"id":1028226,"path":"react-native>@react-native-community/cli>@react-native-community/cli-types>ora>strip-ansi>ansi-regex","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"4.1.0","paths":["react-native>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-native>@react-native-community/cli>ora>strip-ansi>ansi-regex","react-native>@react-native-community/cli>@react-native-community/cli-types>ora>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-native>@react-native-community/cli>strip-ansi>ansi-regex"]}],"metadata":null,"vulnerable_versions":">2.1.1 <5.0.1","module_name":"ansi-regex","severity":"moderate","github_advisory_id":"GHSA-93q8-gq69-wqmw","cves":["CVE-2021-3807"],"access":"public","patched_versions":">=5.0.1","cvss":{"score":7.5,"vectorString":"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"},"updated":"2021-09-23T15:45:50.000Z","recommendation":"Upgrade to version 5.0.1 or later","cwe":"[\"CWE-918\",\"CWE-1333\"]","found_by":null,"deleted":null,"id":1028226,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-3807\n- https://github.com/chalk/ansi-regex/commit/8d1d7cdb586269882c4bdc1b7325d0c58c8f76f9\n- https://huntr.dev/bounties/5b3cf33b-ede0-4398-9974-800876dfd994\n- https://github.com/chalk/ansi-regex/issues/38#issuecomment-924086311\n- https://app.snyk.io/vuln/SNYK-JS-ANSIREGEX-1583908\n- https://github.com/chalk/ansi-regex/issues/38#issuecomment-925924774\n- https://github.com/advisories/GHSA-93q8-gq69-wqmw","created":"2022-03-06T16:00:42.619Z","reported_by":null,"title":" Inefficient Regular Expression Complexity in chalk/ansi-regex","npm_advisory_id":null,"overview":"ansi-regex is vulnerable to Inefficient Regular Expression Complexity","url":"https://github.com/advisories/GHSA-93q8-gq69-wqmw"}}} - {"type":"auditAdvisory","data":{"resolution":{"id":1028226,"path":"react-native>@react-native-community/cli>strip-ansi>ansi-regex","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"4.1.0","paths":["react-native>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-native>@react-native-community/cli>ora>strip-ansi>ansi-regex","react-native>@react-native-community/cli>@react-native-community/cli-types>ora>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-native>@react-native-community/cli>strip-ansi>ansi-regex"]}],"metadata":null,"vulnerable_versions":">2.1.1 <5.0.1","module_name":"ansi-regex","severity":"moderate","github_advisory_id":"GHSA-93q8-gq69-wqmw","cves":["CVE-2021-3807"],"access":"public","patched_versions":">=5.0.1","cvss":{"score":7.5,"vectorString":"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"},"updated":"2021-09-23T15:45:50.000Z","recommendation":"Upgrade to version 5.0.1 or later","cwe":"[]","found_by":null,"deleted":null,"id":1028226,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-3807\n- https://github.com/chalk/ansi-regex/commit/8d1d7cdb586269882c4bdc1b7325d0c58c8f76f9\n- https://huntr.dev/bounties/5b3cf33b-ede0-4398-9974-800876dfd994\n- https://github.com/chalk/ansi-regex/issues/38#issuecomment-924086311\n- https://app.snyk.io/vuln/SNYK-JS-ANSIREGEX-1583908\n- https://github.com/chalk/ansi-regex/issues/38#issuecomment-925924774\n- https://github.com/advisories/GHSA-93q8-gq69-wqmw","created":"2022-03-06T16:00:42.619Z","reported_by":null,"title":" Inefficient Regular Expression Complexity in chalk/ansi-regex","npm_advisory_id":null,"overview":"ansi-regex is vulnerable to Inefficient Regular Expression Complexity","url":"https://github.com/advisories/GHSA-93q8-gq69-wqmw"}}} - {"type":"auditSummary","data":{"vulnerabilities":{"info":0,"low":0,"moderate":6,"high":5,"critical":0},"dependencies":923,"devDependencies":0,"optionalDependencies":0,"totalDependencies":923}} \ No newline at end of file +{"type":"auditAdvisory","data":{"resolution":{"id":1028029,"path":"react-native>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.6.5","paths":["react-native>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-tools>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch"]},{"version":"2.6.5","paths":["react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro-config>metro>node-fetch"]}],"metadata":null,"vulnerable_versions":"<2.6.7","module_name":"node-fetch","severity":"high","github_advisory_id":"GHSA-r683-j2x4-v87g","cves":["CVE-2022-0235"],"access":"public","patched_versions":">=2.6.7","cvss":{"score":8.8,"vectorString":"CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"},"updated":"2022-01-23T01:52:43.000Z","recommendation":"Upgrade to version 2.6.7 or later","cwe":"[\"CWE-173\",\"CWE-200\",\"CWE-601\"]","found_by":null,"deleted":null,"id":1028029,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2022-0235\n- https://github.com/node-fetch/node-fetch/commit/36e47e8a6406185921e4985dcbeff140d73eaa10\n- https://huntr.dev/bounties/d26ab655-38d6-48b3-be15-f9ad6b6ae6f7\n- https://github.com/node-fetch/node-fetch/pull/1453\n- https://github.com/advisories/GHSA-r683-j2x4-v87g","created":"2022-03-06T16:00:42.588Z","reported_by":null,"title":"node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor","npm_advisory_id":null,"overview":"node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor","url":"https://github.com/advisories/GHSA-r683-j2x4-v87g"}}} +{"type":"auditAdvisory","data":{"resolution":{"id":1028029,"path":"react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-tools>node-fetch","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.6.5","paths":["react-native>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-tools>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch"]},{"version":"2.6.5","paths":["react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro-config>metro>node-fetch"]}],"metadata":null,"vulnerable_versions":"<2.6.7","module_name":"node-fetch","severity":"high","github_advisory_id":"GHSA-r683-j2x4-v87g","cves":["CVE-2022-0235"],"access":"public","patched_versions":">=2.6.7","cvss":{"score":8.8,"vectorString":"CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"},"updated":"2022-01-23T01:52:43.000Z","recommendation":"Upgrade to version 2.6.7 or later","cwe":"[\"CWE-173\",\"CWE-200\",\"CWE-601\"]","found_by":null,"deleted":null,"id":1028029,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2022-0235\n- https://github.com/node-fetch/node-fetch/commit/36e47e8a6406185921e4985dcbeff140d73eaa10\n- https://huntr.dev/bounties/d26ab655-38d6-48b3-be15-f9ad6b6ae6f7\n- https://github.com/node-fetch/node-fetch/pull/1453\n- https://github.com/advisories/GHSA-r683-j2x4-v87g","created":"2022-03-06T16:00:42.588Z","reported_by":null,"title":"node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor","npm_advisory_id":null,"overview":"node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor","url":"https://github.com/advisories/GHSA-r683-j2x4-v87g"}}} +{"type":"auditAdvisory","data":{"resolution":{"id":1028029,"path":"react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.6.5","paths":["react-native>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-tools>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch"]},{"version":"2.6.5","paths":["react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro-config>metro>node-fetch"]}],"metadata":null,"vulnerable_versions":"<2.6.7","module_name":"node-fetch","severity":"high","github_advisory_id":"GHSA-r683-j2x4-v87g","cves":["CVE-2022-0235"],"access":"public","patched_versions":">=2.6.7","cvss":{"score":8.8,"vectorString":"CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"},"updated":"2022-01-23T01:52:43.000Z","recommendation":"Upgrade to version 2.6.7 or later","cwe":"[\"CWE-173\",\"CWE-200\",\"CWE-601\"]","found_by":null,"deleted":null,"id":1028029,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2022-0235\n- https://github.com/node-fetch/node-fetch/commit/36e47e8a6406185921e4985dcbeff140d73eaa10\n- https://huntr.dev/bounties/d26ab655-38d6-48b3-be15-f9ad6b6ae6f7\n- https://github.com/node-fetch/node-fetch/pull/1453\n- https://github.com/advisories/GHSA-r683-j2x4-v87g","created":"2022-03-06T16:00:42.588Z","reported_by":null,"title":"node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor","npm_advisory_id":null,"overview":"node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor","url":"https://github.com/advisories/GHSA-r683-j2x4-v87g"}}} +{"type":"auditAdvisory","data":{"resolution":{"id":1028029,"path":"react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro>node-fetch","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.6.5","paths":["react-native>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-tools>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch"]},{"version":"2.6.5","paths":["react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro-config>metro>node-fetch"]}],"metadata":null,"vulnerable_versions":"<2.6.7","module_name":"node-fetch","severity":"high","github_advisory_id":"GHSA-r683-j2x4-v87g","cves":["CVE-2022-0235"],"access":"public","patched_versions":">=2.6.7","cvss":{"score":8.8,"vectorString":"CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"},"updated":"2022-01-23T01:52:43.000Z","recommendation":"Upgrade to version 2.6.7 or later","cwe":"[\"CWE-173\",\"CWE-200\",\"CWE-601\"]","found_by":null,"deleted":null,"id":1028029,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2022-0235\n- https://github.com/node-fetch/node-fetch/commit/36e47e8a6406185921e4985dcbeff140d73eaa10\n- https://huntr.dev/bounties/d26ab655-38d6-48b3-be15-f9ad6b6ae6f7\n- https://github.com/node-fetch/node-fetch/pull/1453\n- https://github.com/advisories/GHSA-r683-j2x4-v87g","created":"2022-03-06T16:00:42.588Z","reported_by":null,"title":"node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor","npm_advisory_id":null,"overview":"node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor","url":"https://github.com/advisories/GHSA-r683-j2x4-v87g"}}} +{"type":"auditAdvisory","data":{"resolution":{"id":1028029,"path":"react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro-config>metro>node-fetch","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.6.5","paths":["react-native>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-tools>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>@react-native-community/cli-tools>node-fetch"]},{"version":"2.6.5","paths":["react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro>node-fetch","react-native>@react-native-community/cli>@react-native-community/cli-plugin-metro>metro-config>metro>node-fetch"]}],"metadata":null,"vulnerable_versions":"<2.6.7","module_name":"node-fetch","severity":"high","github_advisory_id":"GHSA-r683-j2x4-v87g","cves":["CVE-2022-0235"],"access":"public","patched_versions":">=2.6.7","cvss":{"score":8.8,"vectorString":"CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"},"updated":"2022-01-23T01:52:43.000Z","recommendation":"Upgrade to version 2.6.7 or later","cwe":"[\"CWE-173\",\"CWE-200\",\"CWE-601\"]","found_by":null,"deleted":null,"id":1028029,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2022-0235\n- https://github.com/node-fetch/node-fetch/commit/36e47e8a6406185921e4985dcbeff140d73eaa10\n- https://huntr.dev/bounties/d26ab655-38d6-48b3-be15-f9ad6b6ae6f7\n- https://github.com/node-fetch/node-fetch/pull/1453\n- https://github.com/advisories/GHSA-r683-j2x4-v87g","created":"2022-03-06T16:00:42.588Z","reported_by":null,"title":"node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor","npm_advisory_id":null,"overview":"node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor","url":"https://github.com/advisories/GHSA-r683-j2x4-v87g"}}} +{"type":"auditAdvisory","data":{"resolution":{"id":1028226,"path":"react-native>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"4.1.0","paths":["react-native>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-native>@react-native-community/cli>ora>strip-ansi>ansi-regex","react-native>@react-native-community/cli>@react-native-community/cli-types>ora>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-native>@react-native-community/cli>strip-ansi>ansi-regex"]}],"metadata":null,"vulnerable_versions":">2.1.1 <5.0.1","module_name":"ansi-regex","severity":"moderate","github_advisory_id":"GHSA-93q8-gq69-wqmw","cves":["CVE-2021-3807"],"access":"public","patched_versions":">=5.0.1","cvss":{"score":7.5,"vectorString":"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"},"updated":"2021-09-23T15:45:50.000Z","recommendation":"Upgrade to version 5.0.1 or later","cwe":"[\"CWE-918\",\"CWE-1333\"]","found_by":null,"deleted":null,"id":1028226,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-3807\n- https://github.com/chalk/ansi-regex/commit/8d1d7cdb586269882c4bdc1b7325d0c58c8f76f9\n- https://huntr.dev/bounties/5b3cf33b-ede0-4398-9974-800876dfd994\n- https://github.com/chalk/ansi-regex/issues/38#issuecomment-924086311\n- https://app.snyk.io/vuln/SNYK-JS-ANSIREGEX-1583908\n- https://github.com/chalk/ansi-regex/issues/38#issuecomment-925924774\n- https://github.com/advisories/GHSA-93q8-gq69-wqmw","created":"2022-03-06T16:00:42.619Z","reported_by":null,"title":" Inefficient Regular Expression Complexity in chalk/ansi-regex","npm_advisory_id":null,"overview":"ansi-regex is vulnerable to Inefficient Regular Expression Complexity","url":"https://github.com/advisories/GHSA-93q8-gq69-wqmw"}}} +{"type":"auditAdvisory","data":{"resolution":{"id":1028226,"path":"react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"4.1.0","paths":["react-native>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-native>@react-native-community/cli>ora>strip-ansi>ansi-regex","react-native>@react-native-community/cli>@react-native-community/cli-types>ora>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-native>@react-native-community/cli>strip-ansi>ansi-regex"]}],"metadata":null,"vulnerable_versions":">2.1.1 <5.0.1","module_name":"ansi-regex","severity":"moderate","github_advisory_id":"GHSA-93q8-gq69-wqmw","cves":["CVE-2021-3807"],"access":"public","patched_versions":">=5.0.1","cvss":{"score":7.5,"vectorString":"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"},"updated":"2021-09-23T15:45:50.000Z","recommendation":"Upgrade to version 5.0.1 or later","cwe":"[\"CWE-918\",\"CWE-1333\"]","found_by":null,"deleted":null,"id":1028226,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-3807\n- https://github.com/chalk/ansi-regex/commit/8d1d7cdb586269882c4bdc1b7325d0c58c8f76f9\n- https://huntr.dev/bounties/5b3cf33b-ede0-4398-9974-800876dfd994\n- https://github.com/chalk/ansi-regex/issues/38#issuecomment-924086311\n- https://app.snyk.io/vuln/SNYK-JS-ANSIREGEX-1583908\n- https://github.com/chalk/ansi-regex/issues/38#issuecomment-925924774\n- https://github.com/advisories/GHSA-93q8-gq69-wqmw","created":"2022-03-06T16:00:42.619Z","reported_by":null,"title":" Inefficient Regular Expression Complexity in chalk/ansi-regex","npm_advisory_id":null,"overview":"ansi-regex is vulnerable to Inefficient Regular Expression Complexity","url":"https://github.com/advisories/GHSA-93q8-gq69-wqmw"}}} +{"type":"auditAdvisory","data":{"resolution":{"id":1028226,"path":"react-native>@react-native-community/cli>ora>strip-ansi>ansi-regex","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"4.1.0","paths":["react-native>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-native>@react-native-community/cli>ora>strip-ansi>ansi-regex","react-native>@react-native-community/cli>@react-native-community/cli-types>ora>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-native>@react-native-community/cli>strip-ansi>ansi-regex"]}],"metadata":null,"vulnerable_versions":">2.1.1 <5.0.1","module_name":"ansi-regex","severity":"moderate","github_advisory_id":"GHSA-93q8-gq69-wqmw","cves":["CVE-2021-3807"],"access":"public","patched_versions":">=5.0.1","cvss":{"score":7.5,"vectorString":"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"},"updated":"2021-09-23T15:45:50.000Z","recommendation":"Upgrade to version 5.0.1 or later","cwe":"[\"CWE-918\",\"CWE-1333\"]","found_by":null,"deleted":null,"id":1028226,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-3807\n- https://github.com/chalk/ansi-regex/commit/8d1d7cdb586269882c4bdc1b7325d0c58c8f76f9\n- https://huntr.dev/bounties/5b3cf33b-ede0-4398-9974-800876dfd994\n- https://github.com/chalk/ansi-regex/issues/38#issuecomment-924086311\n- https://app.snyk.io/vuln/SNYK-JS-ANSIREGEX-1583908\n- https://github.com/chalk/ansi-regex/issues/38#issuecomment-925924774\n- https://github.com/advisories/GHSA-93q8-gq69-wqmw","created":"2022-03-06T16:00:42.619Z","reported_by":null,"title":" Inefficient Regular Expression Complexity in chalk/ansi-regex","npm_advisory_id":null,"overview":"ansi-regex is vulnerable to Inefficient Regular Expression Complexity","url":"https://github.com/advisories/GHSA-93q8-gq69-wqmw"}}} +{"type":"auditAdvisory","data":{"resolution":{"id":1028226,"path":"react-native>@react-native-community/cli>@react-native-community/cli-types>ora>strip-ansi>ansi-regex","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"4.1.0","paths":["react-native>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-native>@react-native-community/cli>ora>strip-ansi>ansi-regex","react-native>@react-native-community/cli>@react-native-community/cli-types>ora>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-native>@react-native-community/cli>strip-ansi>ansi-regex"]}],"metadata":null,"vulnerable_versions":">2.1.1 <5.0.1","module_name":"ansi-regex","severity":"moderate","github_advisory_id":"GHSA-93q8-gq69-wqmw","cves":["CVE-2021-3807"],"access":"public","patched_versions":">=5.0.1","cvss":{"score":7.5,"vectorString":"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"},"updated":"2021-09-23T15:45:50.000Z","recommendation":"Upgrade to version 5.0.1 or later","cwe":"[\"CWE-918\",\"CWE-1333\"]","found_by":null,"deleted":null,"id":1028226,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-3807\n- https://github.com/chalk/ansi-regex/commit/8d1d7cdb586269882c4bdc1b7325d0c58c8f76f9\n- https://huntr.dev/bounties/5b3cf33b-ede0-4398-9974-800876dfd994\n- https://github.com/chalk/ansi-regex/issues/38#issuecomment-924086311\n- https://app.snyk.io/vuln/SNYK-JS-ANSIREGEX-1583908\n- https://github.com/chalk/ansi-regex/issues/38#issuecomment-925924774\n- https://github.com/advisories/GHSA-93q8-gq69-wqmw","created":"2022-03-06T16:00:42.619Z","reported_by":null,"title":" Inefficient Regular Expression Complexity in chalk/ansi-regex","npm_advisory_id":null,"overview":"ansi-regex is vulnerable to Inefficient Regular Expression Complexity","url":"https://github.com/advisories/GHSA-93q8-gq69-wqmw"}}} +{"type":"auditAdvisory","data":{"resolution":{"id":1028226,"path":"react-native>@react-native-community/cli>strip-ansi>ansi-regex","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"4.1.0","paths":["react-native>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex","react-native>@react-native-community/cli>@react-native-community/cli-hermes>@react-native-community/cli-platform-android>logkitty>ansi-fragments>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-native>@react-native-community/cli>ora>strip-ansi>ansi-regex","react-native>@react-native-community/cli>@react-native-community/cli-types>ora>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-native>@react-native-community/cli>strip-ansi>ansi-regex"]}],"metadata":null,"vulnerable_versions":">2.1.1 <5.0.1","module_name":"ansi-regex","severity":"moderate","github_advisory_id":"GHSA-93q8-gq69-wqmw","cves":["CVE-2021-3807"],"access":"public","patched_versions":">=5.0.1","cvss":{"score":7.5,"vectorString":"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"},"updated":"2021-09-23T15:45:50.000Z","recommendation":"Upgrade to version 5.0.1 or later","cwe":"[]","found_by":null,"deleted":null,"id":1028226,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-3807\n- https://github.com/chalk/ansi-regex/commit/8d1d7cdb586269882c4bdc1b7325d0c58c8f76f9\n- https://huntr.dev/bounties/5b3cf33b-ede0-4398-9974-800876dfd994\n- https://github.com/chalk/ansi-regex/issues/38#issuecomment-924086311\n- https://app.snyk.io/vuln/SNYK-JS-ANSIREGEX-1583908\n- https://github.com/chalk/ansi-regex/issues/38#issuecomment-925924774\n- https://github.com/advisories/GHSA-93q8-gq69-wqmw","created":"2022-03-06T16:00:42.619Z","reported_by":null,"title":" Inefficient Regular Expression Complexity in chalk/ansi-regex","npm_advisory_id":null,"overview":"ansi-regex is vulnerable to Inefficient Regular Expression Complexity","url":"https://github.com/advisories/GHSA-93q8-gq69-wqmw"}}} +{"type":"auditSummary","data":{"vulnerabilities":{"info":0,"low":0,"moderate":6,"high":5,"critical":0},"dependencies":923,"devDependencies":0,"optionalDependencies":0,"totalDependencies":923}} \ No newline at end of file diff --git a/unittests/tools/test_yarn_audit_parser.py b/unittests/tools/test_yarn_audit_parser.py index 3a3c587fdf..2a43e6222a 100644 --- a/unittests/tools/test_yarn_audit_parser.py +++ b/unittests/tools/test_yarn_audit_parser.py @@ -77,7 +77,17 @@ def test_yarn_audit_parser_issue_6495(self): with open("unittests/scans/yarn_audit/issue_6495.json") as testfile: parser = YarnAuditParser() findings = parser.get_findings(testfile, self.get_test()) + testfile.close() self.assertEqual(3, len(findings)) self.assertEqual(findings[0].cwe, "1321") self.assertEqual(findings[1].unsaved_vulnerability_ids[0], "CVE-2022-25851") self.assertEqual(findings[1].cve, None) + + def test_yarn_audit_parser_yarn2_audit_issue9911(self): + with open("unittests/scans/yarn_audit/yarn2_audit_issue9911.json") as testfile: + parser = YarnAuditParser() + findings = parser.get_findings(testfile, self.get_test()) + testfile.close() + self.assertEqual(4, len(findings)) + self.assertEqual(findings[0].title, "@babel/plugin-proposal-class-properties (deprecation)") + self.assertEqual(findings[1].severity, "Medium") From 4a2ba3a5c0ee3b718655c4d7eaeb7e1df4e4fe09 Mon Sep 17 00:00:00 2001 From: kiblik Date: Thu, 2 May 2024 05:23:16 +0200 Subject: [PATCH 116/138] Ruff: clean-up after multiple merges not cover by new rules (#10078) * Ruff: clean-up after multiple merges not cover by new rules * Update dojo/api_v2/permissions.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Update dojo/api_v2/permissions.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Update dojo/forms.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Update dojo/notifications/helper.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Update dojo/settings/settings.dist.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Update dojo/settings/settings.dist.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Update dojo/settings/settings.dist.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Update dojo/settings/settings.dist.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Update dojo/settings/settings.dist.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Update dojo/settings/settings.dist.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Update dojo/settings/settings.dist.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Update dojo/settings/settings.dist.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Update dojo/settings/settings.dist.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Fix unittest --------- Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> --- dojo/api_v2/permissions.py | 55 ++++++-------- dojo/api_v2/serializers.py | 18 ++--- dojo/components/sql_group_concat.py | 6 +- dojo/endpoint/views.py | 6 +- dojo/engagement/views.py | 25 ++++--- dojo/filters.py | 92 ++++++++++++------------ dojo/finding/helper.py | 7 +- dojo/finding/views.py | 17 ++--- dojo/finding_group/views.py | 2 +- dojo/forms.py | 12 ++-- dojo/importers/reimporter/reimporter.py | 10 ++- dojo/jira_link/helper.py | 20 +++--- dojo/jira_link/views.py | 4 +- dojo/management/commands/clear_alerts.py | 4 +- dojo/metrics/views.py | 4 +- dojo/models.py | 5 +- dojo/notifications/helper.py | 2 +- dojo/okta.py | 2 +- dojo/product_type/views.py | 2 +- dojo/search/views.py | 14 ++-- dojo/settings/settings.dist.py | 66 ++++++++--------- dojo/tasks.py | 4 +- dojo/templatetags/display_tags.py | 4 +- dojo/test/views.py | 8 +-- dojo/tools/checkmarx_osa/parser.py | 5 +- dojo/tools/mobsf/parser.py | 4 +- dojo/tools/nmap/parser.py | 15 ++-- dojo/tools/scout_suite/parser.py | 9 +-- dojo/tools/ssl_labs/parser.py | 2 +- dojo/urls.py | 18 ++--- dojo/utils.py | 18 ++--- unittests/dojo_test_case.py | 20 +++--- unittests/test_importers_importer.py | 10 +-- unittests/test_rest_framework.py | 40 +++++------ 34 files changed, 249 insertions(+), 281 deletions(-) diff --git a/dojo/api_v2/permissions.py b/dojo/api_v2/permissions.py index dc02801386..fc8e34d762 100644 --- a/dojo/api_v2/permissions.py +++ b/dojo/api_v2/permissions.py @@ -453,9 +453,8 @@ def has_permission(self, request, view): ) elif engagement_id: # engagement_id doesn't exist - raise serializers.ValidationError( - "Engagement '%s' doesn''t exist" % engagement_id - ) + msg = f"Engagement '{engagement_id}' doesn't exist" + raise serializers.ValidationError(msg) if not auto_create_context: raise_no_auto_create_import_validation_error( @@ -513,9 +512,8 @@ def has_permission(self, request, view): ) elif product_id: # product_id doesn't exist - raise serializers.ValidationError( - "product '%s' doesn''t exist" % product_id - ) + msg = f"product '{product_id}' doesn't exist" + raise serializers.ValidationError(msg) else: msg = "Need product_id or product_name to perform import" raise serializers.ValidationError(msg) @@ -663,9 +661,8 @@ def has_permission(self, request, view): ) elif test_id: # test_id doesn't exist - raise serializers.ValidationError( - "Test '%s' doesn't exist" % test_id - ) + msg = f"Test '{test_id}' doesn't exist" + raise serializers.ValidationError(msg) if not auto_create_context: raise_no_auto_create_import_validation_error( @@ -958,18 +955,16 @@ def raise_no_auto_create_import_validation_error( raise ValidationError(msg) if product_type_name and not product_type: - raise serializers.ValidationError( - "Product Type '%s' doesn't exist" % (product_type_name) - ) + msg = f"Product Type '{product_type_name}' doesn't exist" + raise serializers.ValidationError(msg) if product_name and not product: if product_type_name: msg = f"Product '{product_name}' doesn't exist in Product_Type '{product_type_name}'" raise serializers.ValidationError(msg) else: - raise serializers.ValidationError( - "Product '%s' doesn't exist" % product_name - ) + msg = f"Product '{product_name}' doesn't exist" + raise serializers.ValidationError(msg) if engagement_name and not engagement: msg = f"Engagement '{engagement_name}' doesn't exist in Product '{product_name}'" @@ -1028,37 +1023,29 @@ def check_auto_create_permission( if product and product_name and engagement_name: if not user_has_permission(user, product, Permissions.Engagement_Add): - raise PermissionDenied( - "No permission to create engagements in product '%s'" - % product_name - ) + msg = f"No permission to create engagements in product '{product_name}'" + raise PermissionDenied(msg) if not user_has_permission( user, product, Permissions.Import_Scan_Result ): - raise PermissionDenied( - "No permission to import scans into product '%s'" - % product_name - ) + msg = f"No permission to import scans into product '{product_name}'" + raise PermissionDenied(msg) # all good return True if not product and product_name: if not product_type_name: - raise serializers.ValidationError( - "Product '%s' doesn't exist and no product_type_name provided to create the new product in" - % product_name - ) + msg = f"Product '{product_name}' doesn't exist and no product_type_name provided to create the new product in" + raise serializers.ValidationError(msg) if not product_type: if not user_has_global_permission( user, Permissions.Product_Type_Add ): - raise PermissionDenied( - "No permission to create product_type '%s'" - % product_type_name - ) + msg = f"No permission to create product_type '{product_type_name}'" + raise PermissionDenied(msg) # new product type can be created with current user as owner, so # all objects in it can be created as well return True @@ -1066,10 +1053,8 @@ def check_auto_create_permission( if not user_has_permission( user, product_type, Permissions.Product_Type_Add_Product ): - raise PermissionDenied( - "No permission to create products in product_type '%s'" - % product_type - ) + msg = f"No permission to create products in product_type '{product_type}'" + raise PermissionDenied(msg) # product can be created, so objects in it can be created as well return True diff --git a/dojo/api_v2/serializers.py b/dojo/api_v2/serializers.py index f6544e60b9..3eb65b18bc 100644 --- a/dojo/api_v2/serializers.py +++ b/dojo/api_v2/serializers.py @@ -290,10 +290,8 @@ def to_representation(self, value): elif isinstance(value, str): value = tagulous.utils.parse_tags(value) else: - raise ValueError( - "unable to convert %s into list of tags" - % type(value).__name__ - ) + msg = f"unable to convert {type(value).__name__} into list of tags" + raise ValueError(msg) return value @@ -1912,9 +1910,7 @@ def validate(self, data): def validate_severity(self, value: str) -> str: if value not in SEVERITIES: msg = f"Severity must be one of the following: {SEVERITIES}" - raise serializers.ValidationError( - msg - ) + raise serializers.ValidationError(msg) return value @@ -1996,9 +1992,7 @@ class Meta: def validate_severity(self, value: str) -> str: if value not in SEVERITIES: msg = f"Severity must be one of the following: {SEVERITIES}" - raise serializers.ValidationError( - msg - ) + raise serializers.ValidationError(msg) return value @@ -2015,9 +2009,7 @@ class Meta: def validate_severity(self, value: str) -> str: if value not in SEVERITIES: msg = f"Severity must be one of the following: {SEVERITIES}" - raise serializers.ValidationError( - msg - ) + raise serializers.ValidationError(msg) return value diff --git a/dojo/components/sql_group_concat.py b/dojo/components/sql_group_concat.py index ba23b24e38..b7abd6c9ef 100644 --- a/dojo/components/sql_group_concat.py +++ b/dojo/components/sql_group_concat.py @@ -12,8 +12,8 @@ def __init__( super().__init__( expression, distinct="DISTINCT " if distinct else "", - ordering=" ORDER BY %s" % ordering if ordering is not None else "", - separator=' SEPARATOR "%s"' % separator, + ordering=f" ORDER BY {ordering}" if ordering is not None else "", + separator=f' SEPARATOR "{separator}"', output_field=CharField(), **extra ) @@ -23,7 +23,7 @@ def as_mysql(self, compiler, connection): compiler, connection, template="%(function)s(%(distinct)s%(expressions)s%(ordering)s%(separator)s)", - separator=" SEPARATOR '%s'" % self.separator, + separator=f" SEPARATOR '{self.separator}'", ) def as_sql(self, compiler, connection, **extra): diff --git a/dojo/endpoint/views.py b/dojo/endpoint/views.py index d8c8deaba6..acb956bba1 100644 --- a/dojo/endpoint/views.py +++ b/dojo/endpoint/views.py @@ -223,7 +223,7 @@ def delete_endpoint(request, eid): 'Endpoint and relationships removed.', extra_tags='alert-success') create_notification(event='other', - title='Deletion of %s' % endpoint, + title=f'Deletion of {endpoint}', product=product, description=f'The endpoint "{endpoint}" was deleted by {request.user}', url=reverse('endpoint'), @@ -287,7 +287,7 @@ def add_product_endpoint(request): messages.SUCCESS, 'Endpoint added successfully.', extra_tags='alert-success') - return HttpResponseRedirect(reverse('endpoint') + "?product=%s" % form.product.id) + return HttpResponseRedirect(reverse('endpoint') + f"?product={form.product.id}") add_breadcrumb(title="Add Endpoint", top_level=False, request=request) return render(request, 'dojo/add_endpoint.html', @@ -507,7 +507,7 @@ def import_endpoint_meta(request, pid): endpoint_meta_import(file, product, create_endpoints, create_tags, create_dojo_meta, origin='UI', request=request) except Exception as e: logger.exception(e) - add_error_message_to_response('An exception error occurred during the report import:%s' % str(e)) + add_error_message_to_response(f'An exception error occurred during the report import:{str(e)}') return HttpResponseRedirect(reverse('endpoint') + "?product=" + pid) add_breadcrumb(title="Endpoint Meta Importer", top_level=False, request=request) diff --git a/dojo/engagement/views.py b/dojo/engagement/views.py index 696e7b0ea2..0c01cc72bb 100644 --- a/dojo/engagement/views.py +++ b/dojo/engagement/views.py @@ -280,8 +280,8 @@ def edit_engagement(request, eid): if (new_status == "Cancelled" or new_status == "Completed"): engagement.active = False create_notification(event='close_engagement', - title='Closure of %s' % engagement.name, - description='The engagement "%s" was closed' % (engagement.name), + title=f'Closure of {engagement.name}', + description=f'The engagement "{engagement.name}" was closed', engagement=engagement, url=reverse('engagement_all_findings', args=(engagement.id, ))), else: engagement.active = True @@ -362,7 +362,7 @@ def delete_engagement(request, eid): message, extra_tags='alert-success') create_notification(event='other', - title='Deletion of %s' % engagement.name, + title=f'Deletion of {engagement.name}', product=product, description=f'The engagement "{engagement.name}" was deleted by {request.user}', url=request.build_absolute_uri(reverse('view_engagements', args=(product.id, ))), @@ -405,7 +405,7 @@ def copy_engagement(request, eid): 'Engagement Copied successfully.', extra_tags='alert-success') create_notification(event='other', - title='Copying of %s' % engagement.name, + title=f'Copying of {engagement.name}', description=f'The engagement "{engagement.name}" was copied by {request.user}', product=product, url=request.build_absolute_uri(reverse('view_engagement', args=(engagement_copy.id, ))), @@ -884,7 +884,7 @@ def post(self, request, eid=None, pid=None): except Exception as e: logger.exception(e) - add_error_message_to_response('An exception error occurred during the report import:%s' % str(e)) + add_error_message_to_response(f'An exception error occurred during the report import:{str(e)}') error = True # Save the credential to the test @@ -917,8 +917,8 @@ def close_eng(request, eid): 'Engagement closed successfully.', extra_tags='alert-success') create_notification(event='close_engagement', - title='Closure of %s' % eng.name, - description='The engagement "%s" was closed' % (eng.name), + title=f'Closure of {eng.name}', + description=f'The engagement "{eng.name}" was closed', engagement=eng, url=reverse('engagement_all_findings', args=(eng.id, ))), return HttpResponseRedirect(reverse("view_engagements", args=(eng.product.id, ))) @@ -933,9 +933,9 @@ def reopen_eng(request, eid): 'Engagement reopened successfully.', extra_tags='alert-success') create_notification(event='other', - title='Reopening of %s' % eng.name, + title=f'Reopening of {eng.name}', engagement=eng, - description='The engagement "%s" was reopened' % (eng.name), + description=f'The engagement "{eng.name}" was reopened', url=reverse('view_engagement', args=(eng.id, ))), return HttpResponseRedirect(reverse("view_engagements", args=(eng.product.id, ))) @@ -1051,7 +1051,7 @@ def add_risk_acceptance(request, eid, fid=None): return redirect_to_return_url_or_else(request, reverse('view_engagement', args=(eid, ))) else: - risk_acceptance_title_suggestion = 'Accept: %s' % finding + risk_acceptance_title_suggestion = f'Accept: {finding}' form = RiskAcceptanceForm(initial={'owner': request.user, 'name': risk_acceptance_title_suggestion}) finding_choices = Finding.objects.filter(duplicate=False, test__engagement=eng).filter(NOT_ACCEPTED_FINDINGS_QUERY).order_by('title') @@ -1291,8 +1291,7 @@ def download_risk_acceptance(request, eid, raid): response = StreamingHttpResponse( FileIterWrapper( open(settings.MEDIA_ROOT + "/" + risk_acceptance.path.name, mode='rb'))) - response['Content-Disposition'] = 'attachment; filename="%s"' \ - % risk_acceptance.filename() + response['Content-Disposition'] = f'attachment; filename="{risk_acceptance.filename()}"' mimetype, _encoding = mimetypes.guess_type(risk_acceptance.path.name) response['Content-Type'] = mimetype return response @@ -1361,7 +1360,7 @@ def engagement_ics(request, eid): output = cal.serialize() response = HttpResponse(content=output) response['Content-Type'] = 'text/calendar' - response['Content-Disposition'] = 'attachment; filename=%s.ics' % eng.name + response['Content-Disposition'] = f'attachment; filename={eng.name}.ics' return response diff --git a/dojo/filters.py b/dojo/filters.py index d69202ced0..460a21f6b0 100644 --- a/dojo/filters.py +++ b/dojo/filters.py @@ -101,7 +101,7 @@ def custom_filter(queryset, name, value): values = value.split(',') - filter = ('%s__in' % (name)) + filter = (f'{name}__in') return queryset.filter(Q(**{filter: values})) @@ -322,14 +322,14 @@ def get_tags_model_from_field_name(field): try: parts = field.split('__') model_name = parts[-2] - return apps.get_model('dojo.%s' % model_name, require_ready=True), exclude + return apps.get_model(f'dojo.{model_name}', require_ready=True), exclude except Exception: return None, exclude def get_tags_label_from_model(model): if model: - return 'Tags (%s)' % model.__name__.title() + return f'Tags ({model.__name__.title()})' else: return 'Tags (Unknown)' @@ -602,32 +602,32 @@ class DateRangeFilter(ChoiceFilter): options = { None: (_('Any date'), lambda qs, name: qs.all()), 1: (_('Today'), lambda qs, name: qs.filter(**{ - '%s__year' % name: now().year, - '%s__month' % name: now().month, - '%s__day' % name: now().day + f'{name}__year': now().year, + f'{name}__month': now().month, + f'{name}__day': now().day })), 2: (_('Past 7 days'), lambda qs, name: qs.filter(**{ - '%s__gte' % name: _truncate(now() - timedelta(days=7)), - '%s__lt' % name: _truncate(now() + timedelta(days=1)), + f'{name}__gte': _truncate(now() - timedelta(days=7)), + f'{name}__lt': _truncate(now() + timedelta(days=1)), })), 3: (_('Past 30 days'), lambda qs, name: qs.filter(**{ - '%s__gte' % name: _truncate(now() - timedelta(days=30)), - '%s__lt' % name: _truncate(now() + timedelta(days=1)), + f'{name}__gte': _truncate(now() - timedelta(days=30)), + f'{name}__lt': _truncate(now() + timedelta(days=1)), })), 4: (_('Past 90 days'), lambda qs, name: qs.filter(**{ - '%s__gte' % name: _truncate(now() - timedelta(days=90)), - '%s__lt' % name: _truncate(now() + timedelta(days=1)), + f'{name}__gte': _truncate(now() - timedelta(days=90)), + f'{name}__lt': _truncate(now() + timedelta(days=1)), })), 5: (_('Current month'), lambda qs, name: qs.filter(**{ - '%s__year' % name: now().year, - '%s__month' % name: now().month + f'{name}__year': now().year, + f'{name}__month': now().month })), 6: (_('Current year'), lambda qs, name: qs.filter(**{ - '%s__year' % name: now().year, + f'{name}__year': now().year, })), 7: (_('Past year'), lambda qs, name: qs.filter(**{ - '%s__gte' % name: _truncate(now() - timedelta(days=365)), - '%s__lt' % name: _truncate(now() + timedelta(days=1)), + f'{name}__gte': _truncate(now() - timedelta(days=365)), + f'{name}__lt': _truncate(now() + timedelta(days=1)), })), } @@ -648,48 +648,48 @@ class DateRangeOmniFilter(ChoiceFilter): options = { None: (_('Any date'), lambda qs, name: qs.all()), 1: (_('Today'), lambda qs, name: qs.filter(**{ - '%s__year' % name: now().year, - '%s__month' % name: now().month, - '%s__day' % name: now().day + f'{name}__year': now().year, + f'{name}__month': now().month, + f'{name}__day': now().day })), 2: (_('Next 7 days'), lambda qs, name: qs.filter(**{ - '%s__gte' % name: _truncate(now() + timedelta(days=1)), - '%s__lt' % name: _truncate(now() + timedelta(days=7)), + f'{name}__gte': _truncate(now() + timedelta(days=1)), + f'{name}__lt': _truncate(now() + timedelta(days=7)), })), 3: (_('Next 30 days'), lambda qs, name: qs.filter(**{ - '%s__gte' % name: _truncate(now() + timedelta(days=1)), - '%s__lt' % name: _truncate(now() + timedelta(days=30)), + f'{name}__gte': _truncate(now() + timedelta(days=1)), + f'{name}__lt': _truncate(now() + timedelta(days=30)), })), 4: (_('Next 90 days'), lambda qs, name: qs.filter(**{ - '%s__gte' % name: _truncate(now() + timedelta(days=1)), - '%s__lt' % name: _truncate(now() + timedelta(days=90)), + f'{name}__gte': _truncate(now() + timedelta(days=1)), + f'{name}__lt': _truncate(now() + timedelta(days=90)), })), 5: (_('Past 7 days'), lambda qs, name: qs.filter(**{ - '%s__gte' % name: _truncate(now() - timedelta(days=7)), - '%s__lt' % name: _truncate(now() + timedelta(days=1)), + f'{name}__gte': _truncate(now() - timedelta(days=7)), + f'{name}__lt': _truncate(now() + timedelta(days=1)), })), 6: (_('Past 30 days'), lambda qs, name: qs.filter(**{ - '%s__gte' % name: _truncate(now() - timedelta(days=30)), - '%s__lt' % name: _truncate(now() + timedelta(days=1)), + f'{name}__gte': _truncate(now() - timedelta(days=30)), + f'{name}__lt': _truncate(now() + timedelta(days=1)), })), 7: (_('Past 90 days'), lambda qs, name: qs.filter(**{ - '%s__gte' % name: _truncate(now() - timedelta(days=90)), - '%s__lt' % name: _truncate(now() + timedelta(days=1)), + f'{name}__gte': _truncate(now() - timedelta(days=90)), + f'{name}__lt': _truncate(now() + timedelta(days=1)), })), 8: (_('Current month'), lambda qs, name: qs.filter(**{ - '%s__year' % name: now().year, - '%s__month' % name: now().month + f'{name}__year': now().year, + f'{name}__month': now().month })), 9: (_('Past year'), lambda qs, name: qs.filter(**{ - '%s__gte' % name: _truncate(now() - timedelta(days=365)), - '%s__lt' % name: _truncate(now() + timedelta(days=1)), + f'{name}__gte': _truncate(now() - timedelta(days=365)), + f'{name}__lt': _truncate(now() + timedelta(days=1)), })), 10: (_('Current year'), lambda qs, name: qs.filter(**{ - '%s__year' % name: now().year, + f'{name}__year': now().year, })), 11: (_('Next year'), lambda qs, name: qs.filter(**{ - '%s__gte' % name: _truncate(now() + timedelta(days=1)), - '%s__lt' % name: _truncate(now() + timedelta(days=365)), + f'{name}__gte': _truncate(now() + timedelta(days=1)), + f'{name}__lt': _truncate(now() + timedelta(days=365)), })), } @@ -710,10 +710,10 @@ class ReportBooleanFilter(ChoiceFilter): options = { None: (_('Either'), lambda qs, name: qs.all()), 1: (_('Yes'), lambda qs, name: qs.filter(**{ - '%s' % name: True + f'{name}': True })), 2: (_('No'), lambda qs, name: qs.filter(**{ - '%s' % name: False + f'{name}': False })), } @@ -781,8 +781,8 @@ def current_month(self, qs, name): datetime(now().year, now().month, 1, 0, 0, 0)) self.end_date = now() return qs.filter(**{ - '%s__year' % name: self.start_date.year, - '%s__month' % name: self.start_date.month + f'{name}__year': self.start_date.year, + f'{name}__month': self.start_date.month }) def current_year(self, qs, name): @@ -790,15 +790,15 @@ def current_year(self, qs, name): datetime(now().year, 1, 1, 0, 0, 0)) self.end_date = now() return qs.filter(**{ - '%s__year' % name: now().year, + f'{name}__year': now().year, }) def past_x_days(self, qs, name, days): self.start_date = _truncate(now() - timedelta(days=days)) self.end_date = _truncate(now() + timedelta(days=1)) return qs.filter(**{ - '%s__gte' % name: self.start_date, - '%s__lt' % name: self.end_date, + f'{name}__gte': self.start_date, + f'{name}__lt': self.end_date, }) def past_seven_days(self, qs, name): diff --git a/dojo/finding/helper.py b/dojo/finding/helper.py index 1a5ffb4c2e..3be69d7355 100644 --- a/dojo/finding/helper.py +++ b/dojo/finding/helper.py @@ -251,14 +251,15 @@ def get_group_by_group_name(finding, finding_group_by_option): (finding.component_version if finding.component_version else 'None')) elif finding_group_by_option == 'file_path': if finding.file_path: - group_name = 'Filepath %s' % (finding.file_path) + group_name = f'Filepath {finding.file_path}' elif finding_group_by_option == 'finding_title': group_name = finding.title else: - raise ValueError("Invalid group_by option %s" % finding_group_by_option) + msg = f"Invalid group_by option {finding_group_by_option}" + raise ValueError(msg) if group_name: - return 'Findings in: %s' % group_name + return f'Findings in: {group_name}' return group_name diff --git a/dojo/finding/views.py b/dojo/finding/views.py index f28a37c2fb..44dcce6bea 100644 --- a/dojo/finding/views.py +++ b/dojo/finding/views.py @@ -1290,7 +1290,7 @@ def close_finding(request, fid): ) create_notification( event="other", - title="Closing of %s" % finding.title, + title=f"Closing of {finding.title}", finding=finding, description=f'The finding "{finding.title}" was closed by {request.user}', url=reverse("view_finding", args=(finding.id,)), @@ -1453,7 +1453,7 @@ def reopen_finding(request, fid): ) create_notification( event="other", - title="Reopening of %s" % finding.title, + title=f"Reopening of {finding.title}", finding=finding, description=f'The finding "{finding.title}" was reopened by {request.user}', url=reverse("view_finding", args=(finding.id,)), @@ -1511,7 +1511,7 @@ def copy_finding(request, fid): ) create_notification( event="other", - title="Copying of %s" % finding.title, + title=f"Copying of {finding.title}", description=f'The finding "{finding.title}" was copied by {request.user} to {test.title}', product=product, url=request.build_absolute_uri( @@ -1829,8 +1829,7 @@ def mktemplate(request, fid): request, messages.SUCCESS, mark_safe( - 'Finding template added successfully. You may edit it here.' - % reverse("edit_template", args=(template.id,)) + 'Finding template added successfully. You may edit it here.'.format(reverse("edit_template", args=(template.id,))) ), extra_tags="alert-success", ) @@ -2849,7 +2848,7 @@ def finding_bulk_update_all(request, pid=None): if added: add_success_message_to_response( - "Created finding group with %s findings" % added + f"Created finding group with {added} findings" ) return_url = reverse( "view_finding_group", args=(finding_group.id,) @@ -2857,8 +2856,7 @@ def finding_bulk_update_all(request, pid=None): if skipped: add_success_message_to_response( - "Skipped %s findings in group creation, findings already part of another group" - % skipped + f"Skipped {skipped} findings in group creation, findings already part of another group" ) # refresh findings from db @@ -2912,8 +2910,7 @@ def finding_bulk_update_all(request, pid=None): if skipped: add_success_message_to_response( - "Skipped %s findings when removing from any finding group, findings not part of any group" - % (skipped) + f"Skipped {skipped} findings when removing from any finding group, findings not part of any group" ) # refresh findings from db diff --git a/dojo/finding_group/views.py b/dojo/finding_group/views.py index 8dfe80a317..9173745695 100644 --- a/dojo/finding_group/views.py +++ b/dojo/finding_group/views.py @@ -123,7 +123,7 @@ def delete_finding_group(request, fgid): extra_tags='alert-success') create_notification(event='other', - title='Deletion of %s' % finding_group.name, + title=f'Deletion of {finding_group.name}', product=product, description=f'The finding group "{finding_group.name}" was deleted by {request.user}', url=request.build_absolute_uri(reverse('view_test', args=(finding_group.test.id,))), diff --git a/dojo/forms.py b/dojo/forms.py index 7189c3b50e..c28b4c298b 100644 --- a/dojo/forms.py +++ b/dojo/forms.py @@ -171,7 +171,7 @@ def render(self, name, value, attrs=None, renderer=None): if 'id' in self.attrs: id_ = self.attrs['id'] else: - id_ = 'id_%s' % name + id_ = f'id_{name}' month_choices = list(MONTHS.items()) if not (self.required and value): @@ -194,7 +194,7 @@ def render(self, name, value, attrs=None, renderer=None): return mark_safe('\n'.join(output)) def id_for_label(self, id_): - return '%s_month' % id_ + return f'{id_}_month' id_for_label = classmethod(id_for_label) @@ -783,7 +783,7 @@ class Meta: def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.fields['path'].help_text = 'Existing proof uploaded: %s' % self.instance.filename() if self.instance.filename() else 'None' + self.fields['path'].help_text = f'Existing proof uploaded: {self.instance.filename()}' if self.instance.filename() else 'None' self.fields['expiration_date_warned'].disabled = True self.fields['expiration_date_handled'].disabled = True @@ -2795,9 +2795,9 @@ def __init__(self, *args, **kwargs): if self.target == 'engagement': product_name = self.product.name if self.product else self.engagement.product.name if self.engagement.product else '' - self.fields['project_key'].widget = forms.TextInput(attrs={'placeholder': 'JIRA settings inherited from product ''%s''' % product_name}) - self.fields['project_key'].help_text = 'JIRA settings are inherited from product ''%s'', unless configured differently here.' % product_name - self.fields['jira_instance'].help_text = 'JIRA settings are inherited from product ''%s'' , unless configured differently here.' % product_name + self.fields['project_key'].widget = forms.TextInput(attrs={'placeholder': f"JIRA settings inherited from product '{product_name}'"}) + self.fields['project_key'].help_text = f"JIRA settings are inherited from product '{product_name}', unless configured differently here." + self.fields['jira_instance'].help_text = f"JIRA settings are inherited from product '{product_name}' , unless configured differently here." # if we don't have an instance, django will insert a blank empty one :-( # so we have to check for id to make sure we only trigger this when there is a real instance from db diff --git a/dojo/importers/reimporter/reimporter.py b/dojo/importers/reimporter/reimporter.py index c24f5f961a..9a3ebda828 100644 --- a/dojo/importers/reimporter/reimporter.py +++ b/dojo/importers/reimporter/reimporter.py @@ -203,14 +203,12 @@ def process_parsed_findings( finding.component_version, ) existing_note = finding.notes.filter( - entry="Finding has skipped reactivation from %s re-upload with user decision do_not_reactivate." - % scan_type, + entry=f"Finding has skipped reactivation from {scan_type} re-upload with user decision do_not_reactivate.", author=user, ) if len(existing_note) == 0: note = Notes( - entry="Finding has skipped reactivation from %s re-upload with user decision do_not_reactivate." - % scan_type, + entry=f"Finding has skipped reactivation from {scan_type} re-upload with user decision do_not_reactivate.", author=user, ) note.save() @@ -232,7 +230,7 @@ def process_parsed_findings( # don't dedupe before endpoints are added finding.save(dedupe_option=False) note = Notes( - entry="Re-activated by %s re-upload." % scan_type, author=user + entry=f"Re-activated by {scan_type} re-upload.", author=user ) note.save() @@ -532,7 +530,7 @@ def close_old_findings( finding.save(push_to_jira=push_to_jira, dedupe_option=False) note = Notes( - entry="Mitigated by %s re-upload." % test.test_type, author=user + entry=f"Mitigated by {test.test_type} re-upload.", author=user ) note.save() finding.notes.add(note) diff --git a/dojo/jira_link/helper.py b/dojo/jira_link/helper.py index df99a77096..49525785af 100644 --- a/dojo/jira_link/helper.py +++ b/dojo/jira_link/helper.py @@ -108,10 +108,10 @@ def is_push_all_issues(instance): def can_be_pushed_to_jira(obj, form=None): # logger.debug('can be pushed to JIRA: %s', finding_or_form) if not get_jira_project(obj): - return False, '%s cannot be pushed to jira as there is no jira project configuration for this product.' % to_str_typed(obj), 'error_no_jira_project' + return False, f'{to_str_typed(obj)} cannot be pushed to jira as there is no jira project configuration for this product.', 'error_no_jira_project' if not hasattr(obj, 'has_jira_issue'): - return False, '%s cannot be pushed to jira as there is no jira_issue attribute.' % to_str_typed(obj), 'error_no_jira_issue_attribute' + return False, f'{to_str_typed(obj)} cannot be pushed to jira as there is no jira_issue attribute.', 'error_no_jira_issue_attribute' if isinstance(obj, Stub_Finding): # stub findings don't have active/verified/etc and can always be pushed @@ -142,16 +142,16 @@ def can_be_pushed_to_jira(obj, form=None): jira_minimum_threshold = Finding.get_number_severity(System_Settings.objects.get().jira_minimum_severity) if jira_minimum_threshold and jira_minimum_threshold > Finding.get_number_severity(severity): - logger.debug('Finding below the minimum JIRA severity threshold (%s).' % System_Settings.objects.get().jira_minimum_severity) - return False, 'Finding below the minimum JIRA severity threshold (%s).' % System_Settings.objects.get().jira_minimum_severity, 'below_minimum_threshold' + logger.debug(f'Finding below the minimum JIRA severity threshold ({System_Settings.objects.get().jira_minimum_severity}).') + return False, f'Finding below the minimum JIRA severity threshold ({System_Settings.objects.get().jira_minimum_severity}).', 'below_minimum_threshold' elif isinstance(obj, Finding_Group): if not obj.findings.all(): - return False, '%s cannot be pushed to jira as it is empty.' % to_str_typed(obj), 'error_empty' + return False, f'{to_str_typed(obj)} cannot be pushed to jira as it is empty.', 'error_empty' if 'Active' not in obj.status(): - return False, '%s cannot be pushed to jira as it is not active.' % to_str_typed(obj), 'error_inactive' + return False, f'{to_str_typed(obj)} cannot be pushed to jira as it is not active.', 'error_inactive' else: - return False, '%s cannot be pushed to jira as it is of unsupported type.' % to_str_typed(obj), 'error_unsupported' + return False, f'{to_str_typed(obj)} cannot be pushed to jira as it is of unsupported type.', 'error_unsupported' return True, None, None @@ -448,11 +448,11 @@ def jira_transition(jira, issue, transition_id): except JIRAError as jira_error: logger.debug('error transitioning jira issue ' + issue.key + ' ' + str(jira_error)) logger.exception(jira_error) - alert_text = "JiraError HTTP %s" % jira_error.status_code + alert_text = f"JiraError HTTP {jira_error.status_code}" if jira_error.url: - alert_text += " url: %s" % jira_error.url + alert_text += f" url: {jira_error.url}" if jira_error.text: - alert_text += "\ntext: %s" % jira_error.text + alert_text += f"\ntext: {jira_error.text}" log_jira_generic_alert('error transitioning jira issue ' + issue.key, alert_text) return None diff --git a/dojo/jira_link/views.py b/dojo/jira_link/views.py index 057436dc14..64abdf50ea 100644 --- a/dojo/jira_link/views.py +++ b/dojo/jira_link/views.py @@ -541,12 +541,12 @@ def post(self, request, tid=None): extra_tags='alert-success') create_notification( event='other', - title='Deletion of JIRA: %s' % jira_instance.configuration_name, + title=f'Deletion of JIRA: {jira_instance.configuration_name}', description=f"JIRA \"{jira_instance.configuration_name}\" was deleted by {request.user}", url=request.build_absolute_uri(reverse('jira'))) return HttpResponseRedirect(reverse('jira')) except Exception as e: - add_error_message_to_response('Unable to delete JIRA Instance, probably because it is used by JIRA Issues: %s' % str(e)) + add_error_message_to_response(f'Unable to delete JIRA Instance, probably because it is used by JIRA Issues: {str(e)}') collector = NestedObjects(using=DEFAULT_DB_ALIAS) collector.collect([jira_instance]) rels = collector.nested() diff --git a/dojo/management/commands/clear_alerts.py b/dojo/management/commands/clear_alerts.py index c9b018b9ae..5ae54ae6bb 100644 --- a/dojo/management/commands/clear_alerts.py +++ b/dojo/management/commands/clear_alerts.py @@ -29,9 +29,9 @@ def handle(self, *args, **options): try: user = Dojo_User.objects.get(username=user_name) Alerts.objects.filter(user_id_id=user.id).delete() - self.stdout.write('User Alerts for "%s" deleted with success!' % (user_name)) + self.stdout.write(f'User Alerts for "{user_name}" deleted with success!') except: - self.stdout.write('User "%s" does not exist.' % user_name) + self.stdout.write(f'User "{user_name}" does not exist.') elif alls and not system: Alerts.objects.all().delete() elif system and not alls: diff --git a/dojo/metrics/views.py b/dojo/metrics/views.py index a92c439524..f0348f348e 100644 --- a/dojo/metrics/views.py +++ b/dojo/metrics/views.py @@ -1151,7 +1151,7 @@ def view_engineer(request, eid): details = sorted(details, key=lambda x: x[2]) - add_breadcrumb(title="%s Metrics" % user.get_full_name(), top_level=False, request=request) + add_breadcrumb(title=f"{user.get_full_name()} Metrics", top_level=False, request=request) return render(request, 'dojo/view_engineer.html', { 'open_month': open_month, @@ -1183,7 +1183,7 @@ def view_engineer(request, eid): 'a_chart_data': a_chart_data, 'week_chart_data': week_chart_data, 'week_a_chart_data': week_a_chart_data, - 'name': '%s Metrics' % user.get_full_name(), + 'name': f'{user.get_full_name()} Metrics', 'metric': True, 'total_update': total_update, 'details': details, diff --git a/dojo/models.py b/dojo/models.py index 83ebef99c7..6e7c136578 100644 --- a/dojo/models.py +++ b/dojo/models.py @@ -3072,7 +3072,7 @@ def clean(self): if not val and field == "title": setattr(self, field, "No title given") if not val and field in bigfields: - setattr(self, field, "No %s given" % field) + setattr(self, field, f"No {field} given") def severity_display(self): return self.severity @@ -3958,7 +3958,8 @@ def set_obj(self, obj): elif isinstance(obj, Engagement): self.engagement = obj else: - raise TypeError('unknown object type while creating JIRA_Issue: %s' % to_str_typed(obj)) + msg = f'unknown object type while creating JIRA_Issue: {to_str_typed(obj)}' + raise TypeError(msg) NOTIFICATION_CHOICE_SLACK = ("slack", "slack") diff --git a/dojo/notifications/helper.py b/dojo/notifications/helper.py index 2728b9a148..4f4d16b8a1 100644 --- a/dojo/notifications/helper.py +++ b/dojo/notifications/helper.py @@ -375,7 +375,7 @@ def log_alert(e, notification_type=None, *args, **kwargs): user_id=user, url=kwargs.get('url', reverse('alerts')), title=kwargs.get('title', 'Notification issue')[:250], - description=kwargs.get('description', '%s' % e)[:2000], + description=kwargs.get('description', str(e))[:2000], icon="exclamation-triangle", source=notification_type[:100] if notification_type else kwargs.get('source', 'unknown')[:100]) # relative urls will fail validation diff --git a/dojo/okta.py b/dojo/okta.py index e1aaf13432..47fa718de6 100644 --- a/dojo/okta.py +++ b/dojo/okta.py @@ -57,7 +57,7 @@ def user_data(self, access_token, *args, **kwargs): return self.get_json( self._url('v1/userinfo'), headers={ - 'Authorization': 'Bearer %s' % access_token, + 'Authorization': f'Bearer {access_token}', } ) diff --git a/dojo/product_type/views.py b/dojo/product_type/views.py index 1a0e336e7e..bb41a1cd63 100644 --- a/dojo/product_type/views.py +++ b/dojo/product_type/views.py @@ -148,7 +148,7 @@ def delete_product_type(request, ptid): message, extra_tags='alert-success') create_notification(event='other', - title='Deletion of %s' % product_type.name, + title=f'Deletion of {product_type.name}', no_users=True, description=f'The product type "{product_type.name}" was deleted by {request.user}', url=request.build_absolute_uri(reverse('product_type')), diff --git a/dojo/search/views.py b/dojo/search/views.py index 946462a9e3..9867dfc62f 100644 --- a/dojo/search/views.py +++ b/dojo/search/views.py @@ -424,9 +424,9 @@ def parse_search_query(clean_query): else: keywords.append(vulnerability_id_fix(query_part)) - logger.debug('query: %s' % clean_query) - logger.debug('operators: %s' % operators) - logger.debug('keywords: %s' % keywords) + logger.debug(f'query: {clean_query}') + logger.debug(f'operators: {operators}') + logger.debug(f'keywords: {keywords}') return operators, keywords @@ -491,12 +491,12 @@ def apply_tag_filters(qs, operators, skip_relations=False): if tag_filter in operators: value = operators[tag_filter] value = ','.join(value) # contains needs a single value - qs = qs.filter(**{'%stags__name__contains' % tag_filters[tag_filter]: value}) + qs = qs.filter(**{f'{tag_filters[tag_filter]}tags__name__contains': value}) for tag_filter in tag_filters: if tag_filter + 's' in operators: value = operators[tag_filter + 's'] - qs = qs.filter(**{'%stags__name__in' % tag_filters[tag_filter]: value}) + qs = qs.filter(**{f'{tag_filters[tag_filter]}tags__name__in': value}) # negative search based on not- prefix (not-tags, not-test-tags, not-engagement-tags, not-product-tags, etc) @@ -505,13 +505,13 @@ def apply_tag_filters(qs, operators, skip_relations=False): if tag_filter in operators: value = operators[tag_filter] value = ','.join(value) # contains needs a single value - qs = qs.exclude(**{'%stags__name__contains' % tag_filters[tag_filter.replace('not-', '')]: value}) + qs = qs.exclude(**{'{}tags__name__contains'.format(tag_filters[tag_filter.replace('not-', '')]): value}) for tag_filter in tag_filters: tag_filter = 'not-' + tag_filter if tag_filter + 's' in operators: value = operators[tag_filter + 's'] - qs = qs.exclude(**{'%stags__name__in' % tag_filters[tag_filter.replace('not-', '')]: value}) + qs = qs.exclude(**{'{}tags__name__in'.format(tag_filters[tag_filter.replace('not-', '')]): value}) return qs diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index 5931af1125..2f4de7a9cf 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -605,19 +605,19 @@ def generate_url(scheme, double_slashes, user, password, host, port, path, param MAX_AUTOCOMPLETE_WORDS = env('DD_MAX_AUTOCOMPLETE_WORDS') LOGIN_EXEMPT_URLS = ( - r'^%sstatic/' % URL_PREFIX, - r'^%swebhook/([\w-]+)$' % URL_PREFIX, - r'^%swebhook/' % URL_PREFIX, - r'^%sjira/webhook/([\w-]+)$' % URL_PREFIX, - r'^%sjira/webhook/' % URL_PREFIX, - r'^%sreports/cover$' % URL_PREFIX, - r'^%sfinding/image/(?P[^/]+)$' % URL_PREFIX, - r'^%sapi/v2/' % URL_PREFIX, + rf'^{URL_PREFIX}static/', + rf'^{URL_PREFIX}webhook/([\w-]+)$', + rf'^{URL_PREFIX}webhook/', + rf'^{URL_PREFIX}jira/webhook/([\w-]+)$', + rf'^{URL_PREFIX}jira/webhook/', + rf'^{URL_PREFIX}reports/cover$', + rf'^{URL_PREFIX}finding/image/(?P[^/]+)$', + rf'^{URL_PREFIX}api/v2/', r'complete/', r'empty_questionnaire/([\d]+)/answer', - r'^%spassword_reset/' % URL_PREFIX, - r'^%sforgot_username' % URL_PREFIX, - r'^%sreset/' % URL_PREFIX, + rf'^{URL_PREFIX}password_reset/', + rf'^{URL_PREFIX}forgot_username', + rf'^{URL_PREFIX}reset/', ) AUTH_PASSWORD_VALIDATORS = [ @@ -910,7 +910,7 @@ def saml2_attrib_map_format(dict): INSTALLED_APPS += ('djangosaml2',) MIDDLEWARE.append('djangosaml2.middleware.SamlSessionMiddleware') AUTHENTICATION_BACKENDS += (env('DD_SAML2_AUTHENTICATION_BACKENDS'),) - LOGIN_EXEMPT_URLS += (r'^%ssaml2/' % URL_PREFIX,) + LOGIN_EXEMPT_URLS += (rf'^{URL_PREFIX}saml2/',) SAML_LOGOUT_REQUEST_PREFERRED_BINDING = saml2.BINDING_HTTP_POST SAML_IGNORE_LOGOUT_ERRORS = True SAML_DJANGO_USER_MAIN_ATTRIBUTE = 'username' @@ -922,7 +922,7 @@ def saml2_attrib_map_format(dict): SAML_ALLOW_UNKNOWN_ATTRIBUTES = env('DD_SAML2_ALLOW_UNKNOWN_ATTRIBUTE') BASEDIR = path.dirname(path.abspath(__file__)) if len(env('DD_SAML2_ENTITY_ID')) == 0: - SAML2_ENTITY_ID = '%s/saml2/metadata/' % SITE_URL + SAML2_ENTITY_ID = f'{SITE_URL}/saml2/metadata/' else: SAML2_ENTITY_ID = env('DD_SAML2_ENTITY_ID') @@ -931,7 +931,7 @@ def saml2_attrib_map_format(dict): 'xmlsec_binary': '/usr/bin/xmlsec1', # your entity id, usually your subdomain plus the url to the metadata view - 'entityid': '%s' % SAML2_ENTITY_ID, + 'entityid': str(SAML2_ENTITY_ID), # directory with attribute mapping 'attribute_map_dir': path.join(BASEDIR, 'attribute-maps'), @@ -955,16 +955,16 @@ def saml2_attrib_map_format(dict): # url and binding to the assetion consumer service view # do not change the binding or service name 'assertion_consumer_service': [ - ('%s/saml2/acs/' % SITE_URL, + (f'{SITE_URL}/saml2/acs/', saml2.BINDING_HTTP_POST), ], # url and binding to the single logout service view # do not change the binding or service name 'single_logout_service': [ # Disable next two lines for HTTP_REDIRECT for IDP's that only support HTTP_POST. Ex. Okta: - ('%s/saml2/ls/' % SITE_URL, + (f'{SITE_URL}/saml2/ls/', saml2.BINDING_HTTP_REDIRECT), - ('%s/saml2/ls/post' % SITE_URL, + (f'{SITE_URL}/saml2/ls/post', saml2.BINDING_HTTP_POST), ], }, @@ -1156,7 +1156,7 @@ def saml2_attrib_map_format(dict): database_engine = DATABASES.get('default').get('ENGINE') DATABASES['default']['ENGINE'] = database_engine.replace('django.', 'django_prometheus.', 1) # CELERY_RESULT_BACKEND.replace('django.core','django_prometheus.', 1) - LOGIN_EXEMPT_URLS += (r'^%sdjango_metrics/' % URL_PREFIX,) + LOGIN_EXEMPT_URLS += (rf'^{URL_PREFIX}django_metrics/',) # ------------------------------------ @@ -1563,46 +1563,46 @@ def saml2_attrib_map_format(dict): 'loggers': { 'django.request': { 'handlers': ['mail_admins', 'console'], - 'level': '%s' % LOG_LEVEL, + 'level': str(LOG_LEVEL), 'propagate': False, }, 'django.security': { - 'handlers': [r'%s' % LOGGING_HANDLER], - 'level': '%s' % LOG_LEVEL, + 'handlers': [rf'{LOGGING_HANDLER}'], + 'level': str(LOG_LEVEL), 'propagate': False, }, 'celery': { - 'handlers': [r'%s' % LOGGING_HANDLER], - 'level': '%s' % LOG_LEVEL, + 'handlers': [rf'{LOGGING_HANDLER}'], + 'level': str(LOG_LEVEL), 'propagate': False, # workaround some celery logging known issue 'worker_hijack_root_logger': False, }, 'dojo': { - 'handlers': [r'%s' % LOGGING_HANDLER], - 'level': '%s' % LOG_LEVEL, + 'handlers': [rf'{LOGGING_HANDLER}'], + 'level': str(LOG_LEVEL), 'propagate': False, }, 'dojo.specific-loggers.deduplication': { - 'handlers': [r'%s' % LOGGING_HANDLER], - 'level': '%s' % LOG_LEVEL, + 'handlers': [rf'{LOGGING_HANDLER}'], + 'level': str(LOG_LEVEL), 'propagate': False, }, 'saml2': { - 'handlers': [r'%s' % LOGGING_HANDLER], - 'level': '%s' % LOG_LEVEL, + 'handlers': [rf'{LOGGING_HANDLER}'], + 'level': str(LOG_LEVEL), 'propagate': False, }, 'MARKDOWN': { # The markdown library is too verbose in it's logging, reducing the verbosity in our logs. - 'handlers': [r'%s' % LOGGING_HANDLER], - 'level': '%s' % LOG_LEVEL, + 'handlers': [rf'{LOGGING_HANDLER}'], + 'level': str(LOG_LEVEL), 'propagate': False, }, 'titlecase': { # The titlecase library is too verbose in it's logging, reducing the verbosity in our logs. - 'handlers': [r'%s' % LOGGING_HANDLER], - 'level': '%s' % LOG_LEVEL, + 'handlers': [rf'{LOGGING_HANDLER}'], + 'level': str(LOG_LEVEL), 'propagate': False, }, } diff --git a/dojo/tasks.py b/dojo/tasks.py index 4d089b0ca0..8f4941bbe9 100644 --- a/dojo/tasks.py +++ b/dojo/tasks.py @@ -31,7 +31,7 @@ def add_alerts(self, runinterval): upcoming_engagements = Engagement.objects.filter(target_start__gt=now + timedelta(days=3), target_start__lt=now + timedelta(days=3) + runinterval).order_by('target_start') for engagement in upcoming_engagements: create_notification(event='upcoming_engagement', - title='Upcoming engagement: %s' % engagement.name, + title=f'Upcoming engagement: {engagement.name}', engagement=engagement, recipients=[engagement.lead], url=reverse('view_engagement', args=(engagement.id,))) @@ -42,7 +42,7 @@ def add_alerts(self, runinterval): status='In Progress').order_by('-target_end') for eng in stale_engagements: create_notification(event='stale_engagement', - title='Stale Engagement: %s' % eng.name, + title=f'Stale Engagement: {eng.name}', description='The engagement "{}" is stale. Target end was {}.'.format(eng.name, eng.target_end.strftime("%b. %d, %Y")), url=reverse('view_engagement', args=(eng.id,)), recipients=[eng.lead]) diff --git a/dojo/templatetags/display_tags.py b/dojo/templatetags/display_tags.py index 52e9cd3a4f..1b45c93511 100644 --- a/dojo/templatetags/display_tags.py +++ b/dojo/templatetags/display_tags.py @@ -419,8 +419,8 @@ def render(self, context): _, iterable, _, num_cols, _, _, varname = token.split_contents() num_cols = int(num_cols) except ValueError: - raise template.TemplateSyntaxError( - "Invalid arguments passed to %r." % token.contents.split()[0]) + msg = f"Invalid arguments passed to {token.contents.split()[0]!r}." + raise template.TemplateSyntaxError(msg) return Node(iterable, num_cols, varname) diff --git a/dojo/test/views.py b/dojo/test/views.py index c6c9877beb..d23c4f2164 100644 --- a/dojo/test/views.py +++ b/dojo/test/views.py @@ -383,7 +383,7 @@ def copy_test(request, tid): 'Test Copied successfully.', extra_tags='alert-success') create_notification(event='other', - title='Copying of %s' % test.title, + title=f'Copying of {test.title}', description=f'The test "{test.title}" was copied by {request.user} to {engagement.name}', product=product, url=request.build_absolute_uri(reverse('view_test', args=(test_copy.id,))), @@ -456,7 +456,7 @@ def test_ics(request, tid): output = cal.serialize() response = HttpResponse(content=output) response['Content-Type'] = 'text/calendar' - response['Content-Disposition'] = 'attachment; filename=%s.ics' % test.test_type.name + response['Content-Disposition'] = f'attachment; filename={test.test_type.name}.ics' return response @@ -739,7 +739,7 @@ def add_temp_finding(request, tid, fid): if jform.cleaned_data.get('push_to_jira'): jira_helper.push_to_jira(new_finding) else: - add_error_message_to_response('jira form validation failed: %s' % jform.errors) + add_error_message_to_response(f'jira form validation failed: {jform.errors}') if 'request' in form.cleaned_data or 'response' in form.cleaned_data: burp_rr = BurpRawRequestResponse( finding=new_finding, @@ -910,7 +910,7 @@ def re_import_scan_results(request, tid): apply_tags_to_findings=apply_tags_to_findings, apply_tags_to_endpoints=apply_tags_to_endpoints) except Exception as e: logger.exception(e) - add_error_message_to_response('An exception error occurred during the report import:%s' % str(e)) + add_error_message_to_response(f'An exception error occurred during the report import:{str(e)}') error = True if not error: diff --git a/dojo/tools/checkmarx_osa/parser.py b/dojo/tools/checkmarx_osa/parser.py index c2f8c9fcca..f61f5de656 100644 --- a/dojo/tools/checkmarx_osa/parser.py +++ b/dojo/tools/checkmarx_osa/parser.py @@ -122,6 +122,5 @@ def checkmarx_confidence_to_defectdojo_confidence( def check_mandatory(self, item, mandatory_vulnerability_fields): for field in mandatory_vulnerability_fields: if field not in item: - raise ValueError( - "Invalid format: missing mandatory field %s" % field - ) + msg = f"Invalid format: missing mandatory field {field}" + raise ValueError(msg) diff --git a/dojo/tools/mobsf/parser.py b/dojo/tools/mobsf/parser.py index 02e43944f3..2cbdca7920 100644 --- a/dojo/tools/mobsf/parser.py +++ b/dojo/tools/mobsf/parser.py @@ -53,7 +53,7 @@ def get_findings(self, filename, test): if "maxsdk" in data: test_description = "{} **Max SDK:** {}\n".format(test_description, data["maxsdk"]) - test_description = "%s\n**File Information:**\n" % (test_description) + test_description = f"{test_description}\n**File Information:**\n" if "name" in data: test_description = "{} **Name:** {}\n".format(test_description, data["name"]) @@ -74,7 +74,7 @@ def get_findings(self, filename, test): curl = "" for url in data["urls"]: for curl in url["urls"]: - curl = "%s\n" % (curl) + curl = f"{curl}\n" if curl: test_description = f"{test_description}\n**URL's:**\n {curl}\n" diff --git a/dojo/tools/nmap/parser.py b/dojo/tools/nmap/parser.py index 3cb37710a9..f0eb012895 100644 --- a/dojo/tools/nmap/parser.py +++ b/dojo/tools/nmap/parser.py @@ -37,7 +37,7 @@ def get_findings(self, file, test): ip = host.find("address[@addrtype='ipv4']").attrib["addr"] if ip is not None: - host_info += "**IP Address:** %s\n" % ip + host_info += f"**IP Address:** {ip}\n" fqdn = ( host.find("hostnames/hostname[@type='PTR']").attrib["name"] @@ -45,7 +45,7 @@ def get_findings(self, file, test): else None ) if fqdn is not None: - host_info += "**FQDN:** %s\n" % fqdn + host_info += f"**FQDN:** {fqdn}\n" host_info += "\n\n" @@ -53,7 +53,7 @@ def get_findings(self, file, test): for os_match in os.iter("osmatch"): if "name" in os_match.attrib: host_info += ( - "**Host OS:** %s\n" % os_match.attrib["name"] + "**Host OS:** {}\n".format(os_match.attrib["name"]) ) if "accuracy" in os_match.attrib: host_info += "**Accuracy:** {}%\n".format( @@ -84,20 +84,17 @@ def get_findings(self, file, test): if port_element.find("service") is not None: if "product" in port_element.find("service").attrib: service_info += ( - "**Product:** %s\n" - % port_element.find("service").attrib["product"] + "**Product:** {}\n".format(port_element.find("service").attrib["product"]) ) if "version" in port_element.find("service").attrib: service_info += ( - "**Version:** %s\n" - % port_element.find("service").attrib["version"] + "**Version:** {}\n".format(port_element.find("service").attrib["version"]) ) if "extrainfo" in port_element.find("service").attrib: service_info += ( - "**Extra Info:** %s\n" - % port_element.find("service").attrib["extrainfo"] + "**Extra Info:** {}\n".format(port_element.find("service").attrib["extrainfo"]) ) description += service_info diff --git a/dojo/tools/scout_suite/parser.py b/dojo/tools/scout_suite/parser.py index 03293e586b..e6344fa67a 100644 --- a/dojo/tools/scout_suite/parser.py +++ b/dojo/tools/scout_suite/parser.py @@ -50,12 +50,9 @@ def get_tests(self, scan_type, handle): # Summary of Services test_description = ( - "%s\n\n Services | Checked Items | Flagged Items | Max Level | Resource Count | Rules Count" - % (test_description) - ) - test_description = "%s\n:---|---:|---:|---:|---:|---:" % ( - test_description + f"{test_description}\n\n Services | Checked Items | Flagged Items | Max Level | Resource Count | Rules Count" ) + test_description = f"{test_description}\n:---|---:|---:|---:|---:|---:" for service, items in list(last_run["summary"].items()): test_description += "\n" test_description += "|".join( @@ -178,7 +175,7 @@ def tabs(n): ) else: self.item_data = ( - self.item_data + self.formatview(depth) + "%s\n" % src + self.item_data + self.formatview(depth) + f"{src}\n" ) self.pdepth = depth diff --git a/dojo/tools/ssl_labs/parser.py b/dojo/tools/ssl_labs/parser.py index 9a8e2336dd..f70992674a 100644 --- a/dojo/tools/ssl_labs/parser.py +++ b/dojo/tools/ssl_labs/parser.py @@ -60,7 +60,7 @@ def get_findings(self, filename, test): title = f"TLS Grade '{grade}' for {hostName}" sev = self.getCriticalityRating(grade) - description = "%s \n\n" % title + description = f"{title} \n\n" cert = "" if "cert" in endpoints["details"]: cert = endpoints["details"]["cert"] diff --git a/dojo/urls.py b/dojo/urls.py index 0c5320711e..b9d9493c66 100644 --- a/dojo/urls.py +++ b/dojo/urls.py @@ -211,8 +211,8 @@ api_v2_urls = [ # Django Rest Framework API v2 - re_path(r'^%sapi/v2/' % get_system_setting('url_prefix'), include(v2_api.urls)), - re_path(r'^%sapi/v2/user_profile/' % get_system_setting('url_prefix'), UserProfileView.as_view(), name='user_profile'), + re_path(r'^{}api/v2/'.format(get_system_setting('url_prefix')), include(v2_api.urls)), + re_path(r'^{}api/v2/user_profile/'.format(get_system_setting('url_prefix')), UserProfileView.as_view(), name='user_profile'), ] if hasattr(settings, 'API_TOKENS_ENABLED'): @@ -233,17 +233,17 @@ urlpatterns += [ # action history - re_path(r'^%shistory/(?P\d+)/(?P\d+)$' % get_system_setting('url_prefix'), views.action_history, name='action_history'), - re_path(r'^%s' % get_system_setting('url_prefix'), include(ur)), + re_path(r'^{}history/(?P\d+)/(?P\d+)$'.format(get_system_setting('url_prefix')), views.action_history, name='action_history'), + re_path(r'^{}'.format(get_system_setting('url_prefix')), include(ur)), # drf-spectacular = OpenAPI3 - re_path(r'^%sapi/v2/oa3/schema/' % get_system_setting('url_prefix'), SpectacularAPIView.as_view(), name='schema_oa3'), - re_path(r'^%sapi/v2/oa3/swagger-ui/' % get_system_setting('url_prefix'), SpectacularSwaggerView.as_view(url=get_system_setting('url_prefix') + '/api/v2/oa3/schema/?format=json'), name='swagger-ui_oa3'), + re_path(r'^{}api/v2/oa3/schema/'.format(get_system_setting('url_prefix')), SpectacularAPIView.as_view(), name='schema_oa3'), + re_path(r'^{}api/v2/oa3/swagger-ui/'.format(get_system_setting('url_prefix')), SpectacularSwaggerView.as_view(url=get_system_setting('url_prefix') + '/api/v2/oa3/schema/?format=json'), name='swagger-ui_oa3'), re_path(r'^robots.txt', lambda x: HttpResponse("User-Agent: *\nDisallow: /", content_type="text/plain"), name="robots_file"), re_path(r'^manage_files/(?P\d+)/(?P\w+)$', views.manage_files, name='manage_files'), re_path(r'^access_file/(?P\d+)/(?P\d+)/(?P\w+)$', views.access_file, name='access_file'), - re_path(r'^%s/(?P.*)$' % settings.MEDIA_URL.strip('/'), views.protected_serve, {'document_root': settings.MEDIA_ROOT}) + re_path(r'^{}/(?P.*)$'.format(settings.MEDIA_URL.strip('/')), views.protected_serve, {'document_root': settings.MEDIA_ROOT}) ] urlpatterns += api_v2_urls @@ -251,7 +251,7 @@ if hasattr(settings, 'DJANGO_METRICS_ENABLED'): if settings.DJANGO_METRICS_ENABLED: - urlpatterns += [re_path(r'^%sdjango_metrics/' % get_system_setting('url_prefix'), include('django_prometheus.urls'))] + urlpatterns += [re_path(r'^{}django_metrics/'.format(get_system_setting('url_prefix')), include('django_prometheus.urls'))] if hasattr(settings, 'SAML2_ENABLED'): if settings.SAML2_ENABLED: @@ -261,7 +261,7 @@ if hasattr(settings, 'DJANGO_ADMIN_ENABLED'): if settings.DJANGO_ADMIN_ENABLED: # django admin - urlpatterns += [re_path(r'^%sadmin/' % get_system_setting('url_prefix'), admin.site.urls)] + urlpatterns += [re_path(r'^{}admin/'.format(get_system_setting('url_prefix')), admin.site.urls)] # sometimes urlpatterns needed be added from local_settings.py to avoid having to modify core defect dojo files if hasattr(settings, 'EXTRA_URL_PATTERNS'): diff --git a/dojo/utils.py b/dojo/utils.py index 4e01297393..f5605b9dba 100644 --- a/dojo/utils.py +++ b/dojo/utils.py @@ -1254,7 +1254,7 @@ def build_query(query_string, search_fields): for term in terms: or_query = None # Query to search for a given term in each field for field_name in search_fields: - q = Q(**{"%s__icontains" % field_name: term}) + q = Q(**{f"{field_name}__icontains": term}) if or_query: or_query = or_query | q @@ -1400,7 +1400,7 @@ def process_notifications(request, note, parent_url, parent_title): event='user_mentioned', section=parent_title, note=note, - title='%s jotted a note' % request.user, + title=f'{request.user} jotted a note', url=parent_url, icon='commenting', recipients=users_to_notify) @@ -1878,7 +1878,7 @@ def _add_notification(finding, kind): combined_notifications[pt] = {p: {kind: [notification]}} def _notification_title_for_finding(finding, kind, sla_age): - title = "Finding %s - " % (finding.id) + title = f"Finding {finding.id} - " if kind == 'breached': abs_sla_age = abs(sla_age) period = "day" @@ -2051,7 +2051,7 @@ def get_words_for_field(model, fieldname): if models is not None: words = [ - word for field_value in models.order_by().filter(**{'%s__isnull' % fieldname: False}).values_list(fieldname, flat=True).distinct()[:max_results] for word in (field_value.split() if field_value else []) if len(word) > 2 + word for field_value in models.order_by().filter(**{f'{fieldname}__isnull': False}).values_list(fieldname, flat=True).distinct()[:max_results] for word in (field_value.split() if field_value else []) if len(word) > 2 ] else: words = [] @@ -2094,10 +2094,11 @@ def get_object_or_none(klass, *args, **kwargs): if not hasattr(queryset, 'get'): klass__name = klass.__name__ if isinstance(klass, type) else klass.__class__.__name__ - raise ValueError( + msg = ( "First argument to get_object_or_None() must be a Model, Manager, " - "or QuerySet, not '%s'." % klass__name + f"or QuerySet, not '{klass__name}'." ) + raise ValueError(msg) try: return queryset.get(*args, **kwargs) except queryset.model.DoesNotExist: @@ -2120,10 +2121,11 @@ def get_last_object_or_none(klass, *args, **kwargs): if not hasattr(queryset, 'get'): klass__name = klass.__name__ if isinstance(klass, type) else klass.__class__.__name__ - raise ValueError( + msg = ( "First argument to get_last_object_or_None() must be a Model, Manager, " - "or QuerySet, not '%s'." % klass__name + f"or QuerySet, not '{klass__name}'." ) + raise ValueError(msg) try: results = queryset.filter(*args, **kwargs).order_by('id') logger.debug('last_object_or_none: %s', results.query) diff --git a/unittests/dojo_test_case.py b/unittests/dojo_test_case.py index 32aaa4dec5..656ed87124 100644 --- a/unittests/dojo_test_case.py +++ b/unittests/dojo_test_case.py @@ -81,13 +81,13 @@ def create_product(self, name, *args, description='dummy description', prod_type def patch_product_api(self, product_id, product_details): payload = copy.deepcopy(product_details) - response = self.client.patch(reverse('product-list') + '%s/' % product_id, payload, format='json') + response = self.client.patch(reverse('product-list') + f'{product_id}/', payload, format='json') self.assertEqual(200, response.status_code, response.content[:1000]) return response.data def patch_endpoint_api(self, endpoint_id, endpoint_details): payload = copy.deepcopy(endpoint_details) - response = self.client.patch(reverse('endpoint-list') + '%s/' % endpoint_id, payload, format='json') + response = self.client.patch(reverse('endpoint-list') + f'{endpoint_id}/', payload, format='json') self.assertEqual(200, response.status_code, response.content[:1000]) return response.data @@ -105,7 +105,7 @@ def get_test(self, id): return Test.objects.get(id=id) def get_test_api(self, test_id): - response = self.client.patch(reverse('engagement-list') + '%s/' % test_id) + response = self.client.patch(reverse('engagement-list') + f'{test_id}/') self.assertEqual(200, response.status_code, response.content[:1000]) return response.data @@ -113,7 +113,7 @@ def get_engagement(self, id): return Engagement.objects.get(id=id) def get_engagement_api(self, engagement_id): - response = self.client.patch(reverse('engagement-list') + '%s/' % engagement_id) + response = self.client.patch(reverse('engagement-list') + f'{engagement_id}/') self.assertEqual(200, response.status_code, response.content[:1000]) return response.data @@ -475,7 +475,7 @@ def endpoint_meta_import_scan(self, payload, expected_http_status_code): return json.loads(response.content) def get_test_api(self, test_id): - response = self.client.get(reverse('test-list') + '%s/' % test_id, format='json') + response = self.client.get(reverse('test-list') + f'{test_id}/', format='json') self.assertEqual(200, response.status_code, response.content[:1000]) # print('test.content: ', response.content) return json.loads(response.content) @@ -603,7 +603,7 @@ def endpoint_meta_import_scan_with_params(self, filename, product=1, product_nam return self.endpoint_meta_import_scan(payload, expected_http_status_code) def get_finding_api(self, finding_id): - response = self.client.get(reverse('finding-list') + '%s/' % finding_id, format='json') + response = self.client.get(reverse('finding-list') + f'{finding_id}/', format='json') self.assertEqual(200, response.status_code, response.content[:1000]) return response.data @@ -623,12 +623,12 @@ def put_finding_api(self, finding_id, finding_details, push_to_jira=None): if push_to_jira is not None: payload['push_to_jira'] = push_to_jira - response = self.client.put(reverse('finding-list') + '%s/' % finding_id, payload, format='json') + response = self.client.put(reverse('finding-list') + f'{finding_id}/', payload, format='json') self.assertEqual(200, response.status_code, response.content[:1000]) return response.data def delete_finding_api(self, finding_id): - response = self.client.delete(reverse('finding-list') + '%s/' % finding_id) + response = self.client.delete(reverse('finding-list') + f'{finding_id}/') self.assertEqual(204, response.status_code, response.content[:1000]) return response.data @@ -637,7 +637,7 @@ def patch_finding_api(self, finding_id, finding_details, push_to_jira=None): if push_to_jira is not None: payload['push_to_jira'] = push_to_jira - response = self.client.patch(reverse('finding-list') + '%s/' % finding_id, payload, format='json') + response = self.client.patch(reverse('finding-list') + f'{finding_id}/', payload, format='json') self.assertEqual(200, response.status_code, response.content[:1000]) return response.data @@ -699,7 +699,7 @@ def get_finding_tags_api(self, finding_id): return response.data def get_finding_api_filter_tags(self, tags): - response = self.client.get(reverse('finding-list') + '?tags=%s' % tags, format='json') + response = self.client.get(reverse('finding-list') + f'?tags={tags}', format='json') self.assertEqual(200, response.status_code, response.content[:1000]) # print(response.data) return response.data diff --git a/unittests/test_importers_importer.py b/unittests/test_importers_importer.py index 486088c77e..5a41fc927d 100644 --- a/unittests/test_importers_importer.py +++ b/unittests/test_importers_importer.py @@ -302,7 +302,7 @@ def test_import_with_invalid_parameters(self): with self.subTest('invalid engagement'): import0 = self.import_scan_with_params(NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, engagement=1254235, expected_http_status_code=400) - self.assertEqual(import0, ["Engagement '1254235' doesn''t exist"]) + self.assertEqual(import0, ["Engagement '1254235' doesn't exist"]) with self.subTest('invalid engagement, but exists in another product'): # random product to avoid collision with other tests @@ -310,7 +310,7 @@ def test_import_with_invalid_parameters(self): self.product = self.create_product(another_product_name) import0 = self.import_scan_with_params(NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, engagement=None, engagement_name=ENGAGEMENT_NAME_DEFAULT, product_name=another_product_name, expected_http_status_code=400) - self.assertEqual(import0, ["Engagement 'Engagement 1' doesn't exist in Product '%s'" % another_product_name]) + self.assertEqual(import0, [f"Engagement 'Engagement 1' doesn't exist in Product '{another_product_name}'"]) with self.subTest('invalid engagement not id'): import0 = self.import_scan_with_params(NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, @@ -320,7 +320,7 @@ def test_import_with_invalid_parameters(self): with self.subTest('autocreate product but no product type name'): import0 = self.import_scan_with_params(NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, product_name=PRODUCT_NAME_NEW, engagement=None, engagement_name=ENGAGEMENT_NAME_NEW, auto_create_context=True, expected_http_status_code=400) - self.assertEqual(import0, ["Product '%s' doesn't exist and no product_type_name provided to create the new product in" % PRODUCT_NAME_NEW]) + self.assertEqual(import0, [f"Product '{PRODUCT_NAME_NEW}' doesn't exist and no product_type_name provided to create the new product in"]) with self.subTest('autocreate engagement but no product_name'): import0 = self.import_scan_with_params(NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, product_name=None, @@ -518,7 +518,7 @@ def test_reimport_with_invalid_parameters(self): self.product = self.create_product(another_product_name) import0 = self.reimport_scan_with_params(None, NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, engagement_name=ENGAGEMENT_NAME_DEFAULT, product_name=another_product_name, expected_http_status_code=400) - self.assertEqual(import0, ["Engagement 'Engagement 1' doesn't exist in Product '%s'" % another_product_name]) + self.assertEqual(import0, [f"Engagement 'Engagement 1' doesn't exist in Product '{another_product_name}'"]) with self.subTest('invalid engagement not id'): import0 = self.reimport_scan_with_params(None, NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, @@ -528,7 +528,7 @@ def test_reimport_with_invalid_parameters(self): with self.subTest('autocreate product but no product type name'): import0 = self.reimport_scan_with_params(None, NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, product_name=PRODUCT_NAME_NEW, engagement=None, engagement_name=ENGAGEMENT_NAME_NEW, auto_create_context=True, expected_http_status_code=400) - self.assertEqual(import0, ["Product '%s' doesn't exist and no product_type_name provided to create the new product in" % PRODUCT_NAME_NEW]) + self.assertEqual(import0, [f"Product '{PRODUCT_NAME_NEW}' doesn't exist and no product_type_name provided to create the new product in"]) with self.subTest('autocreate engagement but no product_name'): import0 = self.reimport_scan_with_params(None, NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, diff --git a/unittests/test_rest_framework.py b/unittests/test_rest_framework.py index 710766428a..5e2adac7a0 100644 --- a/unittests/test_rest_framework.py +++ b/unittests/test_rest_framework.py @@ -168,7 +168,7 @@ def skipIfNotSubclass(baseclass): def decorate(f): def wrapper(self, *args, **kwargs): if not issubclass(self.viewset, baseclass): - self.skipTest('This view does not inherit from %s' % baseclass) + self.skipTest(f'This view does not inherit from {baseclass}') else: f(self, *args, **kwargs) return wrapper @@ -458,7 +458,7 @@ def test_create(self): @skipIfNotSubclass(RetrieveModelMixin) def test_detail(self): current_objects = self.client.get(self.url, format='json').data - relative_url = self.url + '%s/' % current_objects['results'][0]['id'] + relative_url = self.url + '{}/'.format(current_objects['results'][0]['id']) response = self.client.get(relative_url) self.assertEqual(200, response.status_code, response.content[:1000]) # sensitive data must be set to write_only so those are not returned in the response @@ -472,14 +472,14 @@ def test_detail(self): @skipIfNotSubclass(DestroyModelMixin) def test_delete(self): current_objects = self.client.get(self.url, format='json').data - relative_url = self.url + '%s/' % current_objects['results'][-1]['id'] + relative_url = self.url + '{}/'.format(current_objects['results'][-1]['id']) response = self.client.delete(relative_url) self.assertEqual(204, response.status_code, response.content[:1000]) @skipIfNotSubclass(UpdateModelMixin) def test_update(self): current_objects = self.client.get(self.url, format='json').data - relative_url = self.url + '%s/' % current_objects['results'][0]['id'] + relative_url = self.url + '{}/'.format(current_objects['results'][0]['id']) response = self.client.patch(relative_url, self.update_fields) self.assertEqual(200, response.status_code, response.content[:1000]) @@ -517,7 +517,7 @@ def test_update(self): @skipIfNotSubclass(DeletePreviewModelMixin) def test_delete_preview(self): current_objects = self.client.get(self.url, format='json').data - relative_url = self.url + '%s/delete_preview/' % current_objects['results'][0]['id'] + relative_url = self.url + '{}/delete_preview/'.format(current_objects['results'][0]['id']) response = self.client.get(relative_url) # print('delete_preview response.data') @@ -549,7 +549,7 @@ def test_detail_prefetch(self): prefetchable_fields = [x[0] for x in _get_prefetchable_fields(self.viewset.serializer_class)] current_objects = self.client.get(self.url, format='json').data - relative_url = self.url + '%s/' % current_objects['results'][0]['id'] + relative_url = self.url + '{}/'.format(current_objects['results'][0]['id']) response = self.client.get(relative_url, data={ "prefetch": ','.join(prefetchable_fields) }) @@ -637,7 +637,7 @@ def test_detail_object_not_authorized(self): self.setUp_not_authorized() current_objects = self.endpoint_model.objects.all() - relative_url = self.url + '%s/' % current_objects[0].id + relative_url = self.url + f'{current_objects[0].id}/' response = self.client.get(relative_url) self.assertEqual(404, response.status_code, response.content[:1000]) @@ -664,7 +664,7 @@ def test_delete_object_not_authorized(self, mock): mock.return_value = False current_objects = self.client.get(self.url, format='json').data - relative_url = self.url + '%s/' % current_objects['results'][0]['id'] + relative_url = self.url + '{}/'.format(current_objects['results'][0]['id']) self.client.delete(relative_url) if self.endpoint_model == Endpoint_Status: @@ -687,7 +687,7 @@ def test_update_object_not_authorized(self, mock): mock.return_value = False current_objects = self.client.get(self.url, format='json').data - relative_url = self.url + '%s/' % current_objects['results'][0]['id'] + relative_url = self.url + '{}/'.format(current_objects['results'][0]['id']) if self.endpoint_model == Endpoint_Status: permission_object = Endpoint.objects.get(id=current_objects['results'][0]['endpoint']) @@ -726,7 +726,7 @@ def test_detail_configuration_not_authorized(self): self.setUp_not_authorized() current_objects = self.endpoint_model.objects.all() - relative_url = self.url + '%s/' % current_objects[0].id + relative_url = self.url + f'{current_objects[0].id}/' response = self.client.get(relative_url) self.assertEqual(403, response.status_code, response.content[:1000]) @@ -748,7 +748,7 @@ def test_delete_configuration_not_authorized(self): self.setUp_not_authorized() current_objects = self.endpoint_model.objects.all() - relative_url = self.url + '%s/' % current_objects[0].id + relative_url = self.url + f'{current_objects[0].id}/' response = self.client.delete(relative_url) self.assertEqual(403, response.status_code, response.content[:1000]) @@ -760,7 +760,7 @@ def test_update_configuration_not_authorized(self): self.setUp_not_authorized() current_objects = self.endpoint_model.objects.all() - relative_url = self.url + '%s/' % current_objects[0].id + relative_url = self.url + f'{current_objects[0].id}/' response = self.client.patch(relative_url, self.update_fields) self.assertEqual(403, response.status_code, response.content[:1000]) @@ -774,7 +774,7 @@ def __init__(self, *args, **kwargs): def test_update(self): current_objects = self.client.get(self.url, format='json').data - relative_url = self.url + '%s/' % current_objects['results'][0]['id'] + relative_url = self.url + '{}/'.format(current_objects['results'][0]['id']) response = self.client.patch(relative_url, self.update_fields) self.assertEqual(405, response.status_code, response.content[:1000]) @@ -792,7 +792,7 @@ def test_update_object_not_authorized(self, mock): mock.return_value = False current_objects = self.client.get(self.url, format='json').data - relative_url = self.url + '%s/' % current_objects['results'][0]['id'] + relative_url = self.url + '{}/'.format(current_objects['results'][0]['id']) response = self.client.put(relative_url, self.payload) self.assertEqual(403, response.status_code, response.content[:1000]) @@ -822,7 +822,7 @@ def test_detail_configuration_not_authorized(self): self.setUp_not_authorized() current_objects = self.endpoint_model.objects.all() - relative_url = self.url + '%s/' % current_objects[0].id + relative_url = self.url + f'{current_objects[0].id}/' response = self.client.get(relative_url) self.assertEqual(200, response.status_code, response.content[:1000]) @@ -919,7 +919,7 @@ def test_update_patch_unsuccessful(self): 'finding': object2['finding'] } - relative_url = self.url + '%s/' % object1['id'] + relative_url = self.url + '{}/'.format(object1['id']) response = self.client.patch(relative_url, unsucessful_payload) self.assertEqual(400, response.status_code, response.content[:1000]) @@ -940,7 +940,7 @@ def test_update_put_unsuccessful(self): 'finding': object2['finding'] } - relative_url = self.url + '%s/' % object1['id'] + relative_url = self.url + '{}/'.format(object1['id']) response = self.client.put(relative_url, unsucessful_payload) self.assertEqual(400, response.status_code, response.content[:1000]) @@ -1073,7 +1073,7 @@ def test_update_forbidden_engagement(self): "notes": [] } current_objects = self.client.get(self.url, format='json').data - relative_url = self.url + '%s/' % current_objects['results'][0]['id'] + relative_url = self.url + '{}/'.format(current_objects['results'][0]['id']) response = self.client.put(relative_url, self.payload) self.assertEqual(403, response.status_code, response.content[:1000]) @@ -2480,7 +2480,7 @@ def test_detail_object_not_authorized(self): self.setUp_not_authorized() current_objects = self.endpoint_model.objects.all() - relative_url = self.url + '%s/' % current_objects[0].id + relative_url = self.url + f'{current_objects[0].id}/' response = self.client.get(relative_url) self.assertEqual(403, response.status_code, response.content[:1000]) @@ -2816,7 +2816,7 @@ def __init__(self, *args, **kwargs): def test_delete(self): current_objects = self.client.get(self.url, format='json').data - relative_url = self.url + '%s/' % current_objects['results'][-1]['id'] + relative_url = self.url + '{}/'.format(current_objects['results'][-1]['id']) response = self.client.delete(relative_url) self.assertEqual(409, response.status_code, response.content[:1000]) From 55ee81d942af56ca586ad804c777a806d6f570ae Mon Sep 17 00:00:00 2001 From: Paul Osinski <42211303+paulOsinski@users.noreply.github.com> Date: Wed, 1 May 2024 23:24:52 -0400 Subject: [PATCH 117/138] reformat example links from social-authentication.md (#10071) --- docs/content/en/integrations/social-authentication.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/content/en/integrations/social-authentication.md b/docs/content/en/integrations/social-authentication.md index 4856ec1777..a7cafe3806 100644 --- a/docs/content/en/integrations/social-authentication.md +++ b/docs/content/en/integrations/social-authentication.md @@ -15,7 +15,7 @@ leverage Auth0 to authenticate users on DefectDojo. 2. On the new application set the following fields: - Name: "Defectdojo" - Allowed Callback URLs: - [https://the_hostname_you_have_dojo_deployed:your_server_port/complete/auth0/](https://the_hostname_you_have_dojo_deployed:your_server_port/complete/auth0/) + **https://the_hostname_you_have_dojo_deployed:your_server_port/complete/auth0/** 3. Copy the following info from the application: - Domain - Client ID @@ -175,7 +175,7 @@ user, such as 'superuser'. - - **OR** - - [https://the_hostname_you_have_dojo_deployed:your_server_port/complete/azuread-tenant-oauth2/](https://the_hostname_you_have_dojo_deployed:your_server_port/complete/azuread-tenant-oauth2/) + - **https://the_hostname_you_have_dojo_deployed:your_server_port/complete/azuread-tenant-oauth2/** 4. Edit the settings (see [Configuration]({{< ref "/getting_started/configuration" >}})) with the following information: @@ -236,13 +236,13 @@ Follow along below. - - **OR** - - [https://the_hostname_you_have_gitlab_deployed:your_gitlab_port/profile/applications](https://the_hostname_you_have_gitlab_deployed:your_gitlab_port/profile/applications) + - **https://the_hostname_you_have_gitlab_deployed:your_gitlab_port/profile/applications** 2. Choose a name for your application 3. For the Redirect URI, enter the DefectDojo URL with the following format - - [https://the_hostname_you_have_dojo_deployed:your_server_port/complete/gitlab/](https://the_hostname_you_have_dojo_deployed:your_server_port/complete/gitlab/) + - **https://the_hostname_you_have_dojo_deployed:your_server_port/complete/gitlab/** 4. Edit the settings (see [Configuration]({{< ref "/getting_started/configuration" >}})) with the following information: @@ -331,7 +331,7 @@ Optionally, you *can* set `DD_SOCIAL_AUTH_KEYCLOAK_LOGIN_BUTTON_TEXT` in order t 2. Choose a name for your application 3. For the Redirect URI, enter the DefectDojo URL with the following format - - [https://the_hostname_you_have_dojo_deployed:your_server_port/complete/github-enterprise/](https://the_hostname_you_have_dojo_deployed:your_server_port/complete/github-enterprise/) + - **https://the_hostname_you_have_dojo_deployed:your_server_port/complete/github-enterprise/** 4. Edit the settings (see [Configuration]({{< ref "/getting_started/configuration" >}})) with the following information: {{< highlight python >}} From b3f13f21939b8bccca9d519b5d15236466e9b309 Mon Sep 17 00:00:00 2001 From: Paul Osinski <42211303+paulOsinski@users.noreply.github.com> Date: Wed, 1 May 2024 23:25:50 -0400 Subject: [PATCH 118/138] Create link_knowledge-base.md (#10075) Add a link to the DefectDojo Knowledge Base on the sidebar --- docs/content/en/link_knowledge-base.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 docs/content/en/link_knowledge-base.md diff --git a/docs/content/en/link_knowledge-base.md b/docs/content/en/link_knowledge-base.md new file mode 100644 index 0000000000..b7e7841e41 --- /dev/null +++ b/docs/content/en/link_knowledge-base.md @@ -0,0 +1,9 @@ +--- +title: "Knowledge Base" +manualLink: "https://support.defectdojo.com" +manualLinkTitle: "Open the DefectDojo Knowledge Base" +icon: fas fa-atlas +date: 2021-02-02T20:46:29+01:00 +weight: 1 +chapter: true +--- From b2854f509918b5fc484bea7a4177d5b0ca50961d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 22:29:01 -0500 Subject: [PATCH 119/138] chore(deps): update helm release rabbitmq from 11.16.2 to v14 (helm/defectdojo/chart.yaml) (#10069) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- helm/defectdojo/Chart.lock | 10 +++++----- helm/defectdojo/Chart.yaml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/helm/defectdojo/Chart.lock b/helm/defectdojo/Chart.lock index f02ae0074d..c243458332 100644 --- a/helm/defectdojo/Chart.lock +++ b/helm/defectdojo/Chart.lock @@ -4,15 +4,15 @@ dependencies: version: 9.19.1 - name: postgresql repository: https://charts.bitnami.com/bitnami - version: 15.2.5 + version: 15.2.7 - name: postgresql-ha repository: https://charts.bitnami.com/bitnami version: 9.4.11 - name: rabbitmq repository: https://charts.bitnami.com/bitnami - version: 11.16.2 + version: 14.1.0 - name: redis repository: https://charts.bitnami.com/bitnami - version: 19.1.3 -digest: sha256:2592451989dc8d0db275de473ec1fe041fbe2cba82ca19c76247b82954633e90 -generated: "2024-04-26T04:12:49.983759527Z" + version: 19.1.5 +digest: sha256:489bde31da1ba28130baef3c49292e052a50bbc3726de037b3778bdb091c7cad +generated: "2024-04-30T12:26:32.131451724Z" diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index 44e82816db..1e4e029d2c 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -23,7 +23,7 @@ dependencies: alias: postgresqlha condition: postgresqlha.enabled - name: rabbitmq - version: ~11.16.0 + version: ~14.1.0 repository: "https://charts.bitnami.com/bitnami" condition: rabbitmq.enabled - name: redis From aa8ee183a319ec13adc3b345938468bc03414aec Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Thu, 2 May 2024 05:50:52 +0200 Subject: [PATCH 120/138] add test description for AWS SecurityHub Scan (#9904) * add test description for AWS SecurityHub Scan * ruff, W293 * Update dojo/tools/awssecurityhub/parser.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * ruff --------- Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> --- dojo/tools/awssecurityhub/parser.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/dojo/tools/awssecurityhub/parser.py b/dojo/tools/awssecurityhub/parser.py index 54babccf73..b761bdd214 100644 --- a/dojo/tools/awssecurityhub/parser.py +++ b/dojo/tools/awssecurityhub/parser.py @@ -3,9 +3,11 @@ from dojo.tools.awssecurityhub.compliance import Compliance from dojo.tools.awssecurityhub.guardduty import GuardDuty from dojo.tools.awssecurityhub.inspector import Inspector +from dojo.tools.parser_test import ParserTest class AwsSecurityHubParser: + ID = "AWS Security Hub" def get_scan_types(self): return ["AWS Security Hub Scan"] @@ -16,6 +18,26 @@ def get_label_for_scan_types(self, scan_type): def get_description_for_scan_types(self, scan_type): return "AWS Security Hub exports in JSON format." + def get_tests(self, scan_type, scan): + data = json.load(scan) + findings = data.get("Findings", data.get("findings", None)) + if not isinstance(findings, list): + msg = "Incorrect Security Hub report format" + raise TypeError(msg) + prod = [] + aws_acc = [] + for finding in findings: + prod.append(finding.get("ProductName", "AWS Security Hub Ruleset")) + aws_acc.append(finding.get("AwsAccountId")) + report_date = data.get("createdAt") + test = ParserTest( + name=self.ID, type=self.ID, version="" + ) + test.description = "**AWS Accounts:** " + ', '.join(set(aws_acc)) + "\n" + test.description += "**Finding Origins:** " + ', '.join(set(prod)) + "\n" + test.findings = self.get_items(data, report_date) + return [test] + def get_findings(self, filehandle, test): tree = json.load(filehandle) if not isinstance(tree, dict): From 823f3ed01de76841c4e7219adf7aa69d012a4814 Mon Sep 17 00:00:00 2001 From: kiblik Date: Thu, 2 May 2024 19:31:48 +0200 Subject: [PATCH 121/138] RemoteUser: Hide from Swagger (#9961) --- dojo/remote_user.py | 3 +++ dojo/settings/settings.dist.py | 4 ++++ unittests/test_remote_user.py | 11 ++++++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/dojo/remote_user.py b/dojo/remote_user.py index 2576d9a284..ed48ce3190 100644 --- a/dojo/remote_user.py +++ b/dojo/remote_user.py @@ -100,6 +100,9 @@ class RemoteUserScheme(OpenApiAuthenticationExtension): priority = 1 def get_security_definition(self, auto_schema): + if not settings.AUTH_REMOTEUSER_VISIBLE_IN_SWAGGER: + return {} + header_name = settings.AUTH_REMOTEUSER_USERNAME_HEADER if header_name.startswith('HTTP_'): header_name = header_name[5:] diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index 2f4de7a9cf..48891b3662 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -181,6 +181,9 @@ DD_AUTH_REMOTEUSER_TRUSTED_PROXY=(list, ['127.0.0.1/32']), # REMOTE_USER will be processed only on login page. Check https://docs.djangoproject.com/en/3.2/howto/auth-remote-user/#using-remote-user-on-login-pages-only DD_AUTH_REMOTEUSER_LOGIN_ONLY=(bool, False), + # `RemoteUser` is usually used behind AuthN proxy and users should not know about this mechanism from Swagger because it is not usable by users. + # It should be hidden by default. + DD_AUTH_REMOTEUSER_VISIBLE_IN_SWAGGER=(bool, False), # if somebody is using own documentation how to use DefectDojo in his own company DD_DOCUMENTATION_URL=(str, 'https://documentation.defectdojo.com'), # merging findings doesn't always work well with dedupe and reimport etc. @@ -1045,6 +1048,7 @@ def saml2_attrib_map_format(dict): AUTH_REMOTEUSER_LASTNAME_HEADER = env('DD_AUTH_REMOTEUSER_LASTNAME_HEADER') AUTH_REMOTEUSER_GROUPS_HEADER = env('DD_AUTH_REMOTEUSER_GROUPS_HEADER') AUTH_REMOTEUSER_GROUPS_CLEANUP = env('DD_AUTH_REMOTEUSER_GROUPS_CLEANUP') +AUTH_REMOTEUSER_VISIBLE_IN_SWAGGER = env('DD_AUTH_REMOTEUSER_VISIBLE_IN_SWAGGER') AUTH_REMOTEUSER_TRUSTED_PROXY = IPSet() for ip_range in env('DD_AUTH_REMOTEUSER_TRUSTED_PROXY'): diff --git a/unittests/test_remote_user.py b/unittests/test_remote_user.py index 718c4913e3..c039e006db 100644 --- a/unittests/test_remote_user.py +++ b/unittests/test_remote_user.py @@ -200,11 +200,20 @@ def test_untrusted_proxy(self): @override_settings( AUTH_REMOTEUSER_ENABLED=True, AUTH_REMOTEUSER_USERNAME_HEADER="HTTP_OUR_REMOTE_USER", + AUTH_REMOTEUSER_VISIBLE_IN_SWAGGER=True, ) - def test_api_schema(self): + def test_api_schema_visible(self): security_definition = RemoteUserScheme.get_security_definition(None, None) self.assertEqual(security_definition, { "type": "apiKey", "in": "header", "name": "Our-remote-user", }) + + @override_settings( + AUTH_REMOTEUSER_ENABLED=True, + AUTH_REMOTEUSER_VISIBLE_IN_SWAGGER=False, + ) + def test_api_schema_hidden(self): + security_definition = RemoteUserScheme.get_security_definition(None, None) + self.assertEqual(security_definition, {}) From 7af5dcf5b0333155c7e38ae1c761458bc9bc06b3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 May 2024 15:45:59 -0500 Subject: [PATCH 122/138] Bump boto3 from 1.34.95 to 1.34.96 (#10096) Bumps [boto3](https://github.com/boto/boto3) from 1.34.95 to 1.34.96. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.34.95...1.34.96) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 41a4d946cc..a04a000cc4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -75,7 +75,7 @@ django-ratelimit==4.1.0 argon2-cffi==23.1.0 blackduck==1.1.3 pycurl==7.45.3 # Required for Celery Broker AWS (SQS) support -boto3==1.34.95 # Required for Celery Broker AWS (SQS) support +boto3==1.34.96 # Required for Celery Broker AWS (SQS) support netaddr==1.2.1 vulners==2.1.5 fontawesomefree==6.5.1 From 4b13d328b831a66a3aad59b5bf7f994d2d426be2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 May 2024 20:42:30 -0500 Subject: [PATCH 123/138] Bump ruff from 0.4.1 to 0.4.2 (#10042) Bumps [ruff](https://github.com/astral-sh/ruff) from 0.4.1 to 0.4.2. - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md) - [Commits](https://github.com/astral-sh/ruff/compare/v0.4.1...v0.4.2) --- updated-dependencies: - dependency-name: ruff dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-lint.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-lint.txt b/requirements-lint.txt index d0bc2a530a..79039f7bbc 100644 --- a/requirements-lint.txt +++ b/requirements-lint.txt @@ -1 +1 @@ -ruff==0.4.1 \ No newline at end of file +ruff==0.4.2 \ No newline at end of file From 6ad06a9b64485dd71b09466b0937d5dacd4dc3f1 Mon Sep 17 00:00:00 2001 From: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> Date: Thu, 2 May 2024 20:56:47 -0500 Subject: [PATCH 124/138] Importer + Reimport: Reorg, cleanup, comment (#10011) * First pass at base importer class * Further implementation and comments * Further implementation and comments * (untested) complete default importer * Importer clean up process_finding function * Complete import CBV (untested) * Importer: passing manual testing * Reimporter + auto create context manager (untested) * Completed testing by hand * Add missing tags patch * Correct some unit tests * Pass API tests * Complete reimport CBV * Fix URL mappings * Remove old importers * Correct missed import error * Remove testing cruft * Fix ruff * Remove extraneous comment * Fix flake 8 * Fix some copy/paste errors * Correcting unit tests * Remove lookups for a function called excessively * Fix ruff errors * More unit test fun * Fix ruff stuff * Flake8 * Fix typo * Fix conflicts * Fix quoting in unit test * Fix tests for real... * Some feedback * Fix oopsies * Fix some feedback * Typo * testing before comitting.. --- dojo/api_v2/permissions.py | 206 +++--- dojo/api_v2/serializers.py | 563 ++++++-------- dojo/api_v2/views.py | 114 +-- dojo/engagement/urls.py | 6 +- dojo/engagement/views.py | 611 ++++++++++----- dojo/forms.py | 53 +- dojo/importers/auto_create_context.py | 353 +++++++++ dojo/importers/base_importer.py | 940 ++++++++++++++++++++++++ dojo/importers/default_importer.py | 492 +++++++++++++ dojo/importers/default_reimporter.py | 877 ++++++++++++++++++++++ dojo/importers/endpoint_manager.py | 144 ++++ dojo/importers/importer/importer.py | 409 ----------- dojo/importers/reimporter/reimporter.py | 779 -------------------- dojo/importers/reimporter/utils.py | 263 ------- dojo/importers/utils.py | 209 ------ dojo/product/urls.py | 6 +- dojo/test/urls.py | 5 +- dojo/test/views.py | 440 +++++++---- unittests/test_importers_closeold.py | 109 +-- unittests/test_importers_importer.py | 176 ++--- unittests/test_rest_framework.py | 78 +- 21 files changed, 4087 insertions(+), 2746 deletions(-) create mode 100644 dojo/importers/auto_create_context.py create mode 100644 dojo/importers/base_importer.py create mode 100644 dojo/importers/default_importer.py create mode 100644 dojo/importers/default_reimporter.py create mode 100644 dojo/importers/endpoint_manager.py delete mode 100644 dojo/importers/importer/importer.py delete mode 100644 dojo/importers/reimporter/reimporter.py delete mode 100644 dojo/importers/reimporter/utils.py delete mode 100644 dojo/importers/utils.py diff --git a/dojo/api_v2/permissions.py b/dojo/api_v2/permissions.py index fc8e34d762..bf999ac635 100644 --- a/dojo/api_v2/permissions.py +++ b/dojo/api_v2/permissions.py @@ -8,23 +8,13 @@ ValidationError, ) -from dojo.api_v2.serializers import ( - get_import_meta_data_from_dict, - get_product_id_from_dict, -) from dojo.authorization.authorization import ( user_has_configuration_permission, user_has_global_permission, user_has_permission, ) from dojo.authorization.roles_permissions import Permissions -from dojo.importers.reimporter.utils import ( - get_target_engagement_if_exists, - get_target_product_by_id_if_exists, - get_target_product_if_exists, - get_target_product_type_if_exists, - get_target_test_if_exists, -) +from dojo.importers.auto_create_context import AutoCreateContextManager from dojo.models import ( Cred_Mapping, Dojo_Group, @@ -427,45 +417,39 @@ class UserHasImportPermission(permissions.BasePermission): def has_permission(self, request, view): # permission check takes place before validation, so we don't have access to serializer.validated_data() # and we have to validate ourselves unfortunately - - ( - _, - _, - _, - engagement_id, - engagement_name, - product_name, - product_type_name, - auto_create_context, - _deduplication_on_engagement, - _do_not_reactivate, - ) = get_import_meta_data_from_dict(request.data) - product_type = get_target_product_type_if_exists(product_type_name) - product = get_target_product_if_exists(product_name, product_type_name) - engagement = get_target_engagement_if_exists( - engagement_id, engagement_name, product - ) - - if engagement: + auto_create = AutoCreateContextManager() + # Process the context to make an conversions needed. Catch any exceptions + # in this case and wrap them in a DRF exception + try: + converted_dict = auto_create.convert_querydict_to_dict(request.data) + auto_create.process_import_meta_data_from_dict(converted_dict) + # Get an existing product + converted_dict["product_type"] = auto_create.get_target_product_type_if_exists(**converted_dict) + converted_dict["product"] = auto_create.get_target_product_if_exists(**converted_dict) + converted_dict["engagement"] = auto_create.get_target_engagement_if_exists(**converted_dict) + except (ValueError, TypeError) as e: + # Raise an explicit drf exception here + raise ValidationError(e) + if engagement := converted_dict.get("engagement"): # existing engagement, nothing special to check return user_has_permission( request.user, engagement, Permissions.Import_Scan_Result ) - elif engagement_id: + elif engagement_id := converted_dict.get("engagement_id"): # engagement_id doesn't exist - msg = f"Engagement '{engagement_id}' doesn't exist" + msg = f"Engagement \"{engagement_id}\" does not exist" raise serializers.ValidationError(msg) - if not auto_create_context: + if not converted_dict.get("auto_create_context"): raise_no_auto_create_import_validation_error( None, None, - engagement_name, - product_name, - product_type_name, - engagement, - product, - product_type, + converted_dict.get("engagement_name"), + converted_dict.get("product_name"), + converted_dict.get("product_type_name"), + converted_dict.get("engagement"), + converted_dict.get("product"), + converted_dict.get("product_type"), "Need engagement_id or product_name + engagement_name to perform import", ) else: @@ -473,12 +457,12 @@ def has_permission(self, request, view): # requested and is allowed to use auto_create return check_auto_create_permission( request.user, - product, - product_name, - engagement, - engagement_name, - product_type, - product_type_name, + converted_dict.get("product"), + converted_dict.get("product_name"), + converted_dict.get("engagement"), + converted_dict.get("engagement_name"), + converted_dict.get("product_type"), + converted_dict.get("product_type_name"), "Need engagement_id or product_name + engagement_name to perform import", ) @@ -487,32 +471,28 @@ class UserHasMetaImportPermission(permissions.BasePermission): def has_permission(self, request, view): # permission check takes place before validation, so we don't have access to serializer.validated_data() # and we have to validate ourselves unfortunately - - ( - _, - _, - _, - _, - _, - product_name, - _, - _, - _, - _, - ) = get_import_meta_data_from_dict(request.data) - product = get_target_product_if_exists(product_name) - if not product: - product_id = get_product_id_from_dict(request.data) - product = get_target_product_by_id_if_exists(product_id) + auto_create = AutoCreateContextManager() + # Process the context to make an conversions needed. Catch any exceptions + # in this case and wrap them in a DRF exception + try: + converted_dict = auto_create.convert_querydict_to_dict(request.data) + auto_create.process_import_meta_data_from_dict(converted_dict) + # Get an existing product + product = auto_create.get_target_product_if_exists(**converted_dict) + if not product: + product = auto_create.get_target_product_by_id_if_exists(**converted_dict) + except (ValueError, TypeError) as e: + # Raise an explicit drf exception here + raise ValidationError(e) if product: # existing product, nothing special to check return user_has_permission( request.user, product, Permissions.Import_Scan_Result ) - elif product_id: + elif product_id := converted_dict.get("product_id"): # product_id doesn't exist - msg = f"product '{product_id}' doesn't exist" + msg = f"Product \"{product_id}\" does not exist" raise serializers.ValidationError(msg) else: msg = "Need product_id or product_name to perform import" @@ -631,49 +611,41 @@ class UserHasReimportPermission(permissions.BasePermission): def has_permission(self, request, view): # permission check takes place before validation, so we don't have access to serializer.validated_data() # and we have to validate ourselves unfortunately - - ( - test_id, - test_title, - scan_type, - _, - engagement_name, - product_name, - product_type_name, - auto_create_context, - _deduplication_on_engagement, - _do_not_reactivate, - ) = get_import_meta_data_from_dict(request.data) - - product_type = get_target_product_type_if_exists(product_type_name) - product = get_target_product_if_exists(product_name, product_type_name) - engagement = get_target_engagement_if_exists( - None, engagement_name, product - ) - test = get_target_test_if_exists( - test_id, test_title, scan_type, engagement - ) - - if test: + auto_create = AutoCreateContextManager() + # Process the context to make an conversions needed. Catch any exceptions + # in this case and wrap them in a DRF exception + try: + converted_dict = auto_create.convert_querydict_to_dict(request.data) + auto_create.process_import_meta_data_from_dict(converted_dict) + # Get an existing product + converted_dict["product_type"] = auto_create.get_target_product_type_if_exists(**converted_dict) + converted_dict["product"] = auto_create.get_target_product_if_exists(**converted_dict) + converted_dict["engagement"] = auto_create.get_target_engagement_if_exists(**converted_dict) + converted_dict["test"] = auto_create.get_target_test_if_exists(**converted_dict) + except (ValueError, TypeError) as e: + # Raise an explicit drf exception here + raise ValidationError(e) + + if test := converted_dict.get("test"): # existing test, nothing special to check return user_has_permission( request.user, test, Permissions.Import_Scan_Result ) - elif test_id: + elif test_id := converted_dict.get("test_id"): # test_id doesn't exist - msg = f"Test '{test_id}' doesn't exist" + msg = f"Test \"{test_id}\" does not exist" raise serializers.ValidationError(msg) - if not auto_create_context: + if not converted_dict.get("auto_create_context"): raise_no_auto_create_import_validation_error( - test_title, - scan_type, - engagement_name, - product_name, - product_type_name, - engagement, - product, - product_type, + converted_dict.get("test_title"), + converted_dict.get("scan_type"), + converted_dict.get("engagement_name"), + converted_dict.get("product_name"), + converted_dict.get("product_type_name"), + converted_dict.get("engagement"), + converted_dict.get("product"), + converted_dict.get("product_type"), "Need test_id or product_name + engagement_name + scan_type to perform reimport", ) else: @@ -681,12 +653,12 @@ def has_permission(self, request, view): # requested and is allowed to use auto_create return check_auto_create_permission( request.user, - product, - product_name, - engagement, - engagement_name, - product_type, - product_type_name, + converted_dict.get("product"), + converted_dict.get("product_name"), + converted_dict.get("engagement"), + converted_dict.get("engagement_name"), + converted_dict.get("product_type"), + converted_dict.get("product_type_name"), "Need test_id or product_name + engagement_name + scan_type to perform reimport", ) @@ -955,28 +927,28 @@ def raise_no_auto_create_import_validation_error( raise ValidationError(msg) if product_type_name and not product_type: - msg = f"Product Type '{product_type_name}' doesn't exist" + msg = f"Product Type \"{product_type_name}\" does not exist" raise serializers.ValidationError(msg) if product_name and not product: if product_type_name: - msg = f"Product '{product_name}' doesn't exist in Product_Type '{product_type_name}'" + msg = f"Product \"{product_name}\" does not exist in Product_Type \"{product_type_name}\"" raise serializers.ValidationError(msg) else: - msg = f"Product '{product_name}' doesn't exist" + msg = f"Product \"{product_name}\" does not exist" raise serializers.ValidationError(msg) if engagement_name and not engagement: - msg = f"Engagement '{engagement_name}' doesn't exist in Product '{product_name}'" + msg = f"Engagement \"{engagement_name}\" does not exist in Product \"{product_name}\"" raise serializers.ValidationError(msg) # these are only set for reimport if test_title: - msg = f"Test '{test_title}' with scan_type '{scan_type}' doesn't exist in Engagement '{engagement_name}'" + msg = f"Test \"{test_title}\" with scan_type \"{scan_type}\" does not exist in Engagement \"{engagement_name}\"" raise serializers.ValidationError(msg) if scan_type: - msg = f"Test with scan_type '{scan_type}' doesn't exist in Engagement '{engagement_name}'" + msg = f"Test with scan_type \"{scan_type}\" does not exist in Engagement \"{engagement_name}\"" raise serializers.ValidationError(msg) raise ValidationError(error_message) @@ -1023,13 +995,13 @@ def check_auto_create_permission( if product and product_name and engagement_name: if not user_has_permission(user, product, Permissions.Engagement_Add): - msg = f"No permission to create engagements in product '{product_name}'" + msg = f"No permission to create engagements in product \"{product_name}\"" raise PermissionDenied(msg) if not user_has_permission( user, product, Permissions.Import_Scan_Result ): - msg = f"No permission to import scans into product '{product_name}'" + msg = f"No permission to import scans into product \"{product_name}\"" raise PermissionDenied(msg) # all good @@ -1037,14 +1009,14 @@ def check_auto_create_permission( if not product and product_name: if not product_type_name: - msg = f"Product '{product_name}' doesn't exist and no product_type_name provided to create the new product in" + msg = f"Product \"{product_name}\" does not exist and no product_type_name provided to create the new product in" raise serializers.ValidationError(msg) if not product_type: if not user_has_global_permission( user, Permissions.Product_Type_Add ): - msg = f"No permission to create product_type '{product_type_name}'" + msg = f"No permission to create product_type \"{product_type_name}\"" raise PermissionDenied(msg) # new product type can be created with current user as owner, so # all objects in it can be created as well @@ -1053,7 +1025,7 @@ def check_auto_create_permission( if not user_has_permission( user, product_type, Permissions.Product_Type_Add_Product ): - msg = f"No permission to create products in product_type '{product_type}'" + msg = f"No permission to create products in product_type \"{product_type}\"" raise PermissionDenied(msg) # product can be created, so objects in it can be created as well diff --git a/dojo/api_v2/serializers.py b/dojo/api_v2/serializers.py index 3eb65b18bc..c8ab20cc33 100644 --- a/dojo/api_v2/serializers.py +++ b/dojo/api_v2/serializers.py @@ -29,17 +29,10 @@ ) from dojo.finding.queries import get_authorized_findings from dojo.group.utils import get_auth_group_name -from dojo.importers.importer.importer import DojoDefaultImporter as Importer -from dojo.importers.reimporter.reimporter import ( - DojoDefaultReImporter as ReImporter, -) -from dojo.importers.reimporter.utils import ( - get_or_create_engagement, - get_target_engagement_if_exists, - get_target_product_by_id_if_exists, - get_target_product_if_exists, - get_target_test_if_exists, -) +from dojo.importers.auto_create_context import AutoCreateContextManager +from dojo.importers.base_importer import BaseImporter +from dojo.importers.default_importer import DefaultImporter +from dojo.importers.default_reimporter import DefaultReImporter from dojo.models import ( DEFAULT_NOTIFICATION, IMPORT_ACTIONS, @@ -126,52 +119,6 @@ deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") -def get_import_meta_data_from_dict(data): - test_id = data.get("test", None) - if test_id: - if isinstance(test_id, Test): - test_id = test_id.id - elif isinstance(test_id, str) and not test_id.isdigit(): - msg = "test must be an integer" - raise serializers.ValidationError(msg) - - scan_type = data.get("scan_type", None) - - test_title = data.get("test_title", None) - - engagement_id = data.get("engagement", None) - if engagement_id: - if isinstance(engagement_id, Engagement): - engagement_id = engagement_id.id - elif isinstance(engagement_id, str) and not engagement_id.isdigit(): - msg = "engagement must be an integer" - raise serializers.ValidationError(msg) - - engagement_name = data.get("engagement_name", None) - - product_name = data.get("product_name", None) - product_type_name = data.get("product_type_name", None) - - auto_create_context = data.get("auto_create_context", None) - - deduplication_on_engagement = data.get( - "deduplication_on_engagement", False - ) - do_not_reactivate = data.get("do_not_reactivate", False) - return ( - test_id, - test_title, - scan_type, - engagement_id, - engagement_name, - product_name, - product_type_name, - auto_create_context, - deduplication_on_engagement, - do_not_reactivate, - ) - - def get_product_id_from_dict(data): product_id = data.get("product", None) if product_id: @@ -261,7 +208,7 @@ def to_internal_value(self, data): except ValueError: self.fail("invalid_json") - logger.debug("data as json: %s", data) + logger.debug(f"data as json: {data}") if not isinstance(data, list): self.fail("not_a_list", input_type=type(data).__name__) @@ -2072,7 +2019,6 @@ class ImportScanSerializer(serializers.Serializer): help_text="The IP address, host name or full URL. It must be valid", ) file = serializers.FileField(allow_empty_file=True, required=False) - product_type_name = serializers.CharField(required=False) product_name = serializers.CharField(required=False) engagement_name = serializers.CharField(required=False) @@ -2134,7 +2080,6 @@ class ImportScanSerializer(serializers.Serializer): "This is an optional field which is used in deduplication and closing of old findings when set. " "This affects the whole engagement/product depending on your deduplication scope.", ) - group_by = serializers.ChoiceField( required=False, choices=Finding_Group.GROUP_BY_OPTIONS, @@ -2145,7 +2090,6 @@ class ImportScanSerializer(serializers.Serializer): required=False, default=True, ) - # extra fields populated in response # need to use the _id suffix as without the serializer framework gets # confused @@ -2156,7 +2100,6 @@ class ImportScanSerializer(serializers.Serializer): engagement_id = serializers.IntegerField(read_only=True) product_id = serializers.IntegerField(read_only=True) product_type_id = serializers.IntegerField(read_only=True) - statistics = ImportStatisticsSerializer(read_only=True, required=False) apply_tags_to_findings = serializers.BooleanField( help_text="If set to True, the tags will be applied to the findings", @@ -2167,135 +2110,106 @@ class ImportScanSerializer(serializers.Serializer): required=False, ) - def save(self, push_to_jira=False): - data = self.validated_data - close_old_findings = data.get("close_old_findings") - close_old_findings_product_scope = data.get( - "close_old_findings_product_scope" - ) - minimum_severity = data.get("minimum_severity") - endpoint_to_add = data.get("endpoint_to_add") - scan_date = data.get("scan_date", None) - # Will save in the provided environment or in the `Development` one if - # absent - version = data.get("version", None) - build_id = data.get("build_id", None) - branch_tag = data.get("branch_tag", None) - commit_hash = data.get("commit_hash", None) - api_scan_configuration = data.get("api_scan_configuration", None) - service = data.get("service", None) - apply_tags_to_findings = data.get("apply_tags_to_findings", False) - apply_tags_to_endpoints = data.get("apply_tags_to_endpoints", False) - source_code_management_uri = data.get( - "source_code_management_uri", None + def set_context( + self, + data: dict, + ) -> dict: + """ + Process all of the user supplied inputs to massage them into the correct + format the importer is expecting to see + """ + context = dict(data) + # update some vars + context["scan"] = data.get("file", None) + context["environment"] = Development_Environment.objects.get( + name=data.get("environment", "Development") ) - + # Set the active/verified status based upon the overrides if "active" in self.initial_data: - active = data.get("active") + context["active"] = data.get("active") else: - active = None + context["active"] = None if "verified" in self.initial_data: - verified = data.get("verified") + context["verified"] = data.get("verified") else: - verified = None - - environment_name = data.get("environment", "Development") - environment = Development_Environment.objects.get( - name=environment_name - ) - tags = data.get("tags", None) + context["verified"] = None + # Change the way that endpoints are sent to the importer + if endpoints_to_add := data.get("endpoint_to_add"): + context["endpoints_to_add"] = [endpoints_to_add] + else: + context["endpoint_to_add"] = None # Convert the tags to a list if needed. At this point, the # TaggitListSerializer has already removed commas supplied # by the user, so this operation will consistently return # a list to be used by the importer - if isinstance(tags, str): - tags = tags.split(", ") - lead = data.get("lead") - - scan = data.get("file", None) - endpoints_to_add = [endpoint_to_add] if endpoint_to_add else None - - group_by = data.get("group_by", None) - create_finding_groups_for_all_findings = data.get( - "create_finding_groups_for_all_findings", True - ) - - engagement_end_date = data.get("engagement_end_date", None) - ( - _, - test_title, - scan_type, - engagement_id, - engagement_name, - product_name, - product_type_name, - auto_create_context, - deduplication_on_engagement, - _do_not_reactivate, - ) = get_import_meta_data_from_dict(data) - engagement = get_or_create_engagement( - engagement_id, - engagement_name, - product_name, - product_type_name, - auto_create_context, - deduplication_on_engagement, - source_code_management_uri=source_code_management_uri, - target_end=engagement_end_date, - ) - + if tags := context.get("tags"): + if isinstance(tags, str): + context["tags"] = tags.split(", ") # have to make the scan_date_time timezone aware otherwise uploads via # the API would fail (but unit tests for api upload would pass...) - scan_date_time = ( + context["scan_date"] = ( timezone.make_aware( - datetime.combine(scan_date, datetime.min.time()) + datetime.combine(context.get("scan_date"), datetime.min.time()) ) - if scan_date + if context.get("scan_date") else None ) - importer = Importer() + # Process the auto create context inputs + self.process_auto_create_create_context(context) + + return context + + def process_auto_create_create_context( + self, + context: dict, + ) -> None: + """ + Extract all of the pertinent args used to auto create any product + types, products, or engagements. This function will also validate + those inputs for any required info that is not present. In the event + of an error, an exception will be raised and bubble up to the user + """ + auto_create = AutoCreateContextManager() + # Process the context to make an conversions needed. Catch any exceptions + # in this case and wrap them in a DRF exception try: - ( - test, - _finding_count, - _closed_finding_count, - _test_import, - ) = importer.import_scan( - scan, - scan_type, - engagement, - lead, - environment, - active=active, - verified=verified, - tags=tags, - minimum_severity=minimum_severity, - endpoints_to_add=endpoints_to_add, - scan_date=scan_date_time, - version=version, - branch_tag=branch_tag, - build_id=build_id, - commit_hash=commit_hash, - push_to_jira=push_to_jira, - close_old_findings=close_old_findings, - close_old_findings_product_scope=close_old_findings_product_scope, - group_by=group_by, - api_scan_configuration=api_scan_configuration, - service=service, - title=test_title, - create_finding_groups_for_all_findings=create_finding_groups_for_all_findings, - apply_tags_to_findings=apply_tags_to_findings, - apply_tags_to_endpoints=apply_tags_to_endpoints, + auto_create.process_import_meta_data_from_dict(context) + # Attempt to create an engagement + context["engagement"] = auto_create.get_or_create_engagement(**context) + except (ValueError, TypeError) as e: + # Raise an explicit drf exception here + raise ValidationError(str(e)) + + def get_importer(self) -> BaseImporter: + """ + Returns a new instance of an importer that extends + the BaseImporter class + """ + return DefaultImporter() + + def process_scan( + self, + data: dict, + context: dict + ) -> None: + """ + Process the scan with all of the supplied data fully massaged + into the format we are expecting + + Raises exceptions in the event of an error + """ + try: + context["test"], _, _, _, _, _, _ = self.get_importer().process_scan( + **context, ) - - if test: + # Update the response body with some new data + if test := context.get("test"): data["test"] = test.id data["test_id"] = test.id data["engagement_id"] = test.engagement.id data["product_id"] = test.engagement.product.id data["product_type_id"] = test.engagement.product.prod_type.id data["statistics"] = {"after": test.statistics} - # convert to exception otherwise django rest framework will swallow them as 400 error # exceptions are already logged in the importer except SyntaxError as se: @@ -2303,7 +2217,17 @@ def save(self, push_to_jira=False): except ValueError as ve: raise Exception(ve) - def validate(self, data): + def save(self, push_to_jira=False): + # Go through the validate method + data = self.validated_data + # Extract the data from the form + context = self.set_context(data) + # set the jira option again as it was overridden + context["push_to_jira"] = push_to_jira + # Import the scan with all of the supplied data + self.process_scan(data, context) + + def validate(self, data: dict) -> dict: scan_type = data.get("scan_type") file = data.get("file") if not file and requires_file(scan_type): @@ -2324,7 +2248,7 @@ def validate(self, data): raise serializers.ValidationError(msg) return data - def validate_scan_date(self, value): + def validate_scan_date(self, value: str) -> None: if value and value > timezone.localdate(): msg = "The scan_date cannot be in the future!" raise serializers.ValidationError(msg) @@ -2458,186 +2382,118 @@ class ReImportScanSerializer(TaggitSerializer, serializers.Serializer): required=False, ) - def save(self, push_to_jira=False): - logger.debug("push_to_jira: %s", push_to_jira) - data = self.validated_data - scan_type = data.get("scan_type") - endpoint_to_add = data.get("endpoint_to_add") - minimum_severity = data.get("minimum_severity") - scan_date = data.get("scan_date", None) - close_old_findings = data.get("close_old_findings") - close_old_findings_product_scope = data.get( - "close_old_findings_product_scope" - ) - apply_tags_to_findings = data.get("apply_tags_to_findings", False) - apply_tags_to_endpoints = data.get("apply_tags_to_endpoints", False) - do_not_reactivate = data.get("do_not_reactivate", False) - version = data.get("version", None) - build_id = data.get("build_id", None) - branch_tag = data.get("branch_tag", None) - commit_hash = data.get("commit_hash", None) - api_scan_configuration = data.get("api_scan_configuration", None) - service = data.get("service", None) - lead = data.get("lead", None) - tags = data.get("tags", None) - # Convert the tags to a list if needed. At this point, the - # TaggitListSerializer has already removed commas supplied - # by the user, so this operation will consistently return - # a list to be used by the importer - if isinstance(tags, str): - tags = tags.split(", ") - environment_name = data.get("environment", "Development") - environment = Development_Environment.objects.get( - name=environment_name - ) - scan = data.get("file", None) - endpoints_to_add = [endpoint_to_add] if endpoint_to_add else None - source_code_management_uri = data.get( - "source_code_management_uri", None + def set_context( + self, + data: dict, + ) -> dict: + """ + Process all of the user supplied inputs to massage them into the correct + format the importer is expecting to see + """ + context = dict(data) + # update some vars + context["scan"] = data.get("file", None) + context["environment"] = Development_Environment.objects.get( + name=data.get("environment", "Development") ) - engagement_end_date = data.get("engagement_end_date", None) - + # Set the active/verified status based upon the overrides if "active" in self.initial_data: - active = data.get("active") + context["active"] = data.get("active") else: - active = None + context["active"] = None if "verified" in self.initial_data: - verified = data.get("verified") + context["verified"] = data.get("verified") else: - verified = None - - group_by = data.get("group_by", None) - create_finding_groups_for_all_findings = data.get( - "create_finding_groups_for_all_findings", True - ) - - ( - test_id, - test_title, - scan_type, - _, - engagement_name, - product_name, - product_type_name, - auto_create_context, - deduplication_on_engagement, - do_not_reactivate, - ) = get_import_meta_data_from_dict(data) - # we passed validation, so the test is present - product = get_target_product_if_exists(product_name) - engagement = get_target_engagement_if_exists( - None, engagement_name, product - ) - test = get_target_test_if_exists( - test_id, test_title, scan_type, engagement - ) - + context["verified"] = None + # Change the way that endpoints are sent to the importer + if endpoints_to_add := data.get("endpoint_to_add"): + context["endpoints_to_add"] = [endpoints_to_add] + else: + context["endpoint_to_add"] = None + # Convert the tags to a list if needed. At this point, the + # TaggitListSerializer has already removed commas supplied + # by the user, so this operation will consistently return + # a list to be used by the importer + if tags := context.get("tags"): + if isinstance(tags, str): + context["tags"] = tags.split(", ") # have to make the scan_date_time timezone aware otherwise uploads via # the API would fail (but unit tests for api upload would pass...) - scan_date_time = ( + context["scan_date"] = ( timezone.make_aware( - datetime.combine(scan_date, datetime.min.time()) + datetime.combine(context.get("scan_date"), datetime.min.time()) ) - if scan_date + if context.get("scan_date") else None ) - statistics_before, statistics_delta = None, None + return context + + def process_auto_create_create_context( + self, + auto_create_manager: AutoCreateContextManager, + context: dict, + ) -> None: + """ + Extract all of the pertinent args used to auto create any product + types, products, or engagements. This function will also validate + those inputs for any required info that is not present. In the event + of an error, an exception will be raised and bubble up to the user + """ + # Process the context to make an conversions needed. Catch any exceptions + # in this case and wrap them in a DRF exception + try: + auto_create_manager.process_import_meta_data_from_dict(context) + context["product"] = auto_create_manager.get_target_product_if_exists(**context) + context["engagement"] = auto_create_manager.get_target_engagement_if_exists(**context) + context["test"] = auto_create_manager.get_target_test_if_exists(**context) + except (ValueError, TypeError) as e: + # Raise an explicit drf exception here + raise ValidationError(str(e)) + + def get_importer(self) -> BaseImporter: + """ + Returns a new instance of an importer that extends + the BaseImporter class + """ + return DefaultImporter() + + def get_reimporter(self) -> BaseImporter: + """ + Returns a new instance of a reimporter that extends + the BaseImporter class + """ + return DefaultReImporter() + + def process_scan( + self, + auto_create_manager: AutoCreateContextManager, + data: dict, + context: dict, + ) -> None: + """ + Process the scan with all of the supplied data fully massaged + into the format we are expecting + + Raises exceptions in the event of an error + """ + statistics_before, statistics_delta = None, None try: - if test: - # reimport into provided / latest test + if test := context.get("test"): statistics_before = test.statistics - reimporter = ReImporter() - ( - test, - _finding_count, - _new_finding_count, - _closed_finding_count, - _reactivated_finding_count, - _untouched_finding_count, - test_import, - ) = reimporter.reimport_scan( - scan, - scan_type, - test, - active=active, - verified=verified, - tags=tags, - minimum_severity=minimum_severity, - endpoints_to_add=endpoints_to_add, - scan_date=scan_date_time, - version=version, - branch_tag=branch_tag, - build_id=build_id, - commit_hash=commit_hash, - push_to_jira=push_to_jira, - close_old_findings=close_old_findings, - group_by=group_by, - api_scan_configuration=api_scan_configuration, - service=service, - do_not_reactivate=do_not_reactivate, - create_finding_groups_for_all_findings=create_finding_groups_for_all_findings, - apply_tags_to_findings=apply_tags_to_findings, - apply_tags_to_endpoints=apply_tags_to_endpoints, - ) - + context["test"], _, _, _, _, _, test_import = self.get_reimporter().process_scan(**context) if test_import: statistics_delta = test_import.statistics - elif auto_create_context: - # perform Import to create test - logger.debug( - "reimport for non-existing test, using import to create new test" - ) - engagement = get_or_create_engagement( - None, - engagement_name, - product_name, - product_type_name, - auto_create_context, - deduplication_on_engagement, - source_code_management_uri=source_code_management_uri, - target_end=engagement_end_date, - ) - importer = Importer() - ( - test, - _finding_count, - _closed_finding_count, - _, - ) = importer.import_scan( - scan, - scan_type, - engagement, - lead, - environment, - active=active, - verified=verified, - tags=tags, - minimum_severity=minimum_severity, - endpoints_to_add=endpoints_to_add, - scan_date=scan_date_time, - version=version, - branch_tag=branch_tag, - build_id=build_id, - commit_hash=commit_hash, - push_to_jira=push_to_jira, - close_old_findings=close_old_findings, - close_old_findings_product_scope=close_old_findings_product_scope, - group_by=group_by, - api_scan_configuration=api_scan_configuration, - service=service, - title=test_title, - create_finding_groups_for_all_findings=create_finding_groups_for_all_findings, - apply_tags_to_findings=apply_tags_to_findings, - apply_tags_to_endpoints=apply_tags_to_endpoints, - ) - + elif context.get("auto_create_context"): + # Attempt to create an engagement + logger.debug("reimport for non-existing test, using import to create new test") + context["engagement"] = auto_create_manager.get_or_create_engagement(**context) + context["test"], _, _, _, _, _, _ = self.get_importer().process_scan(**context) else: - # should be captured by validation / permission check already - msg = "test not found" + msg = "A test could not be found!" raise NotFound(msg) - - if test: + # Update the response body with some new data + if test := context.get("test"): data["test"] = test data["test_id"] = test.id data["engagement_id"] = test.engagement.id @@ -2649,7 +2505,6 @@ def save(self, push_to_jira=False): if statistics_delta: data["statistics"]["delta"] = statistics_delta data["statistics"]["after"] = test.statistics - # convert to exception otherwise django rest framework will swallow them as 400 error # exceptions are already logged in the importer except SyntaxError as se: @@ -2657,6 +2512,19 @@ def save(self, push_to_jira=False): except ValueError as ve: raise Exception(ve) + def save(self, push_to_jira=False): + # Go through the validate method + data = self.validated_data + # Extract the data from the form + context = self.set_context(data) + # set the jira option again as it was overridden + context["push_to_jira"] = push_to_jira + # Process the auto create context inputs + auto_create_manager = AutoCreateContextManager() + self.process_auto_create_create_context(auto_create_manager, context) + # Import the scan with all of the supplied data + self.process_scan(auto_create_manager, data, context) + def validate(self, data): scan_type = data.get("scan_type") file = data.get("file") @@ -2710,27 +2578,22 @@ def validate(self, data): def save(self): data = self.validated_data file = data.get("file") - create_endpoints = data.get("create_endpoints", True) create_tags = data.get("create_tags", True) create_dojo_meta = data.get("create_dojo_meta", False) + auto_create = AutoCreateContextManager() + # Process the context to make an conversions needed. Catch any exceptions + # in this case and wrap them in a DRF exception + try: + auto_create.process_import_meta_data_from_dict(data) + # Get an existing product + product = auto_create.get_target_product_if_exists(**data) + if not product: + product = auto_create.get_target_product_by_id_if_exists(**data) + except (ValueError, TypeError) as e: + # Raise an explicit drf exception here + raise ValidationError(str(e)) - ( - _, - _, - _, - _, - _, - product_name, - _, - _, - _, - _, - ) = get_import_meta_data_from_dict(data) - product = get_target_product_if_exists(product_name) - if not product: - product_id = get_product_id_from_dict(data) - product = get_target_product_by_id_if_exists(product_id) try: endpoint_meta_import( file, diff --git a/dojo/api_v2/views.py b/dojo/api_v2/views.py index 38abf945c7..9b5239f011 100644 --- a/dojo/api_v2/views.py +++ b/dojo/api_v2/views.py @@ -73,11 +73,7 @@ get_authorized_group_members, get_authorized_groups, ) -from dojo.importers.reimporter.utils import ( - get_target_engagement_if_exists, - get_target_product_if_exists, - get_target_test_if_exists, -) +from dojo.importers.auto_create_context import AutoCreateContextManager from dojo.jira_link.queries import ( get_authorized_jira_issues, get_authorized_jira_projects, @@ -2604,41 +2600,27 @@ class ImportScanView(mixins.CreateModelMixin, viewsets.GenericViewSet): permission_classes = (IsAuthenticated, permissions.UserHasImportPermission) def perform_create(self, serializer): - ( - _, - _, - _, - engagement_id, - engagement_name, - product_name, - _product_type_name, - _auto_create_context, - _deduplication_on_engagement, - _do_not_reactivate, - ) = serializers.get_import_meta_data_from_dict( - serializer.validated_data - ) - product = get_target_product_if_exists(product_name) - engagement = get_target_engagement_if_exists( - engagement_id, engagement_name, product - ) + auto_create = AutoCreateContextManager() + # Process the context to make an conversions needed. Catch any exceptions + # in this case and wrap them in a DRF exception + try: + converted_dict = auto_create.convert_querydict_to_dict(serializer.validated_data) + auto_create.process_import_meta_data_from_dict(converted_dict) + # Get an existing product + product = auto_create.get_target_product_if_exists(**converted_dict) + engagement = auto_create.get_target_engagement_if_exists(**converted_dict) + except (ValueError, TypeError) as e: + # Raise an explicit drf exception here + raise ValidationError(str(e)) # when using auto_create_context, the engagement or product may not # have been created yet - jira_driver = ( - engagement if engagement else product if product else None - ) - jira_project = ( - jira_helper.get_jira_project(jira_driver) if jira_driver else None - ) - push_to_jira = serializer.validated_data.get("push_to_jira") - if get_system_setting("enable_jira") and jira_project: - push_to_jira = push_to_jira or jira_project.push_all_issues - - logger.debug( - "push_to_jira: %s", serializer.validated_data.get("push_to_jira") - ) + if get_system_setting("enable_jira"): + jira_driver = (engagement if engagement else product if product else None) + if jira_project := (jira_helper.get_jira_project(jira_driver) if jira_driver else None): + push_to_jira = push_to_jira or jira_project.push_all_issues + logger.debug(f"push_to_jira: {push_to_jira}") serializer.save(push_to_jira=push_to_jira) def get_queryset(self): @@ -2783,50 +2765,30 @@ def get_queryset(self): return get_authorized_tests(Permissions.Import_Scan_Result) def perform_create(self, serializer): - ( - test_id, - test_title, - scan_type, - _, - engagement_name, - product_name, - _product_type_name, - _auto_create_context, - _deduplication_on_engagement, - _do_not_reactivate, - ) = serializers.get_import_meta_data_from_dict( - serializer.validated_data - ) - product = get_target_product_if_exists(product_name) - engagement = get_target_engagement_if_exists( - None, engagement_name, product - ) - test = get_target_test_if_exists( - test_id, test_title, scan_type, engagement - ) + auto_create = AutoCreateContextManager() + # Process the context to make an conversions needed. Catch any exceptions + # in this case and wrap them in a DRF exception + try: + converted_dict = auto_create.convert_querydict_to_dict(serializer.validated_data) + auto_create.process_import_meta_data_from_dict(converted_dict) + # Get an existing product + product = auto_create.get_target_product_if_exists(**converted_dict) + engagement = auto_create.get_target_engagement_if_exists(**converted_dict) + test = auto_create.get_target_test_if_exists(**converted_dict) + except (ValueError, TypeError) as e: + # Raise an explicit drf exception here + raise ValidationError(str(e)) # when using auto_create_context, the engagement or product may not # have been created yet - jira_driver = ( - test - if test - else engagement - if engagement - else product - if product - else None - ) - jira_project = ( - jira_helper.get_jira_project(jira_driver) if jira_driver else None - ) - push_to_jira = serializer.validated_data.get("push_to_jira") - if get_system_setting("enable_jira") and jira_project: - push_to_jira = push_to_jira or jira_project.push_all_issues - - logger.debug( - "push_to_jira: %s", serializer.validated_data.get("push_to_jira") - ) + if get_system_setting("enable_jira"): + jira_driver = ( + test if test else engagement if engagement else product if product else None + ) + if jira_project := (jira_helper.get_jira_project(jira_driver) if jira_driver else None): + push_to_jira = push_to_jira or jira_project.push_all_issues + logger.debug(f"push_to_jira: {push_to_jira}") serializer.save(push_to_jira=push_to_jira) diff --git a/dojo/engagement/urls.py b/dojo/engagement/urls.py index 66099672ed..df0a7f5af2 100644 --- a/dojo/engagement/urls.py +++ b/dojo/engagement/urls.py @@ -22,8 +22,10 @@ name='copy_engagement'), re_path(r'^engagement/(?P\d+)/add_tests$', views.add_tests, name='add_tests'), - re_path(r'^engagement/(?P\d+)/import_scan_results$', - views.ImportScanResultsView.as_view(), name='import_scan_results'), + re_path( + r'^engagement/(?P\d+)/import_scan_results$', + views.ImportScanResultsView.as_view(), + name='import_scan_results'), re_path(r'^engagement/(?P\d+)/close$', views.close_eng, name='close_engagement'), re_path(r'^engagement/(?P\d+)/reopen$', views.reopen_eng, diff --git a/dojo/engagement/views.py b/dojo/engagement/views.py index 0c01cc72bb..5ac3340fcc 100644 --- a/dojo/engagement/views.py +++ b/dojo/engagement/views.py @@ -6,7 +6,7 @@ from functools import reduce from tempfile import NamedTemporaryFile from time import strftime -from typing import List +from typing import List, Tuple from django.conf import settings from django.contrib import messages @@ -66,11 +66,12 @@ TypedNoteForm, UploadThreatForm, ) -from dojo.importers.importer.importer import DojoDefaultImporter as Importer +from dojo.importers.default_importer import DefaultImporter from dojo.models import ( Check_List, Cred_Mapping, Development_Environment, + Dojo_User, Endpoint, Engagement, Finding, @@ -102,7 +103,6 @@ get_setting, get_system_setting, handle_uploaded_threat, - is_scan_file_too_large, redirect_to_return_url_or_else, ) @@ -706,205 +706,427 @@ def add_tests(request, eid): class ImportScanResultsView(View): - def get(self, request, eid=None, pid=None): - environment = Development_Environment.objects.filter(name='Development').first() - engagement = None - form = ImportScanForm(initial={'environment': environment}) - cred_form = CredMappingForm() - jform = None - user = request.user + def get_template(self) -> str: + """ + Returns the template that will be presented to the user + """ + return "dojo/import_scan_results.html" - if eid: - engagement = get_object_or_404(Engagement, id=eid) + def get_development_environment( + self, + environment_name: str = "Development", + ) -> Development_Environment | None: + """ + Get the development environment in two cases: + - GET: Environment "Development" by default + - POST: The label supplied by the user, with Development as a backup + """ + return Development_Environment.objects.filter(name=environment_name).first() + + def get_engagement_or_product( + self, + user: Dojo_User, + engagement_id: int = None, + product_id: int = None, + ) -> Tuple[Engagement, Product, Product | Engagement]: + """ + Using the path parameters, either fetch the product or engagement + """ + engagement = product = engagement_or_product = None + # Get the product if supplied + # Get the engagement if supplied + if engagement_id is not None: + engagement = get_object_or_404(Engagement, id=engagement_id) engagement_or_product = engagement - cred_form.fields["cred_user"].queryset = Cred_Mapping.objects.filter(engagement=engagement).order_by('cred_id') - elif pid: - product = get_object_or_404(Product, id=pid) + elif product_id is not None: + product = get_object_or_404(Product, id=product_id) engagement_or_product = product else: msg = 'Either Engagement or Product has to be provided' raise Exception(msg) - + # Ensure the supplied user has access to import to the engagement or product user_has_permission_or_403(user, engagement_or_product, Permissions.Import_Scan_Result) + return engagement, product, engagement_or_product + + def get_form( + self, + request: HttpRequest, + **kwargs: dict, + ) -> ImportScanForm: + """ + Returns the default import form for importing findings + """ + if request.method == "POST": + return ImportScanForm(request.POST, request.FILES, **kwargs) + else: + return ImportScanForm(**kwargs) + + def get_credential_form( + self, + request: HttpRequest, + engagement: Engagement, + ) -> CredMappingForm: + """ + Return a new instance of a form managing credentials. If an engagement + it present at this time any existing credential objects will be attempted + to be fetched to populate the form + """ + if request.method == "POST": + return CredMappingForm(request.POST) + else: + # If the engagement is not present, return an empty form + if engagement is None: + return CredMappingForm() + # Otherwise get all creds in the associated engagement + return CredMappingForm( + initial={ + "cred_user_queryset": Cred_Mapping.objects.filter( + engagement=engagement + ).order_by('cred_id'), + } + ) + + def get_jira_form( + self, + request: HttpRequest, + engagement_or_product: Engagement | Product, + ) -> Tuple[JIRAImportScanForm | None, bool]: + """ + Returns a JiraImportScanForm if jira is enabled + """ + jira_form = None + push_all_jira_issues = False + # Determine if jira issues should be pushed automatically push_all_jira_issues = jira_helper.is_push_all_issues(engagement_or_product) + # Only return the form if the jira is enabled on this engagement or product + if jira_helper.get_jira_project(engagement_or_product): + if request.method == "POST": + jira_form = JIRAImportScanForm( + request.POST, + push_all=push_all_jira_issues, + prefix='jiraform' + ) + else: + jira_form = JIRAImportScanForm( + push_all=push_all_jira_issues, + prefix='jiraform' + ) + return jira_form, push_all_jira_issues + + def get_product_tab( + self, + product: Product, + engagement: Engagement, + ) -> Tuple[Product_Tab, dict]: + """ + Determine how the product tab will be rendered, and what tab will be selected + as currently active + """ custom_breadcrumb = None - title = "Import Scan Results" if engagement: - product_tab = Product_Tab(engagement.product, title=title, tab="engagements") + product_tab = Product_Tab(engagement.product, title="Import Scan Results", tab="engagements") product_tab.setEngagement(engagement) else: custom_breadcrumb = {"", ""} - product_tab = Product_Tab(product, title=title, tab="findings") + product_tab = Product_Tab(product, title="Import Scan Results", tab="findings") + return product_tab, custom_breadcrumb - if jira_helper.get_jira_project(engagement_or_product): - jform = JIRAImportScanForm(push_all=push_all_jira_issues, prefix='jiraform') - - form.fields['endpoints'].queryset = Endpoint.objects.filter(product__id=product_tab.product.id) - form.fields['api_scan_configuration'].queryset = Product_API_Scan_Configuration.objects.filter(product__id=product_tab.product.id) - - return render(request, - 'dojo/import_scan_results.html', - {'form': form, - 'product_tab': product_tab, - 'engagement_or_product': engagement_or_product, - 'custom_breadcrumb': custom_breadcrumb, - 'title': title, - 'cred_form': cred_form, - 'jform': jform, - 'scan_types': get_scan_types_sorted(), - }) - - def post(self, request, eid=None, pid=None): - environment = Development_Environment.objects.filter(name='Development').first() # If 'Development' was removed, None is used - engagement = None - form = ImportScanForm(initial={'environment': environment}) - cred_form = CredMappingForm() - finding_count = 0 - jform = None + def handle_request( + self, + request: HttpRequest, + engagement_id: int = None, + product_id: int = None, + ) -> Tuple[HttpRequest, dict]: + """ + Process the common behaviors between request types, and then return + the request and context dict back to be rendered + """ user = request.user + # Get the development environment + environment = self.get_development_environment() + # Get the product or engagement from the path parameters + engagement, product, engagement_or_product = self.get_engagement_or_product( + user, + engagement_id=engagement_id, + product_id=product_id, + ) + # Get the product tab and any additional custom breadcrumbs + product_tab, custom_breadcrumb = self.get_product_tab(product, engagement) + # Get the import form with some initial data in place + form = self.get_form( + request, + environment=environment, + endpoints=Endpoint.objects.filter(product__id=product_tab.product.id), + api_scan_configuration=Product_API_Scan_Configuration.objects.filter(product__id=product_tab.product.id), + ) + # Get the credential mapping form + cred_form = self.get_credential_form(request, engagement) + # Get the jira form + jira_form, push_all_jira_issues = self.get_jira_form(request, engagement_or_product) + # Return the request and the context + return request, { + "user": user, + "lead": user, + "form": form, + "environment": environment, + "product_tab": product_tab, + "product": product, + "engagement": engagement, + "engagement_or_product": engagement_or_product, + "custom_breadcrumb": custom_breadcrumb, + "title": "Import Scan Results", + "cred_form": cred_form, + "jform": jira_form, + "scan_types": get_scan_types_sorted(), + "push_all_jira_issues": push_all_jira_issues, + } + + def validate_forms( + self, + context: dict, + ) -> bool: + """ + Validates each of the forms to ensure all errors from the form + level are bubbled up to the user first before we process too much + """ + form_validation_list = [] + if context.get("form") is not None: + form_validation_list.append(context.get("form").is_valid()) + if context.get("jform") is not None: + form_validation_list.append(context.get("jform").is_valid()) + if context.get("cred_form") is not None: + form_validation_list.append(context.get("cred_form").is_valid()) + return all(form_validation_list) + + def create_engagement( + self, + context: dict, + ) -> Engagement: + """ + Create an engagement if the import was triggered from the product level, + otherwise, return the existing engagement instead + """ + # Make sure an engagement does not exist already + engagement = context.get("engagement") + if engagement is None: + engagement = Engagement.objects.create( + name="AdHoc Import - " + strftime("%a, %d %b %Y %X", timezone.now().timetuple()), + threat_model=False, + api_test=False, + pen_test=False, + check_list=False, + active=True, + target_start=timezone.now().date(), + target_end=timezone.now().date(), + product=context.get("product"), + status='In Progress', + version=context.get("version"), + branch_tag=context.get("branch_tag"), + build_id=context.get("build_id"), + commit_hash=context.get("commit_hash"), + ) + # Update the engagement in the context + context["engagement"] = engagement + # Return the engagement + return engagement + + def import_findings( + self, + context: dict, + ) -> str | None: + """ + Attempt to import with all the supplied information + """ + try: + importer_client = DefaultImporter() + context["test"], _, finding_count, closed_finding_count, _, _, _ = importer_client.process_scan( + **context, + ) + # Add a message to the view for the user to see the results + add_success_message_to_response(importer_client.construct_imported_message( + context.get("scan_type"), + Test_Import.IMPORT_TYPE, + finding_count=finding_count, + closed_finding_count=closed_finding_count, + close_old_findings=context.get("close_old_findings"), + )) + except Exception as e: + logger.exception(e) + return f"An exception error occurred during the report import: {e}" + return None + + def process_form( + self, + request: HttpRequest, + form: ImportScanForm, + context: dict, + ) -> str | None: + """ + Process the form and manipulate the input in any way that is appropriate + """ + # Update the running context dict with cleaned form input + context.update({ + "scan": request.FILES.get("file", None), + "scan_date": form.cleaned_data.get("scan_date"), + "minimum_severity": form.cleaned_data.get("minimum_severity"), + "active": None, + "verified": None, + "scan_type": request.POST.get("scan_type"), + "tags": form.cleaned_data.get("tags"), + "version": form.cleaned_data.get("version"), + "branch_tag": form.cleaned_data.get("branch_tag", None), + "build_id": form.cleaned_data.get("build_id", None), + "commit_hash": form.cleaned_data.get("commit_hash", None), + "api_scan_configuration": form.cleaned_data.get("api_scan_configuration", None), + "service": form.cleaned_data.get("service", None), + "close_old_findings": form.cleaned_data.get("close_old_findings", None), + "apply_tags_to_findings": form.cleaned_data.get("apply_tags_to_findings", False), + "apply_tags_to_endpoints": form.cleaned_data.get("apply_tags_to_endpoints", False), + "close_old_findings_product_scope": form.cleaned_data.get("close_old_findings_product_scope", None), + "group_by": form.cleaned_data.get("group_by", None), + "create_finding_groups_for_all_findings": form.cleaned_data.get("create_finding_groups_for_all_findings"), + "environment": self.get_development_environment(environment_name=form.cleaned_data.get("environment")), + }) + # Create the engagement if necessary + self.create_engagement(context) + # close_old_findings_product_scope is a modifier of close_old_findings. + # If it is selected, close_old_findings should also be selected. + if close_old_findings_product_scope := form.cleaned_data.get('close_old_findings_product_scope', None): + context["close_old_findings_product_scope"] = close_old_findings_product_scope + context["close_old_findings"] = True + # Save newly added endpoints + added_endpoints = save_endpoints_to_add(form.endpoints_to_add_list, context.get("engagement").product) + endpoints_from_form = list(form.cleaned_data['endpoints']) + context["endpoints_to_add"] = endpoints_from_form + added_endpoints + # Override the form values of active and verified + if activeChoice := form.cleaned_data.get('active', None): + if activeChoice == 'force_to_true': + context["active"] = True + elif activeChoice == 'force_to_false': + context["active"] = False + if verifiedChoice := form.cleaned_data.get('verified', None): + if verifiedChoice == 'force_to_true': + context["verified"] = True + elif verifiedChoice == 'force_to_false': + context["verified"] = False + return None + + def process_jira_form( + self, + request: HttpRequest, + form: JIRAImportScanForm, + context: dict, + ) -> str | None: + """ + Process the jira form by first making sure one was supplied + and then setting any values supplied by the user. An error + may be returned and will be bubbled up in the form of a message + """ + # Determine if push all issues is enabled + push_all_jira_issues = context.get("push_all_jira_issues", False) + context["push_to_jira"] = push_all_jira_issues or (form and form.cleaned_data.get("push_to_jira")) + return None + + def process_credentials_form( + self, + request: HttpRequest, + form: CredMappingForm, + context: dict, + ) -> str | None: + """ + Process the credentials form by creating + """ + if cred_user := form.cleaned_data['cred_user']: + # Select the credential mapping object from the selected list and only allow if the credential is associated with the product + cred_user = Cred_Mapping.objects.filter( + pk=cred_user.id, + engagement=context.get("engagement") + ).first() + # Create the new credential mapping object + new_cred_mapping = form.save(commit=False) + new_cred_mapping.test = context.get("test") + new_cred_mapping.cred_id = cred_user.cred_id + new_cred_mapping.save() + # update the context + context["cred_user"] = cred_user + return None + + def success_redirect( + self, + context: dict, + ) -> HttpResponseRedirect: + """ + Redirect the user to a place that indicates a successful import + """ + return HttpResponseRedirect(reverse("view_test", args=(context.get("test").id, ))) + + def failure_redirect( + self, + context: dict, + ) -> HttpResponseRedirect: + """ + Redirect the user to a place that indicates a failed import + """ + return HttpResponseRedirect(reverse( + "import_scan_results", + args=(context.get("engagement", context.get("product")).id, ), + )) + + def get( + self, + request: HttpRequest, + engagement_id: int = None, + product_id: int = None, + ) -> HttpResponse: + """ + Process GET requests for the Import View + """ + # process the request and path parameters + request, context = self.handle_request( + request, + engagement_id=engagement_id, + product_id=product_id, + ) + # Render the form + return render(request, self.get_template(), context) - if eid: - engagement = get_object_or_404(Engagement, id=eid) - engagement_or_product = engagement - cred_form.fields["cred_user"].queryset = Cred_Mapping.objects.filter(engagement=engagement).order_by('cred_id') - elif pid: - product = get_object_or_404(Product, id=pid) - engagement_or_product = product - else: - msg = 'Either Engagement or Product has to be provided' - raise Exception(msg) - - user_has_permission_or_403(user, engagement_or_product, Permissions.Import_Scan_Result) - - push_all_jira_issues = jira_helper.is_push_all_issues(engagement_or_product) - form = ImportScanForm(request.POST, request.FILES) - cred_form = CredMappingForm(request.POST) - cred_form.fields["cred_user"].queryset = Cred_Mapping.objects.filter( - engagement=engagement).order_by('cred_id') - - if jira_helper.get_jira_project(engagement_or_product): - jform = JIRAImportScanForm(request.POST, push_all=push_all_jira_issues, prefix='jiraform') - logger.debug('jform valid: %s', jform.is_valid()) - logger.debug('jform errors: %s', jform.errors) - - if form.is_valid() and (jform is None or jform.is_valid()): - scan = request.FILES.get('file', None) - scan_date = form.cleaned_data['scan_date'] - minimum_severity = form.cleaned_data['minimum_severity'] - activeChoice = form.cleaned_data.get('active', None) - verifiedChoice = form.cleaned_data.get('verified', None) - scan_type = request.POST['scan_type'] - tags = form.cleaned_data['tags'] - version = form.cleaned_data['version'] - branch_tag = form.cleaned_data.get('branch_tag', None) - build_id = form.cleaned_data.get('build_id', None) - commit_hash = form.cleaned_data.get('commit_hash', None) - api_scan_configuration = form.cleaned_data.get('api_scan_configuration', None) - service = form.cleaned_data.get('service', None) - close_old_findings = form.cleaned_data.get('close_old_findings', None) - apply_tags_to_findings = form.cleaned_data.get('apply_tags_to_findings', False) - apply_tags_to_endpoints = form.cleaned_data.get('apply_tags_to_endpoints', False) - # close_old_findings_prodct_scope is a modifier of close_old_findings. - # If it is selected, close_old_findings should also be selected. - close_old_findings_product_scope = form.cleaned_data.get('close_old_findings_product_scope', None) - if close_old_findings_product_scope: - close_old_findings = True - # Will save in the provided environment or in the `Development` one if absent - environment_id = request.POST.get('environment', 'Development') - environment = Development_Environment.objects.get(id=environment_id) - - group_by = form.cleaned_data.get('group_by', None) - create_finding_groups_for_all_findings = form.cleaned_data['create_finding_groups_for_all_findings'] - - # TODO move to form validation? - if scan and is_scan_file_too_large(scan): - messages.add_message(request, - messages.ERROR, - f"Report file is too large. Maximum supported size is {settings.SCAN_FILE_MAX_SIZE} MB", - extra_tags='alert-danger') - return HttpResponseRedirect(reverse('import_scan_results', args=(engagement,))) - - # Allows for a test to be imported with an engagement created on the fly - if engagement is None: - engagement = Engagement() - engagement.name = "AdHoc Import - " + strftime("%a, %d %b %Y %X", timezone.now().timetuple()) - engagement.threat_model = False - engagement.api_test = False - engagement.pen_test = False - engagement.check_list = False - engagement.target_start = timezone.now().date() - engagement.target_end = timezone.now().date() - engagement.product = product - engagement.active = True - engagement.status = 'In Progress' - engagement.version = version - engagement.branch_tag = branch_tag - engagement.build_id = build_id - engagement.commit_hash = commit_hash - engagement.save() - - # can't use helper as when push_all_jira_issues is True, the checkbox gets disabled and is always false - # push_to_jira = jira_helper.is_push_to_jira(new_finding, jform.cleaned_data.get('push_to_jira')) - push_to_jira = push_all_jira_issues or (jform and jform.cleaned_data.get('push_to_jira')) - error = False - - # Save newly added endpoints - added_endpoints = save_endpoints_to_add(form.endpoints_to_add_list, engagement.product) - - active = None - if activeChoice: - if activeChoice == 'force_to_true': - active = True - elif activeChoice == 'force_to_false': - active = False - verified = None - if verifiedChoice: - if verifiedChoice == 'force_to_true': - verified = True - elif verifiedChoice == 'force_to_false': - verified = False - - try: - importer = Importer() - test, finding_count, closed_finding_count, _ = importer.import_scan(scan, scan_type, engagement, user, environment, active=active, verified=verified, tags=tags, - minimum_severity=minimum_severity, endpoints_to_add=list(form.cleaned_data['endpoints']) + added_endpoints, scan_date=scan_date, - version=version, branch_tag=branch_tag, build_id=build_id, commit_hash=commit_hash, push_to_jira=push_to_jira, - close_old_findings=close_old_findings, close_old_findings_product_scope=close_old_findings_product_scope, group_by=group_by, api_scan_configuration=api_scan_configuration, service=service, - create_finding_groups_for_all_findings=create_finding_groups_for_all_findings, apply_tags_to_findings=apply_tags_to_findings, apply_tags_to_endpoints=apply_tags_to_endpoints) - - message = f'{scan_type} processed a total of {finding_count} findings' - - if close_old_findings: - message = message + ' and closed %d findings' % (closed_finding_count) - - message = message + "." - - add_success_message_to_response(message) - - except Exception as e: - logger.exception(e) - add_error_message_to_response(f'An exception error occurred during the report import:{str(e)}') - error = True - - # Save the credential to the test - if cred_form.is_valid(): - if cred_form.cleaned_data['cred_user']: - # Select the credential mapping object from the selected list and only allow if the credential is associated with the product - cred_user = Cred_Mapping.objects.filter( - pk=cred_form.cleaned_data['cred_user'].id, - engagement=eid).first() - - new_f = cred_form.save(commit=False) - new_f.test = test - new_f.cred_id = cred_user.cred_id - new_f.save() - - if not error: - return HttpResponseRedirect( - reverse('view_test', args=(test.id, ))) - - return HttpResponseRedirect(reverse('import_scan_results', args=(engagement.id, ))) + def post( + self, + request: HttpRequest, + engagement_id: int = None, + product_id: int = None, + ) -> HttpResponse: + """ + Process POST requests for the Import View + """ + # process the request and path parameters + request, context = self.handle_request( + request, + engagement_id=engagement_id, + product_id=product_id, + ) + # ensure all three forms are valid first before moving forward + if not self.validate_forms(context): + return self.failure_redirect(context) + # Process the jira form if it is present + if form_error := self.process_jira_form(request, context.get("jform"), context): + add_error_message_to_response(form_error) + return self.failure_redirect(context) + # Process the import form + if form_error := self.process_form(request, context.get("form"), context): + add_error_message_to_response(form_error) + return self.failure_redirect(context) + # Kick off the import process + if import_error := self.import_findings(context): + add_error_message_to_response(import_error) + return self.failure_redirect(context) + # Process the credential form + if form_error := self.process_credentials_form(request, context.get("cred_form"), context): + add_error_message_to_response(form_error) + return self.failure_redirect(context) + # Otherwise return the user back to the engagement (if present) or the product + return self.success_redirect(context) @user_is_authorized(Engagement, Permissions.Engagement_Edit, 'eid') @@ -1101,7 +1323,7 @@ def view_edit_risk_acceptance(request, eid, raid, edit_mode=False): risk_acceptance_form = EditRiskAcceptanceForm(request.POST, request.FILES, instance=risk_acceptance) errors = errors or not risk_acceptance_form.is_valid() if not errors: - logger.debug('path: %s', risk_acceptance_form.cleaned_data['path']) + logger.debug(f"path: {risk_acceptance_form.cleaned_data['path']}") risk_acceptance_form.save() @@ -1187,8 +1409,7 @@ def view_edit_risk_acceptance(request, eid, raid, edit_mode=False): messages.add_message( request, messages.SUCCESS, - 'Finding%s added successfully.' % ('s' if len(findings) > 1 - else ''), + f"Finding{'s' if len(findings) > 1 else ''} added successfully.", extra_tags='alert-success') if not errors: logger.debug('redirecting to return_url') @@ -1350,13 +1571,17 @@ def engagement_ics(request, eid): eng = get_object_or_404(Engagement, id=eid) start_date = datetime.combine(eng.target_start, datetime.min.time()) end_date = datetime.combine(eng.target_end, datetime.max.time()) - uid = "dojo_eng_%d_%d" % (eng.id, eng.product.id) + uid = f"dojo_eng_{eng.id}_{eng.product.id}" cal = get_cal_event( - start_date, end_date, + start_date, + end_date, f"Engagement: {eng.name} ({eng.product.name})", - "Set aside for engagement {}, on product {}. Additional detail can be found at {}".format(eng.name, eng.product.name, - request.build_absolute_uri( - reverse("view_engagement", args=(eng.id, )))), uid) + ( + f"Set aside for engagement {eng.name}, on product {eng.product.name}. " + f"Additional detail can be found at {request.build_absolute_uri(reverse('view_engagement', args=(eng.id, )))}" + ), + uid + ) output = cal.serialize() response = HttpResponse(content=output) response['Content-Type'] = 'text/calendar' diff --git a/dojo/forms.py b/dojo/forms.py index c28b4c298b..0bf5429f71 100644 --- a/dojo/forms.py +++ b/dojo/forms.py @@ -101,7 +101,13 @@ from dojo.tools.factory import get_choices_sorted, requires_file, requires_tool_type from dojo.user.queries import get_authorized_users, get_authorized_users_for_product_and_product_type from dojo.user.utils import get_configuration_permissions_fields -from dojo.utils import get_password_requirements_string, get_product, get_system_setting, is_finding_groups_enabled +from dojo.utils import ( + get_password_requirements_string, + get_product, + get_system_setting, + is_finding_groups_enabled, + is_scan_file_too_large, +) from dojo.widgets import TableCheckboxWidget logger = logging.getLogger(__name__) @@ -548,10 +554,18 @@ class ImportScanForm(forms.Form): create_finding_groups_for_all_findings = forms.BooleanField(help_text="If unchecked, finding groups will only be created when there is more than one grouped finding", required=False, initial=True) def __init__(self, *args, **kwargs): + environment = kwargs.pop("environment", None) + endpoints = kwargs.pop("endpoints", None) + api_scan_configuration = kwargs.pop("api_scan_configuration", None) super().__init__(*args, **kwargs) self.fields['active'].initial = self.active_verified_choices[0] self.fields['verified'].initial = self.active_verified_choices[0] - + if environment: + self.fields['environment'].initial = environment + if endpoints: + self.fields['endpoints'].queryset = endpoints + if api_scan_configuration: + self.fields['api_scan_configuration'].queryset = api_scan_configuration # couldn't find a cleaner way to add empty default if 'group_by' in self.fields: choices = self.fields['group_by'].choices @@ -564,10 +578,13 @@ def clean(self): cleaned_data = super().clean() scan_type = cleaned_data.get("scan_type") file = cleaned_data.get("file") + tool_type = requires_tool_type(scan_type) if requires_file(scan_type) and not file: - msg = f'Uploading a Report File is required for {scan_type}' + msg = _(f"Uploading a Report File is required for {scan_type}") + raise forms.ValidationError(msg) + if file and is_scan_file_too_large(file): + msg = _(f"Report file is too large. Maximum supported size is {settings.SCAN_FILE_MAX_SIZE} MB") raise forms.ValidationError(msg) - tool_type = requires_tool_type(scan_type) if tool_type: api_scan_configuration = cleaned_data.get('api_scan_configuration') if api_scan_configuration and tool_type != api_scan_configuration.tool_configuration.tool_type.name: @@ -649,6 +666,9 @@ class ReImportScanForm(forms.Form): create_finding_groups_for_all_findings = forms.BooleanField(help_text="If unchecked, finding groups will only be created when there is more than one grouped finding", required=False, initial=True) def __init__(self, *args, test=None, **kwargs): + endpoints = kwargs.pop("endpoints", None) + api_scan_configuration = kwargs.pop("api_scan_configuration", None) + api_scan_configuration_queryset = kwargs.pop("api_scan_configuration_queryset", None) super().__init__(*args, **kwargs) self.fields['active'].initial = self.active_verified_choices[0] self.fields['verified'].initial = self.active_verified_choices[0] @@ -656,7 +676,12 @@ def __init__(self, *args, test=None, **kwargs): if test: self.scan_type = test.test_type.name self.fields['tags'].initial = test.tags.all() - + if endpoints: + self.fields["endpoints"].queryset = endpoints + if api_scan_configuration: + self.initial["api_scan_configuration"] = api_scan_configuration + if api_scan_configuration_queryset: + self.fields["api_scan_configuration"].queryset = api_scan_configuration_queryset # couldn't find a cleaner way to add empty default if 'group_by' in self.fields: choices = self.fields['group_by'].choices @@ -667,7 +692,10 @@ def clean(self): cleaned_data = super().clean() file = cleaned_data.get("file") if requires_file(self.scan_type) and not file: - msg = "Uploading a report file is required for re-uploading findings." + msg = _("Uploading a report file is required for re-uploading findings.") + raise forms.ValidationError(msg) + if file and is_scan_file_too_large(file): + msg = _(f"Report file is too large. Maximum supported size is {settings.SCAN_FILE_MAX_SIZE} MB") raise forms.ValidationError(msg) tool_type = requires_tool_type(self.scan_type) if tool_type: @@ -2645,14 +2673,23 @@ def clean(self): class CredMappingForm(forms.ModelForm): - cred_user = forms.ModelChoiceField(queryset=Cred_Mapping.objects.all().select_related('cred_id'), required=False, - label='Select a Credential') + cred_user = forms.ModelChoiceField( + queryset=Cred_Mapping.objects.all().select_related('cred_id'), + required=False, + label='Select a Credential', + ) class Meta: model = Cred_Mapping fields = ['cred_user'] exclude = ['product', 'finding', 'engagement', 'test', 'url', 'is_authn_provider'] + def __init__(self, *args, **kwargs): + cred_user_queryset = kwargs.pop("cred_user_queryset", None) + super().__init__(*args, **kwargs) + if cred_user_queryset is not None: + self.fields["cred_user"].queryset = cred_user_queryset + class CredMappingFormProd(forms.ModelForm): class Meta: diff --git a/dojo/importers/auto_create_context.py b/dojo/importers/auto_create_context.py new file mode 100644 index 0000000000..c0c70f72b9 --- /dev/null +++ b/dojo/importers/auto_create_context.py @@ -0,0 +1,353 @@ +import logging +from datetime import datetime, timedelta +from typing import Any + +from crum import get_current_user +from django.http.request import QueryDict +from django.utils import timezone + +from dojo.models import ( + Engagement, + Product, + Product_Member, + Product_Type, + Product_Type_Member, + Role, + Test, +) +from dojo.utils import get_last_object_or_none, get_object_or_none + +logger = logging.getLogger(__name__) +deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") + + +class AutoCreateContextManager: + """ + Management of safely fetching and creating resources used in the import + and reimport processes. Resources managed by this class are: + - Product Types + - Products + - Engagements + - Tests + """ + """ + =================================== + ----------- Validators ------------ + =================================== + """ + def process_object_fields( + self, + key: str, + label: str, + object_type: Any, + data: dict, + **kwargs: dict, + ) -> None: + """ + Process the object fields such as product, engagement, and + test such that passing the whole object, or just the ID + will suffice + """ + if object_id := data.get(key, None): + # Convert to just the ID if the whole object as passed + if isinstance(object_id, object_type): + object_id = object_id.id + # Convert to a string if needed + if isinstance(object_id, list) and len(object_id) > 0: + object_id = object_id[0] + # Ensure the ID is an integer, not a string + elif isinstance(object_id, str) and not object_id.isdigit(): + msg = f"{key} must be an integer" + raise ValueError(msg) + # Update the "test" entry in the dict with the ID + data[label] = object_id + + def process_object_name( + self, + key: str, + data: dict, + **kwargs: dict, + ) -> None: + """ + Process the object names by ensuring that the inputs + are a string and not a list of strings + """ + if object_name := data.get(key): + # Convert to a string if needed + if isinstance(object_name, list) and len(object_name) > 0: + data[key] = object_name[0] + + def process_import_meta_data_from_dict( + self, + data: dict, + **kwargs: dict, + ) -> None: + """ + Ensure that the inputs supplied for test and engagement can be + derive into am integer ID. This can happen if a full Test or + Engagement is supplied, or if the input is an integer ID to + start with + """ + # Validate the test artifact + self.process_object_fields("test", "test_id", Test, data) + # Validate the engagement artifact + self.process_object_fields("engagement", "engagement_id", Engagement, data) + # Validate the product artifact + self.process_object_fields("product", "product_id", Product, data) + # Validate the product_type_name + self.process_object_name("product_type_name", data) + # Validate the product_name + self.process_object_name("product_name", data) + # Validate the engagement_name + self.process_object_name("engagement_name", data) + # Validate the test_title + self.process_object_name("test_title", data) + + """ + =================================== + ------------ Fetchers ------------- + =================================== + """ + def get_target_product_type_if_exists( + self, + product_type_name: str = None, + **kwargs: dict, + ) -> Product_Type | None: + """ + Query for a product type that matches the name `product_type_name`. + + If a match is not found, return None + """ + # Look for an existing object + if product_type_name: + return get_object_or_none(Product_Type, name=product_type_name) + return None + + def get_target_product_if_exists( + self, + product_name: str = None, + product_type_name: str = None, + **kwargs: dict, + ) -> Product | None: + """ + Query for a product that matches the name `product_name`. Some + extra verification is also administered to ensure the + `product_type_name` matches the one on the fetched product + + If a match is not found, return None + """ + # Look for an existing object + if product_name and (product := get_object_or_none(Product, name=product_name)): + # product type name must match if provided + if product_type_name and product.prod_type.name != product_type_name: + msg = ( + "The fetched product has a conflict with the supplied product type name: " + f"existing product type name - {product.prod_type.name} vs " + f"supplied product type name - {product_type_name}" + ) + raise ValueError(msg) + # Return the product + return product + return None + + def get_target_product_by_id_if_exists( + self, + product_id: int = 0, + **kwargs: dict, + ) -> Product | None: + """ + Query for a product matching by ID + + If a match is not found, return None + """ + return get_object_or_none(Product, pk=product_id) + + def get_target_engagement_if_exists( + self, + engagement_id: int = 0, + engagement_name: str = None, + product: Product = None, + **kwargs: dict, + ) -> Engagement | None: + """ + Query for an engagement matching by ID. If a match is not found, + and a product is supplied, return the last engagement created on + the product by name + + If a match is not found, and a product is not supplied, return None + """ + if engagement := get_object_or_none(Engagement, pk=engagement_id): + logger.debug('Using existing engagement by id: %s', engagement_id) + return engagement + # if there's no product, then for sure there's no engagement either + if product is None: + return None + # engagement name is not unique unfortunately + return get_last_object_or_none(Engagement, product=product, name=engagement_name) + + def get_target_test_if_exists( + self, + test_id: int = 0, + test_title: str = None, + scan_type: str = None, + engagement: Engagement = None, + **kwargs: dict, + ) -> Test | None: + """ + Retrieves the target test to reimport. This can be as simple as looking up the test via the `test_id` parameter. + If there is no `test_id` provided, we lookup the latest test inside the provided engagement that satisfies + the provided scan_type and test_title. + """ + if test := get_object_or_none(Test, pk=test_id): + logger.debug('Using existing Test by id: %s', test_id) + return test + # If the engagement is not supplied, we cannot do anything + if not engagement: + return None + # Check for a custom test title + if test_title: + return get_last_object_or_none(Test, engagement=engagement, title=test_title, scan_type=scan_type) + # Otherwise use the last test by scan type + return get_last_object_or_none(Test, engagement=engagement, scan_type=scan_type) + + """ + =================================== + ------------ Creators ------------- + =================================== + """ + def get_or_create_product_type( + self, + product_type_name: str = None, + **kwargs: dict, + ) -> Product_Type: + """ + Fetches a product type by name if one already exists. If not, + a new product type will be created with the current user being + added as product type member + """ + # Look for an existing object + if product_type := self.get_target_product_type_if_exists(product_type_name=product_type_name): + return product_type + else: + product_type, created = Product_Type.objects.get_or_create(name=product_type_name) + if created: + Product_Type_Member.objects.create( + user=get_current_user(), + product_type=product_type, + role=Role.objects.get(is_owner=True), + ) + return product_type + + def get_or_create_product( + self, + product_name: str = None, + product_type_name: str = None, + auto_create_context: bool = False, + **kwargs: dict, + ) -> Product: + """ + Fetches a product by name if it exists. When `auto_create_context` is + enabled the product will be created with the current user being added + as product member + """ + # try to find the product (within the provided product_type) + if product := self.get_target_product_if_exists(product_name, product_type_name): + return product + # not found .... create it + if not auto_create_context: + msg = "auto_create_context not True, unable to create non-existing product" + raise ValueError(msg) + # Look for a product type first + product_type = self.get_or_create_product_type(product_type_name=product_type_name) + # Create the product + product, created = Product.objects.get_or_create(name=product_name, prod_type=product_type, description=product_name) + if created: + Product_Member.objects.create( + user=get_current_user(), + product=product, + role=Role.objects.get(is_owner=True), + ) + + return product + + def get_or_create_engagement( + self, + engagement_id: int = 0, + engagement_name: str = None, + product_name: str = None, + product_type_name: str = None, + auto_create_context: bool = False, + deduplication_on_engagement: bool = False, + source_code_management_uri: str = None, + target_end: datetime = None, + **kwargs: dict, + ) -> Engagement: + """ + Fetches an engagement by name or ID if one already exists. + """ + # try to find the engagement (and product) + product = self.get_target_product_if_exists( + product_name=product_name, + product_type_name=product_type_name, + ) + engagement = self.get_target_engagement_if_exists( + engagement_id=engagement_id, + engagement_name=engagement_name, + product=product + ) + # If we have an engagement, we cna just return it + if engagement: + return engagement + # not found .... create it + if not auto_create_context: + msg = "auto_create_context not True, unable to create non-existing engagement" + raise ValueError(msg) + # Get a product first + product = self.get_or_create_product( + product_name=product_name, + product_type_name=product_type_name, + auto_create_context=auto_create_context, + ) + # Get the target start date in order + target_start = timezone.now().date() + if (target_end is None) or (target_start > target_end): + target_end = (timezone.now() + timedelta(days=365)).date() + # Create the engagement + return Engagement.objects.create( + engagement_type="CI/CD", + name=engagement_name, + product=product, + lead=get_current_user(), + target_start=target_start, + target_end=target_end, + status="In Progress", + deduplication_on_engagement=deduplication_on_engagement, + source_code_management_uri=source_code_management_uri, + ) + + """ + =================================== + ------------ Utilities ------------ + =================================== + """ + def convert_querydict_to_dict( + self, + query_dict_data: QueryDict, + ) -> dict: + """ + Creates a copy of a query dict, and then converts it + to a dict + """ + # First copy the query dict + copy = {} + # Iterate ovr the dict and extract the elements based + # on whether they are a single item, or a list + for key, value in query_dict_data.items(): + if value: + # Accommodate lists + if isinstance(value, list): + copy[key] = value if len(value) > 1 else value[0] + else: + copy[key] = value + # Convert to a regular dict + return copy diff --git a/dojo/importers/base_importer.py b/dojo/importers/base_importer.py new file mode 100644 index 0000000000..491450e1de --- /dev/null +++ b/dojo/importers/base_importer.py @@ -0,0 +1,940 @@ +import base64 +import logging +from abc import ABC, abstractmethod +from datetime import datetime +from typing import List, Tuple + +from django.conf import settings +from django.core.exceptions import MultipleObjectsReturned, ValidationError +from django.core.files.base import ContentFile +from django.core.files.uploadedfile import TemporaryUploadedFile +from django.urls import reverse +from django.utils import timezone +from django.utils.timezone import make_aware + +import dojo.finding.helper as finding_helper +from dojo.celery import app +from dojo.decorators import dojo_async_task +from dojo.endpoint.utils import endpoint_get_or_create +from dojo.importers.endpoint_manager import DefaultReImporterEndpointManager +from dojo.models import ( + # Import History States + IMPORT_CLOSED_FINDING, + IMPORT_CREATED_FINDING, + IMPORT_REACTIVATED_FINDING, + IMPORT_UNTOUCHED_FINDING, + # Finding Severities + SEVERITIES, + BurpRawRequestResponse, + Dojo_User, + Endpoint, + Endpoint_Status, + # models + Engagement, + FileUpload, + Finding, + Test, + Test_Import, + Test_Import_Finding_Action, + Test_Type, + Tool_Configuration, + Vulnerability_Id, +) +from dojo.tools.factory import get_parser +from dojo.utils import get_current_user, is_finding_groups_enabled, max_safe + +logger = logging.getLogger(__name__) + + +class Parser: + """ + This class is used as an alias to a given parser + and is purely for the sake of type hinting + """ + + def get_findings(scan_type: str) -> List[Finding]: + """ + Stub function to make the hinting happier. The actual class + is loosely obligated to have this function defined. + + TODO This should be enforced in the future, but here is not the place + TODO once this enforced, this stub class should be removed + """ + pass + + +class BaseImporter(ABC, DefaultReImporterEndpointManager): + """ + A collection of utilities used by various importers within DefectDojo. + Some of these commonalities may be fully used by children importers, + or even extended + """ + def __init__(self, *args: list, **kwargs: dict): + """ + Initializing or constructing this parent class is prohibited + and will raise a `NotImplemented` exception + """ + self.new_or_init(*args, **kwargs) + + def __new__(self, *args: list, **kwargs: dict): + """ + Initializing or constructing this parent class is prohibited + and will raise a `NotImplemented` exception + """ + instance = super().__new__(self, *args, **kwargs) + instance.new_or_init(*args, **kwargs) + return instance + + def new_or_init(self, *args: list, **kwargs: dict): + """ + Ensures that that the parent BaseImporter class is not + instantiated directly + """ + self.check_child_implementation_exception() + + def check_child_implementation_exception(self): + """ + This is a helper function for a quick check to ensure that the methods of the + BaseImporter are not being used directly + """ + if isinstance(self, BaseImporter): + msg = ( + "The BaseImporter class must not be used directly. " + "Please use a class that extends the BaseImporter class." + ) + raise NotImplementedError(msg) + + @abstractmethod + def process_scan( + self, + scan: TemporaryUploadedFile, + scan_type: str, + engagement: Engagement = None, + test: Test = None, + user: Dojo_User = None, + parsed_findings: List[Finding] = None, + **kwargs: dict, + ) -> Tuple[Test, int, int, int, int, int, Test_Import]: + """ + A helper method that executes the entire import process in a single method. + This includes parsing the file, processing the findings, and returning the + statistics from the import + """ + self.check_child_implementation_exception() + + @abstractmethod + @dojo_async_task + @app.task(ignore_result=False) + def process_findings( + self, + test: Test, + parsed_findings: List[Finding], + user: Dojo_User, + **kwargs: dict, + ) -> List[Finding]: + """ + Make the conversion from unsaved Findings in memory to Findings that are saved in the + database with and ID associated with them. This processor will also save any associated + objects such as endpoints, vulnerability IDs, and request/response pairs + """ + self.check_child_implementation_exception() + + @abstractmethod + def close_old_findings( + self, + test: Test, + findings: List[Finding], + user: Dojo_User, + scan_date: datetime = timezone.now(), + **kwargs: dict, + ) -> List[Finding]: + """ + Identify any findings that have been imported before, + but are no longer present in later reports so that + we can automatically close them as "implied mitigated" + + This function will vary by importer, so it is marked as + abstract with a prohibitive exception raised if the + method is attempted to to be used by the BaseImporter class + """ + self.check_child_implementation_exception() + + def get_parser( + self, + scan_type: str, + ) -> Parser: + """ + Returns the correct parser based on the the test type supplied. If a test type + is supplied that does not have a parser created for it, an exception is raised + from the factory `get_parser` function + """ + return get_parser(scan_type) + + def process_scan_file( + self, + scan: TemporaryUploadedFile, + ) -> TemporaryUploadedFile: + """ + Make any preprocessing actions or changes on the report before submitting + to the parser to generate findings from the file + """ + return scan + + def parse_findings_static_test_type( + self, + parser: Parser, + scan_type: str, + scan: TemporaryUploadedFile, + test: Test = None, + **kwargs: dict, + ) -> List[Finding]: + """ + Parse the scan report submitted with the parser class and generate some findings + that are not saved to the database yet. This step is crucial in determining if + there are any errors in the parser before creating any new resources + """ + # Ensure that a test is present when calling this method as there are cases where + # the test will be created by this function in a child class + if test is None or not isinstance(test, Test): + msg = "A test must be supplied to parse the file" + raise ValidationError(msg) + try: + return parser.get_findings(scan, test) + except ValueError as e: + logger.warning(e) + raise ValidationError(e) + + def parse_dynamic_test_type_tests( + self, + parser: Parser, + scan_type: str, + scan: TemporaryUploadedFile, + **kwargs: dict, + ) -> List[Test]: + """ + Use the API configuration object to get the tests to be used by the parser + """ + try: + return parser.get_tests(scan_type, scan) + except ValueError as e: + logger.warning(e) + raise ValidationError(e) + + def parse_dynamic_test_type_findings_from_tests( + self, + tests: List[Test], + **kwargs: dict, + ) -> List[Finding]: + """ + currently we only support import one Test + so for parser that support multiple tests (like SARIF) + we aggregate all the findings into one uniq test + """ + parsed_findings = [] + for test_raw in tests: + parsed_findings.extend(test_raw.findings) + return parsed_findings + + def parse_findings_dynamic_test_type( + self, + parser: Parser, + scan_type: str, + scan: TemporaryUploadedFile, + **kwargs: dict, + ) -> List[Finding]: + """ + Use the API configuration object to get the tests to be used by the parser + to dump findings into + + This version of this function is intended to be extended by children classes + """ + tests = self.parse_dynamic_test_type_tests( + parser, + scan_type, + scan, + **kwargs, + ) + return self.parse_dynamic_test_type_findings_from_tests(tests, **kwargs) + + def parse_findings( + self, + parser: Parser, + scan_type: str, + scan: TemporaryUploadedFile, + test: Test = None, + **kwargs: dict, + ) -> List[Finding]: + """ + Determine how to parse the findings based on the presence of the + `get_tests` function on the parser object + """ + if hasattr(parser, 'get_tests'): + return self.parse_findings_dynamic_test_type( + parser, + scan_type, + scan, + **kwargs, + ) + else: + return self.parse_findings_static_test_type( + parser, + scan_type, + scan, + test=test, + **kwargs, + ) + + def determine_process_method( + self, + test: Test, + parsed_findings: List[Finding], + user: Dojo_User, + **kwargs: dict, + ) -> List[Finding]: + """ + Determines whether to process the scan iteratively, or in chunks, + based upon the ASYNC_FINDING_IMPORT setting + """ + if settings.ASYNC_FINDING_IMPORT: + return self.async_process_findings( + test, + parsed_findings, + user, + **kwargs, + ) + else: + return self.sync_process_findings( + test, + parsed_findings, + user, + **kwargs, + ) + + def update_test_meta( + self, + test: Test, + **kwargs: dict, + ) -> Test: + """ + Update the test with some values stored in the kwargs dict. The common + fields used today are `version`, `branch_tag`, `build_id`, and `commit_hash` + """ + # Add the extra fields to the test if they are specified here + if not (version := kwargs.get("version", "")).isspace(): + test.version = version + if not (branch_tag := kwargs.get("branch_tag", "")).isspace(): + test.branch_tag = branch_tag + if not (build_id := kwargs.get("build_id", "")).isspace(): + test.build_id = build_id + if not (commit_hash := kwargs.get("commit_hash", "")).isspace(): + test.commit_hash = commit_hash + + return test + + def update_timestamps( + self, + test: Test, + **kwargs: dict, + ) -> Test: + """ + Update the target end dates for tests as imports are occurring: + - Import + - Updates to the test target date are largely non impacting. + However, there is a possibility that the engagement is a CI/CD + engagement, so the target end should be updated + - Reimport + - Updates to the test target date are very important as we are + constantly reusing the same test over and over + - In the (likely) event the engagement is a CI/CD type, the target + end date should be updated as well + """ + # Make sure there is at least something in the scan date field + scan_date = kwargs.get("scan_date") + if scan_date is None: + scan_date = kwargs.get("now") + # Update the target end of the engagement if it is a CI/CD engagement + # If the supplied scan date is greater than the current configured + # target end date on the engagement + if test.engagement.engagement_type == 'CI/CD': + test.engagement.target_end = max_safe([scan_date.date(), test.engagement.target_end]) + # Set the target end date on the test in a similar fashion + max_test_start_date = max_safe([scan_date, test.target_end]) + # Quick check to make sure we have a datetime that is timezone aware + # so that we can suppress naive datetime warnings + if not max_test_start_date.tzinfo: + max_test_start_date = make_aware(max_test_start_date) + test.target_end = max_test_start_date + + return test + + def update_test_tags( + self, + test: Test, + tags: List[str], + ) -> None: + """ + Update the list of tags on the test if they are supplied + at import time + """ + # Make sure the list is not empty as we do not want to overwrite + # any existing tags + if tags is not None and len(tags) > 0: + test.tags = tags + # Save the test for changes to be applied + # TODO this may be a redundant save, and may be able to be pruned + test.save() + + def update_import_history( + self, + type: str, + test: Test, + new_findings: List[Finding] = [], + closed_findings: List[Finding] = [], + reactivated_findings: List[Finding] = [], + untouched_findings: List[Finding] = [], + **kwargs: dict, + ) -> Test_Import: + """ + Creates a record of the import or reimport operation that has occurred. + """ + # Quick fail check to determine if we even wanted this + if settings.TRACK_IMPORT_HISTORY is False: + return None + # Log the current state of what has occurred in case there could be + # deviation from what is displayed in the view + logger.debug( + f"new: {len(new_findings)} " + f"closed: {len(closed_findings)} " + f"reactivated: {len(reactivated_findings)} " + f"untouched: {len(untouched_findings)} " + ) + # Create a dictionary to stuff into the test import object + import_settings = {} + import_settings['active'] = kwargs.get("active") + import_settings['verified'] = kwargs.get("verified") + import_settings['minimum_severity'] = kwargs.get("minimum_severity") + import_settings['close_old_findings'] = kwargs.get("close_old_findings") + import_settings['push_to_jira'] = kwargs.get("push_to_jira") + import_settings['tags'] = kwargs.get("tags") + # Add the list of endpoints that were added exclusively at import time + if (endpoints_to_add := kwargs.get("endpoints_to_add")) and len(endpoints_to_add) > 0: + import_settings['endpoints'] = [str(endpoint) for endpoint in endpoints_to_add] + # Create the test import object + test_import = Test_Import.objects.create( + test=test, + import_settings=import_settings, + version=kwargs.get("version"), + branch_tag=kwargs.get("branch_tag"), + build_id=kwargs.get("build_id"), + commit_hash=kwargs.get("commit_hash"), + type=type, + ) + # Define all of the respective import finding actions for the test import object + test_import_finding_action_list = [] + for finding in closed_findings: + logger.debug(f"preparing Test_Import_Finding_Action for closed finding: {finding.id}") + test_import_finding_action_list.append(Test_Import_Finding_Action( + test_import=test_import, + finding=finding, + action=IMPORT_CLOSED_FINDING, + )) + for finding in new_findings: + logger.debug(f"preparing Test_Import_Finding_Action for created finding: {finding.id}") + test_import_finding_action_list.append(Test_Import_Finding_Action( + test_import=test_import, + finding=finding, + action=IMPORT_CREATED_FINDING, + )) + for finding in reactivated_findings: + logger.debug(f"preparing Test_Import_Finding_Action for reactivated finding: {finding.id}") + test_import_finding_action_list.append(Test_Import_Finding_Action( + test_import=test_import, + finding=finding, + action=IMPORT_REACTIVATED_FINDING, + )) + for finding in untouched_findings: + logger.debug(f"preparing Test_Import_Finding_Action for untouched finding: {finding.id}") + test_import_finding_action_list.append(Test_Import_Finding_Action( + test_import=test_import, + finding=finding, + action=IMPORT_UNTOUCHED_FINDING, + )) + # Bulk create all the defined objects + Test_Import_Finding_Action.objects.bulk_create(test_import_finding_action_list) + # Add any tags to the findings imported if necessary + if kwargs.get("apply_tags_to_findings", False) and (tags := kwargs.get("tags")): + for finding in test_import.findings_affected.all(): + for tag in tags: + finding.tags.add(tag) + # Add any tags to any endpoints of the findings imported if necessary + if kwargs.get("apply_tags_to_endpoints", False) and (tags := kwargs.get("tags")): + for finding in test_import.findings_affected.all(): + for endpoint in finding.endpoints.all(): + for tag in tags: + endpoint.tags.add(tag) + + return test_import + + def construct_imported_message( + self, + scan_type: str, + import_type: str, + finding_count: int = 0, + new_finding_count: int = 0, + closed_finding_count: int = 0, + reactivated_finding_count: int = 0, + untouched_finding_count: int = 0, + **kwargs: dict, + ) -> str: + """ + Constructs a success message to be displayed on screen in the UI as a digest for the user. + This digest includes counts for the findings in the following status: + - Created: New findings that have not been created before + - Closed: Findings that were not detected in the report any longer, so the original was closed + - Reactivated: Findings that were once closed, but has reappeared in the report again + - Untouched: Findings that have not changed between now, and the last import/reimport + """ + # Only construct this message if there is any change in finding status + if finding_count > 0: + # Set the base message to indicate how many findings were parsed from the report + message = f"{scan_type} processed a total of {finding_count} findings" + if import_type == Test_Import.IMPORT_TYPE: + # Check for close old findings context to determine if more detail should be added + if kwargs.get("close_old_findings", False): + message += f" and closed {closed_finding_count} findings" + if import_type == Test_Import.REIMPORT_TYPE: + # Add more details for any status changes recorded + if new_finding_count: + message += f" created {new_finding_count} findings" + if closed_finding_count: + message += f" closed {closed_finding_count} findings" + if reactivated_finding_count: + message += f" reactivated {reactivated_finding_count} findings" + if untouched_finding_count: + message += f" did not touch {untouched_finding_count} findings" + # Drop a period at the end + message += "." + else: + # Set the message to convey that all findings processed are identical to the last time an import/reimport occurred + message = "No findings were added/updated/closed/reactivated as the findings in Defect Dojo are identical to those in the uploaded report." + + return message + + def chunk_objects( + self, + object_list: List[Finding | Endpoint], + chunk_size: int = settings.ASYNC_FINDING_IMPORT_CHUNK_SIZE, + ) -> List[List[Finding | Endpoint]]: + """ + Split a single large list into a list of lists of size `chunk_size`. + For Example + ``` + >>> chunk_objects([A, B, C, D, E], 2) + >>> [[A, B], [B, C], [E]] + ``` + """ + # Break the list of parsed findings into "chunk_size" lists + chunk_list = [object_list[i:i + chunk_size] for i in range(0, len(object_list), chunk_size)] + logger.debug(f"IMPORT_SCAN: Split endpoints/findings into {len(chunk_list)} chunks of {chunk_size}") + return chunk_list + + def chunk_endpoints_and_disperse( + self, + finding: Finding, + test: Test, + endpoints: List[Endpoint], + **kwargs: dict, + ) -> None: + """ + Determines whether to asynchronously process endpoints on a finding or not. if so, + chunk up the findings to be dispersed into individual celery workers. Otherwise, + only use one worker + """ + if settings.ASYNC_FINDING_IMPORT: + chunked_list = self.chunk_objects(endpoints) + # If there is only one chunk, then do not bother with async + if len(chunked_list) < 2: + self.add_endpoints_to_unsaved_finding(finding, test, endpoints, sync=True) + return [] + # First kick off all the workers + for endpoints_list in chunked_list: + self.add_endpoints_to_unsaved_finding(finding, test, endpoints_list, sync=False) + else: + # Do not run this asynchronously or chunk the endpoints + self.add_endpoints_to_unsaved_finding(finding, test, endpoints, sync=True) + return None + + def clean_unsaved_endpoints( + self, + endpoints: List[Endpoint] + ) -> None: + """ + Clean endpoints that are supplied. For any endpoints that fail this validation + process, raise a message that broken endpoints are being stored + """ + for endpoint in endpoints: + try: + endpoint.clean() + except ValidationError as e: + logger.warning(f"DefectDojo is storing broken endpoint because cleaning wasn't successful: {e}") + return None + + @dojo_async_task + @app.task() + def add_endpoints_to_unsaved_finding( + self, + finding: Finding, + test: Test, + endpoints: List[Endpoint], + **kwargs: dict, + ) -> None: + """ + Creates Endpoint objects for a single finding and creates the link via the endpoint status + """ + logger.debug(f"IMPORT_SCAN: Adding {len(endpoints)} endpoints to finding: {finding}") + self.clean_unsaved_endpoints(endpoints) + for endpoint in endpoints: + ep = None + try: + ep, _ = endpoint_get_or_create( + protocol=endpoint.protocol, + userinfo=endpoint.userinfo, + host=endpoint.host, + port=endpoint.port, + path=endpoint.path, + query=endpoint.query, + fragment=endpoint.fragment, + product=test.engagement.product) + except (MultipleObjectsReturned): + msg = ( + f"Endpoints in your database are broken. " + f"Please access {reverse('endpoint_migrate')} and migrate them to new format or remove them." + ) + raise Exception(msg) + + Endpoint_Status.objects.get_or_create( + finding=finding, + endpoint=ep, + defaults={'date': finding.date}) + logger.debug(f"IMPORT_SCAN: {len(endpoints)} imported") + return None + + @dojo_async_task + @app.task() + def update_test_progress( + self, + test: Test, + **kwargs: dict, + ) -> None: + """ + This function is added to the async queue at the end of all finding import tasks + and after endpoint task, so this should only run after all the other ones are done. + It's purpose is to update the percent completion of the test to 100 percent + """ + test.percent_complete = 100 + test.save() + return None + + def get_or_create_test_type( + self, + test_type_name: str, + ) -> Test_Type: + """ + Ensures that a test type exists for a given test. This function can be called + in the following circumstances: + - Ensuring a test type exists for import + - Ensuring a test type exists for reimport with auto-create context + - Creating a new test type for dynamic test types such as generic and sarif + """ + test_type, created = Test_Type.objects.get_or_create(name=test_type_name) + if created: + logger.info(f"Created new Test_Type with name {test_type.name} because a report is being imported") + return test_type + + def add_timezone_scan_date_and_now( + self, + scan_date: datetime = None, + now: datetime = timezone.now(), + ) -> Tuple[datetime, datetime]: + """ + Add timezone information the scan date set at import time. In the event the + scan date is not supplied, fall back on the current time so that the test + can have a time for the target start and end + """ + # Add timezone information to the scan date if it is not already present + if scan_date is not None and not scan_date.tzinfo: + scan_date = timezone.make_aware(scan_date) + # Add timezone information to the current time if it is not already present + if now is None: + now = timezone.now() + elif not now.tzinfo: + now = timezone.make_aware(now) + + return scan_date, now + + def get_user_if_supplied( + self, + user: Dojo_User = None, + ) -> Dojo_User: + """ + Determines whether the user supplied at import time should + be used or not. If the user supplied is not actually a user, + the current authorized user will be fetched instead + """ + if user is None: + return get_current_user() + return user + + def verify_tool_configuration_from_test( + self, + api_scan_configuration: Tool_Configuration, + test: Test, + ) -> Test: + """ + Verify that the Tool_Configuration supplied along with the + test is found on the product. If not, then raise a validation + error that will bubble up back to the user + + if f there is a case where the Tool_Configuration supplied to + this function does not match the one saved on the test, then + we will user the one supplied rather than the one on the test. + """ + # Do not bother with any of the verification if a Tool_Configuration is not supplied + if api_scan_configuration is None: + # Return early as there is no value in validating further + return test + # Ensure that a test was supplied + elif not isinstance(test, Test): + msg = "A test must be supplied to verify the Tool_Configuration against" + raise ValidationError(msg) + # Validate that the test has a value + elif test is not None: + # Make sure the Tool_Configuration is connected to the product that the test is + if api_scan_configuration.product != test.engagement.product: + msg = "API Scan Configuration has to be from same product as the Test" + raise ValidationError(msg) + # If the Tool_Configuration on the test is not the same as the one supplied, then lets + # use the one that is supplied + if test.api_scan_configuration != api_scan_configuration: + test.api_scan_configuration = api_scan_configuration + test.save() + # Return the test here for an early exit + return test + + def verify_tool_configuration_from_engagement( + self, + api_scan_configuration: Tool_Configuration, + engagement: Engagement, + ) -> Test | Engagement: + """ + Verify that the Tool_Configuration supplied along with the + engagement is found on the product. If not, then raise a validation + error that will bubble up back to the user + + if there is a case where the Tool_Configuration supplied to + this function does not match the one saved on the engagement, then + we will user the one supplied rather than the one on the engagement. + """ + # Do not bother with any of the verification if a Tool_Configuration is not supplied + if api_scan_configuration is None: + # Return early as there is no value in validating further + return engagement + # Ensure that an engagement was supplied + elif not isinstance(engagement, Engagement): + msg = "An engagement must be supplied to verify the Tool_Configuration against" + raise ValidationError(msg) + # Validate that the engagement has a value + elif engagement is not None and isinstance(engagement, Engagement): + # Make sure the Tool_Configuration is connected to the engagement that the test is + if api_scan_configuration.product != engagement.product: + msg = "API Scan Configuration has to be from same product as the Engagement" + raise ValidationError(msg) + # Return the test here for an early exit + return engagement + + def sanitize_severity( + self, + finding: Finding, + ) -> Finding: + """ + Sanitization on the finding severity such that only the following + severities may be set on the finding: + - Critical, High, Medium, Low, Info + There is a simple conversion process to convert any of the following + to a value of Info + - info, informational, Informational, None, none + If not, raise a ValidationError explaining as such + """ + # Checks around Informational/Info severity + starts_with_info = finding.severity.lower().startswith('info') + lower_none = finding.severity.lower() == 'none' + not_info = finding.severity != 'Info' + # Make the comparisons + if not_info and (starts_with_info or lower_none): + # Correct the severity + finding.severity = 'Info' + # Ensure the final severity is one of the supported options + if finding.severity not in SEVERITIES: + msg = ( + f"Finding severity \"{finding.severity}\" is not supported. " + f"Any of the following are supported: {SEVERITIES}." + ) + raise ValidationError(msg) + # Set the numerical severity on the finding based on the cleaned severity + finding.numerical_severity = Finding.get_numerical_severity(finding.severity) + # Return the finding if all else is good + return finding + + def process_finding_groups( + self, + finding: Finding, + group_by: str, + group_names_to_findings_dict: dict, + ) -> None: + """ + Determines how to handle an incoming finding with respect to grouping + if finding groups are enabled, use the supplied grouping mechanism to + store a reference of how the finding should be grouped + """ + if is_finding_groups_enabled() and group_by: + # If finding groups are enabled, group all findings by group name + name = finding_helper.get_group_by_group_name(finding, group_by) + if name is not None: + if name in group_names_to_findings_dict: + group_names_to_findings_dict[name].append(finding) + else: + group_names_to_findings_dict[name] = [finding] + + def process_request_response_pairs( + self, + finding: Finding + ) -> None: + """ + Search the unsaved finding for the following attributes to determine + if the data can be saved to the finding + - unsaved_req_resp + - unsaved_request + - unsaved_response + Create BurpRawRequestResponse objects linked to the finding without + returning the finding afterward + """ + if len(unsaved_req_resp := getattr(finding, 'unsaved_req_resp', [])) > 0: + for req_resp in unsaved_req_resp: + burp_rr = BurpRawRequestResponse( + finding=finding, + burpRequestBase64=base64.b64encode(req_resp["req"].encode("utf-8")), + burpResponseBase64=base64.b64encode(req_resp["resp"].encode("utf-8"))) + burp_rr.clean() + burp_rr.save() + + unsaved_request = getattr(finding, "unsaved_request", None) + unsaved_response = getattr(finding, "unsaved_response", None) + if unsaved_request is not None and unsaved_response is not None: + burp_rr = BurpRawRequestResponse( + finding=finding, + burpRequestBase64=base64.b64encode(unsaved_request.encode()), + burpResponseBase64=base64.b64encode(unsaved_response.encode())) + burp_rr.clean() + burp_rr.save() + + def process_endpoints( + self, + finding: Finding, + endpoints_to_add: List[Endpoint], + ) -> None: + """ + Process any endpoints to add to the finding. Endpoints could come from two places + - Directly from the report + - Supplied by the user from the import form + These endpoints will be processed in to endpoints objects and associated with the + finding and and product + """ + # Save the unsaved endpoints + self.chunk_endpoints_and_disperse(finding, finding.test, finding.unsaved_endpoints) + # Check for any that were added in the form + if len(endpoints_to_add) > 0: + logger.debug('endpoints_to_add: %s', endpoints_to_add) + self.chunk_endpoints_and_disperse(finding, finding.test, endpoints_to_add) + + def process_vulnerability_ids( + self, + finding: Finding + ) -> Finding: + """ + Parse the `unsaved_vulnerability_ids` field from findings after they are parsed + to create `Vulnerability_Id` objects with the finding associated correctly + """ + # Synchronize the cve field with the unsaved_vulnerability_ids + # We do this to be as flexible as possible to handle the fields until + # the cve field is not needed anymore and can be removed. + if finding.unsaved_vulnerability_ids and finding.cve: + # Make sure the first entry of the list is the value of the cve field + finding.unsaved_vulnerability_ids.insert(0, finding.cve) + elif finding.unsaved_vulnerability_ids and not finding.cve: + # If the cve field is not set, use the first entry of the list to set it + finding.cve = finding.unsaved_vulnerability_ids[0] + elif not finding.unsaved_vulnerability_ids and finding.cve: + # If there is no list, make one with the value of the cve field + finding.unsaved_vulnerability_ids = [finding.cve] + + if finding.unsaved_vulnerability_ids: + # Remove duplicates + finding.unsaved_vulnerability_ids = list(dict.fromkeys(finding.unsaved_vulnerability_ids)) + # Add all vulnerability ids to the database + for vulnerability_id in finding.unsaved_vulnerability_ids: + Vulnerability_Id( + vulnerability_id=vulnerability_id, + finding=finding, + ).save() + + return finding + + def process_files( + self, + finding: Finding, + ) -> None: + """ + Some parsers may supply files in the form of base64 encoded blobs, + so lets save them in the form of an attached file on the finding + object + """ + if finding.unsaved_files: + for unsaved_file in finding.unsaved_files: + data = base64.b64decode(unsaved_file.get('data')) + title = unsaved_file.get('title', '') + file_upload, _ = FileUpload.objects.get_or_create(title=title) + file_upload.file.save(title, ContentFile(data)) + file_upload.save() + finding.files.add(file_upload) + + def mitigate_finding( + self, + finding: Finding, + user: Dojo_User, + scan_date: datetime, + note_message: str, + finding_groups_enabled: bool, + push_to_jira: bool, + ) -> None: + """ + Mitigates a finding, all endpoint statuses, leaves a note on the finding + with a record of what happened, and then saves the finding. Changes to + this finding will also be synced with some ticket tracking system as well + as groups + """ + finding.active = False + finding.is_mitigated = True + finding.mitigated = scan_date + finding.mitigated_by = user + finding.notes.create( + author=user, + entry=note_message, + ) + # Mitigate the endpoint statuses + self.mitigate_endpoint_status(finding.status_finding.all(), user, kwuser=user, sync=True) + # to avoid pushing a finding group multiple times, we push those outside of the loop + if finding_groups_enabled and finding.finding_group: + # don't try to dedupe findings that we are closing + finding.save(dedupe_option=False) + else: + finding.save(dedupe_option=False, push_to_jira=push_to_jira) diff --git a/dojo/importers/default_importer.py b/dojo/importers/default_importer.py new file mode 100644 index 0000000000..d324f0e9af --- /dev/null +++ b/dojo/importers/default_importer.py @@ -0,0 +1,492 @@ +import logging +from abc import ABC +from datetime import datetime +from typing import List, Tuple + +from django.core.files.uploadedfile import TemporaryUploadedFile +from django.core.serializers import deserialize, serialize +from django.db.models.query_utils import Q +from django.utils import timezone + +import dojo.finding.helper as finding_helper +import dojo.jira_link.helper as jira_helper +import dojo.notifications.helper as notifications_helper +from dojo.importers.base_importer import BaseImporter, Parser +from dojo.models import ( + Dojo_User, + Engagement, + Finding, + Test, + Test_Import, +) +from dojo.utils import is_finding_groups_enabled + +logger = logging.getLogger(__name__) +deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") + + +class DefaultImporter(BaseImporter): + """ + The classic importer process used by DefectDojo + + This Importer is intended to be used when auditing the history + of findings at a given point in time is required + """ + def __init__(self, *args: list, **kwargs: dict): + """ + Bypass the __init__ method of the BaseImporter class + as it will raise a `NotImplemented` exception + """ + ABC.__init__(self, *args, **kwargs) + + def __new__(self, *args: list, **kwargs: dict): + """ + Bypass the __new__ method of the BaseImporter class + as it will raise a `NotImplemented` exception + """ + return ABC.__new__(self, *args, **kwargs) + + def create_test( + self, + scan_type: str, + test_type_name: str, + **kwargs: dict, + ) -> Test: + """ + Create a fresh test object to be used by the importer. This + new test will be attached to the supplied engagement with the + supplied user being marked as the lead of the test + """ + # Ensure the following fields were supplied in the kwargs + required_fields = ["engagement", "lead", "environment"] + if not all(field in kwargs for field in required_fields): + msg = ( + "(Importer) parse_findings_static_test_type - " + f"The following fields must be supplied: {required_fields}" + ) + raise ValueError(msg) + # Grab the fields from the kwargs + engagement = kwargs.get("engagement") + lead = kwargs.get("lead") + environment = kwargs.get("environment") + # Ensure a test type is available for use + test_type = self.get_or_create_test_type(test_type_name) + target_date = (kwargs.get("scan_date") or kwargs.get("now")) or timezone.now() + # Create the test object + return Test.objects.create( + title=kwargs.get("test_title"), + engagement=engagement, + lead=lead, + environment=environment, + test_type=test_type, + scan_type=scan_type, + target_start=target_date, + target_end=target_date, + percent_complete=100, + version=kwargs.get("version"), + branch_tag=kwargs.get("branch_tag"), + build_id=kwargs.get("build_id"), + commit_hash=kwargs.get("commit_hash"), + api_scan_configuration=kwargs.get("api_scan_configuration"), + tags=kwargs.get("tags"), + ) + + def process_scan( + self, + scan: TemporaryUploadedFile, + scan_type: str, + engagement: Engagement = None, + test: Test = None, + user: Dojo_User = None, + parsed_findings: List[Finding] = None, + **kwargs: dict, + ) -> Tuple[Test, int, int, int, int, int, Test_Import]: + """ + The full step process of taking a scan report, and converting it to + findings in the database. This entails the the following actions: + - Verify the API scan configuration (if supplied) + - Parser the findings + - Process the findings + - Update the timestamps on the test + - Update/Create import history objects + - Send out notifications + - Update the test progress + """ + logger.debug(f'IMPORT_SCAN: parameters: {locals()}') + # Get a user in some point + user = self.get_user_if_supplied(user=user) + # Validate the Tool_Configuration + engagement = self.verify_tool_configuration_from_engagement( + kwargs.get("api_scan_configuration", None), + engagement + ) + # Make sure timezone is applied to dates + kwargs["scan_date"], kwargs["now"] = self.add_timezone_scan_date_and_now( + kwargs.get("scan_date"), + now=kwargs.get("now", timezone.now()) + ) + # Fetch the parser based upon the string version of the scan type + parser = self.get_parser(scan_type) + # Get the findings from the parser based on what methods the parser supplies + # This could either mean traditional file parsing, or API pull parsing + test, parsed_findings = self.parse_findings(parser, scan_type, scan, test=None, engagement=engagement, **kwargs) + # process the findings in the foreground or background + new_findings = self.determine_process_method(test, parsed_findings, user, **kwargs) + # Close any old findings in the processed list if the the user specified for that + # to occur in the form that is then passed to the kwargs + closed_findings = self.close_old_findings(test, test.finding_set.values(), user, **kwargs) + # Update the timestamps of the test object by looking at the findings imported + test = self.update_timestamps(test, **kwargs) + # Update the test meta + test = self.update_test_meta(test, **kwargs) + # Save the test and engagement for changes to take affect + test.save() + test.engagement.save() + # Create a test import history object to record the flags sent to the importer + # This operation will return None if the user does not have the import history + # feature enabled + test_import_history = self.update_import_history( + Test_Import.IMPORT_TYPE, + test, + new_findings=new_findings, + closed_findings=closed_findings, + **kwargs, + ) + # Send out som notifications to the user + logger.debug('IMPORT_SCAN: Generating notifications') + notifications_helper.notify_test_created(test) + updated_count = len(new_findings) + len(closed_findings) + notifications_helper.notify_scan_added(test, updated_count, new_findings=new_findings, findings_mitigated=closed_findings) + # Update the test progress to reflect that the import has completed + logger.debug('IMPORT_SCAN: Updating Test progress') + self.update_test_progress(test) + logger.debug('IMPORT_SCAN: Done') + return test, 0, len(new_findings), len(closed_findings), 0, 0, test_import_history + + def process_findings( + self, + test: Test, + parsed_findings: List[Finding], + user: Dojo_User, + **kwargs: dict, + ) -> List[Finding]: + """ + Saves findings in memory that were parsed from the scan report into the database. + This process involves first saving associated objects such as endpoints, files, + vulnerability IDs, and request response pairs. Once all that has been completed, + the finding may be appended to a new or existing group based upon user selection + at import time + """ + new_findings = [] + logger.debug('starting import of %i parsed findings.', len(parsed_findings) if parsed_findings else 0) + group_names_to_findings_dict = {} + + for unsaved_finding in parsed_findings: + # make sure the severity is something is digestible + unsaved_finding = self.sanitize_severity(unsaved_finding) + # Filter on minimum severity if applicable + if (minimum_severity := kwargs.get("minimum_severity")) and (Finding.SEVERITIES[unsaved_finding.severity] > Finding.SEVERITIES[minimum_severity]): + # finding's severity is below the configured threshold : ignoring the finding + continue + + now = kwargs.get("now") + # Some parsers provide "mitigated" field but do not set timezone (because they are probably not available in the report) + # Finding.mitigated is DateTimeField and it requires timezone + if unsaved_finding.mitigated and not unsaved_finding.mitigated.tzinfo: + unsaved_finding.mitigated = unsaved_finding.mitigated.replace(tzinfo=now.tzinfo) + # Set some explicit fields on the finding + unsaved_finding.test = test + unsaved_finding.reporter = user + unsaved_finding.last_reviewed_by = user + unsaved_finding.last_reviewed = now + logger.debug('process_parsed_findings: active from report: %s, verified from report: %s', unsaved_finding.active, unsaved_finding.verified) + # indicates an override. Otherwise, do not change the value of unsaved_finding.active + if (active := kwargs.get("active")) is not None: + unsaved_finding.active = active + # indicates an override. Otherwise, do not change the value of verified + if (verified := kwargs.get("verified")) is not None: + unsaved_finding.verified = verified + # scan_date was provided, override value from parser + if (scan_date := kwargs.get("scan_date")) is not None: + unsaved_finding.date = scan_date.date() + if (service := kwargs.get("service")) is not None: + unsaved_finding.service = service + unsaved_finding.save(dedupe_option=False) + finding = unsaved_finding + # Determine how the finding should be grouped + group_by = kwargs.get("group_by") + self.process_finding_groups( + finding, + group_by, + group_names_to_findings_dict, + ) + # Process any request/response pairs + self.process_request_response_pairs(finding) + # Process any endpoints on the endpoint, or added on the form + self.process_endpoints(finding, kwargs.get("endpoints_to_add", [])) + # Process any tags + if finding.unsaved_tags: + finding.tags = finding.unsaved_tags + # Process any files + self.process_files(finding) + # Process vulnerability IDs + finding = self.process_vulnerability_ids(finding) + # Categorize this finding as a new one + new_findings.append(finding) + # to avoid pushing a finding group multiple times, we push those outside of the loop + push_to_jira = kwargs.get("push_to_jira", False) + if is_finding_groups_enabled() and group_by: + finding.save() + else: + finding.save(push_to_jira=push_to_jira) + + for (group_name, findings) in group_names_to_findings_dict.items(): + finding_helper.add_findings_to_auto_group( + group_name, + findings, + **kwargs + ) + if push_to_jira: + if findings[0].finding_group is not None: + jira_helper.push_to_jira(findings[0].finding_group) + else: + jira_helper.push_to_jira(findings[0]) + + sync = kwargs.get('sync', False) + if not sync: + return [serialize('json', [finding, ]) for finding in new_findings] + return new_findings + + def close_old_findings( + self, + test: Test, + findings: List[Finding], + user: Dojo_User, + scan_date: datetime = timezone.now(), + **kwargs: dict, + ) -> List[Finding]: + """ + Closes old findings based on a hash code match at either the product + or the engagement scope. Closing an old finding entails setting the + finding to mitigated status, setting all endpoint statuses to mitigated, + as well as leaving a not on the finding indicating that it was mitigated + because the vulnerability is no longer present in the submitted scan report. + """ + # First check if close old findings is desired + if kwargs.get("close_old_findings") is False: + return [] + logger.debug("REIMPORT_SCAN: Closing findings no longer present in scan report") + # Close old active findings that are not reported by this scan. + # Refactoring this to only call test.finding_set.values() once. + mitigated_hash_codes = [] + new_hash_codes = [] + for finding in findings: + new_hash_codes.append(finding["hash_code"]) + if getattr(finding, "is_mitigated", None): + mitigated_hash_codes.append(finding["hash_code"]) + for hash_code in new_hash_codes: + if hash_code == finding["hash_code"]: + new_hash_codes.remove(hash_code) + # Get the initial filtered list of old findings to be closed without + # considering the scope of the product or engagement + old_findings = Finding.objects.exclude( + test=test + ).exclude( + hash_code__in=new_hash_codes + ).filter( + test__test_type=test.test_type, + active=True + ) + # Accommodate for product scope or engagement scope + if kwargs.get("close_old_findings_product_scope"): + old_findings = old_findings.filter(test__engagement__product=test.engagement.product) + else: + old_findings = old_findings.filter(test__engagement=test.engagement) + # Use the service to differentiate further + if service := kwargs.get("service"): + old_findings = old_findings.filter(service=service) + else: + old_findings = old_findings.filter(Q(service__isnull=True) | Q(service__exact='')) + # Determine if pushing to jira or if the finding groups are enabled + push_to_jira = kwargs.get("push_to_jira", False) + finding_groups_enabled = is_finding_groups_enabled() + # Update the status of the findings and any endpoints + for old_finding in old_findings: + self.mitigate_finding( + old_finding, + user, + scan_date, + ( + "This finding has been automatically closed " + "as it is not present anymore in recent scans." + ), + finding_groups_enabled, + push_to_jira, + ) + # push finding groups to jira since we only only want to push whole groups + if finding_groups_enabled and push_to_jira: + for finding_group in {finding.finding_group for finding in old_findings if finding.finding_group is not None}: + jira_helper.push_to_jira(finding_group) + + return old_findings + + def parse_findings( + self, + parser: Parser, + scan_type: str, + scan: TemporaryUploadedFile, + test: Test = None, + **kwargs: dict, + ) -> Tuple[Test, List[Finding]]: + """ + A stub function for making function definitions easier to follow + with correct type signatures + """ + return BaseImporter.parse_findings( + self, + parser, + scan_type, + scan, + **kwargs, + ) + + def parse_findings_static_test_type( + self, + parser: Parser, + scan_type: str, + scan: TemporaryUploadedFile, + test: Test = None, + **kwargs: dict, + ) -> Tuple[Test, List[Finding]]: + """ + Creates a test object as part of the import process as there is not one present + at the time of import. Once the test is created, proceed with the traditional + file import as usual from the base class + """ + # by default test_type == scan_type + test = self.create_test( + scan_type, + scan_type, + **kwargs, + ) + logger.debug('IMPORT_SCAN: Parse findings') + # Use the parent method for the rest of this + return test, BaseImporter.parse_findings_static_test_type( + self, + parser, + scan_type, + scan, + test=test, + **kwargs, + ) + + def parse_findings_dynamic_test_type( + self, + parser: Parser, + scan_type: str, + scan: TemporaryUploadedFile, + **kwargs: dict, + ) -> Tuple[Test, List[Finding]]: + """ + Uses the parser to fetch any tests that may have been created + by the API based parser, aggregates all findings from each test + into a single test, and then renames the test is applicable + """ + logger.debug('IMPORT_SCAN parser v2: Create Test and parse findings') + parsed_findings = [] + tests = self.parse_dynamic_test_type_tests( + parser, + scan_type, + scan, + **kwargs, + ) + # Make sure we have at least one test returned + if len(tests) == 0: + logger.info(f'No tests found in import for {scan_type}') + return None, parsed_findings + # for now we only consider the first test in the list and artificially aggregate all findings of all tests + # this is the same as the old behavior as current import/reimporter implementation doesn't handle the case + # when there is more than 1 test + # + # we also aggregate the label of the Test_type to show the user the original scan_type + # only if they are different. This is to support meta format like SARIF + # so a report that have the label 'CodeScanner' will be changed to 'CodeScanner Scan (SARIF)' + test_type_name = scan_type + # Determine if we should use a custom test type name + if tests[0].type: + test_type_name = f"{tests[0].type} Scan" + if test_type_name != scan_type: + test_type_name = f"{test_type_name} ({scan_type})" + # Create a new test + test = self.create_test( + scan_type, + test_type_name, + **kwargs, + ) + # This part change the name of the Test + # we get it from the data of the parser + test_raw = tests[0] + if test_raw.name: + test.name = test_raw.name + if test_raw.description: + test.description = test_raw.description + test.save() + logger.debug('IMPORT_SCAN parser v2: Parse findings (aggregate)') + # Aggregate all the findings and return them with the newly created test + return test, self.parse_dynamic_test_type_findings_from_tests(tests) + + def sync_process_findings( + self, + test: Test, + parsed_findings: List[Finding], + user: Dojo_User, + **kwargs: dict, + ) -> List[Finding]: + """ + Processes findings in a synchronous manner such that all findings + will be processed in a worker/process/thread + """ + return self.process_findings( + test, + parsed_findings, + user, + sync=True, + **kwargs, + ) + + def async_process_findings( + self, + test: Test, + parsed_findings: List[Finding], + user: Dojo_User, + **kwargs: dict, + ) -> List[Finding]: + """ + Processes findings in chunks within N number of processes. The + ASYNC_FINDING_IMPORT_CHUNK_SIZE setting will determine how many + findings will be processed in a given worker/process/thread + """ + chunk_list = self.chunk_objects(parsed_findings) + results_list = [] + # First kick off all the workers + for findings_list in chunk_list: + result = self.process_findings( + test, + findings_list, + user, + sync=False, + **kwargs, + ) + # Since I dont want to wait until the task is done right now, save the id + # So I can check on the task later + results_list += [result] + # After all tasks have been started, time to pull the results + logger.info('IMPORT_SCAN: Collecting Findings') + for results in results_list: + serial_new_findings = results.get() + new_findings += [next(deserialize("json", finding)).object for finding in serial_new_findings] + logger.info('IMPORT_SCAN: All Findings Collected') + # Indicate that the test is not complete yet as endpoints will still be rolling in. + test.percent_complete = 50 + test.save() + return new_findings diff --git a/dojo/importers/default_reimporter.py b/dojo/importers/default_reimporter.py new file mode 100644 index 0000000000..be6455e161 --- /dev/null +++ b/dojo/importers/default_reimporter.py @@ -0,0 +1,877 @@ +import logging +from abc import ABC +from datetime import datetime +from typing import List, Tuple + +from django.core.files.uploadedfile import TemporaryUploadedFile +from django.core.serializers import deserialize, serialize +from django.db.models.query_utils import Q +from django.utils import timezone + +import dojo.finding.helper as finding_helper +import dojo.jira_link.helper as jira_helper +import dojo.notifications.helper as notifications_helper +from dojo.importers.base_importer import BaseImporter, Parser +from dojo.models import ( + Dojo_User, + Engagement, + Finding, + Notes, + Test, + Test_Import, +) +from dojo.utils import is_finding_groups_enabled + +logger = logging.getLogger(__name__) +deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") + + +class DefaultReImporter(BaseImporter): + """ + The classic reimporter process used by DefectDojo + + This importer is intended to be used when mitigation of + vulnerabilities is the ultimate tool for getting a current + point time view of security of a given product + """ + def __init__(self, *args: list, **kwargs: dict): + """ + Bypass the __init__ method of the BaseImporter class + as it will raise a `NotImplemented` exception + """ + ABC.__init__(self, *args, **kwargs) + + def __new__(self, *args: list, **kwargs: dict): + """ + Bypass the __new__ method of the BaseImporter class + as it will raise a `NotImplemented` exception + """ + return ABC.__new__(self, *args, **kwargs) + + def process_scan( + self, + scan: TemporaryUploadedFile, + scan_type: str, + engagement: Engagement = None, + test: Test = None, + user: Dojo_User = None, + parsed_findings: List[Finding] = None, + **kwargs: dict, + ) -> Tuple[Test, int, int, int, int, int, Test_Import]: + """ + The full step process of taking a scan report, and converting it to + findings in the database. This entails the the following actions: + - Verify the API scan configuration (if supplied) + - Parser the findings + - Process the findings + - Update the timestamps on the test + - Update/Create import history objects + - Send out notifications + - Update the test progress + """ + logger.debug(f'REIMPORT_SCAN: parameters: {locals()}') + # Get a user in some point + user = self.get_user_if_supplied(user=user) + # Validate the Tool_Configuration + test = self.verify_tool_configuration_from_test( + kwargs.get("api_scan_configuration", None), + test + ) + # Make sure timezone is applied to dates + kwargs["scan_date"], kwargs["now"] = self.add_timezone_scan_date_and_now( + kwargs.get("scan_date"), + now=kwargs.get("now", timezone.now()) + ) + # Fetch the parser based upon the string version of the scan type + parser = self.get_parser(scan_type) + # Get the findings from the parser based on what methods the parser supplies + # This could either mean traditional file parsing, or API pull parsing + parsed_findings = self.parse_findings(parser, scan_type, scan, test=test, engagement=engagement, **kwargs) + # process the findings in the foreground or background + ( + new_findings, + reactivated_findings, + findings_to_mitigate, + untouched_findings, + ) = self.determine_process_method(test, parsed_findings, user, **kwargs) + # Close any old findings in the processed list if the the user specified for that + # to occur in the form that is then passed to the kwargs + closed_findings = self.close_old_findings(test, findings_to_mitigate, user, **kwargs) + # Update the timestamps of the test object by looking at the findings imported + logger.debug("REIMPORT_SCAN: Updating test/engagement timestamps") + test = self.update_timestamps(test, **kwargs) + # Update the test meta + test = self.update_test_meta(test, **kwargs) + # Save the test and engagement for changes to take affect + test.save() + test.engagement.save() + logger.debug("REIMPORT_SCAN: Updating test tags") + self.update_test_tags(test, kwargs.get("tags", [])) + # Create a test import history object to record the flags sent to the importer + # This operation will return None if the user does not have the import history + # feature enabled + test_import_history = self.update_import_history( + Test_Import.REIMPORT_TYPE, + test, + new_findings=new_findings, + closed_findings=closed_findings, + reactivated_findings=reactivated_findings, + untouched_findings=untouched_findings, + **kwargs, + ) + # Send out som notifications to the user + logger.debug('REIMPORT_SCAN: Generating notifications') + updated_count = ( + len(closed_findings) + len(reactivated_findings) + len(new_findings) + ) + notifications_helper.notify_scan_added( + test, + updated_count, + new_findings=new_findings, + findings_mitigated=closed_findings, + findings_reactivated=reactivated_findings, + findings_untouched=untouched_findings, + ) + # Update the test progress to reflect that the import has completed + logger.debug('REIMPORT_SCAN: Updating Test progress') + self.update_test_progress(test) + logger.debug('REIMPORT_SCAN: Done') + return ( + test, + updated_count, + len(new_findings), + len(closed_findings), + len(reactivated_findings), + len(untouched_findings), + test_import_history, + ) + + def process_findings( + self, + test: Test, + parsed_findings: List[Finding], + user: Dojo_User, + **kwargs: dict, + ) -> Tuple[List[Finding], List[Finding], List[Finding], List[Finding]]: + """ + Saves findings in memory that were parsed from the scan report into the database. + This process involves first saving associated objects such as endpoints, files, + vulnerability IDs, and request response pairs. Once all that has been completed, + the finding may be appended to a new or existing group based upon user selection + at import time + """ + + original_items = list(test.finding_set.all()) + deduplication_algorithm = test.deduplication_algorithm + group_names_to_findings_dict = {} + new_items = [] + reactivated_items = [] + unchanged_items = [] + + group_names_to_findings_dict = {} + logger.debug(f"starting reimport of {len(parsed_findings) if parsed_findings else 0} items.") + logger.debug("STEP 1: looping over findings from the reimported report and trying to match them to existing findings") + deduplicationLogger.debug(f"Algorithm used for matching new findings to existing findings: {deduplication_algorithm}") + + for unsaved_finding in parsed_findings: + # make sure the severity is something is digestible + unsaved_finding = self.sanitize_severity(unsaved_finding) + # Filter on minimum severity if applicable + if (minimum_severity := kwargs.get("minimum_severity")) and (Finding.SEVERITIES[unsaved_finding.severity] > Finding.SEVERITIES[minimum_severity]): + # finding's severity is below the configured threshold : ignoring the finding + continue + + now = kwargs.get("now") + group_by = kwargs.get("group_by") + push_to_jira = kwargs.get("push_to_jira", False) + # Some parsers provide "mitigated" field but do not set timezone (because they are probably not available in the report) + # Finding.mitigated is DateTimeField and it requires timezone + if unsaved_finding.mitigated and not unsaved_finding.mitigated.tzinfo: + unsaved_finding.mitigated = unsaved_finding.mitigated.replace(tzinfo=now.tzinfo) + # Override the test if needed + if not hasattr(unsaved_finding, "test"): + unsaved_finding.test = test + # Set the service supplied at import time + if service := kwargs.get("service"): + unsaved_finding.service = service + # Clean any endpoints that are on the finding + self.clean_unsaved_endpoints(unsaved_finding.unsaved_endpoints) + # Calculate the hash code to be used to identify duplicates + unsaved_finding.hash_code = unsaved_finding.compute_hash_code() + deduplicationLogger.debug(f"unsaved finding's hash_code: {unsaved_finding.hash_code}") + # Match any findings to this new one coming in + matched_findings = self.match_new_finding_to_existing_finding(unsaved_finding, test, deduplication_algorithm) + deduplicationLogger.debug(f"found {len(matched_findings)} findings matching with current new finding") + # Determine how to proceed based on whether matches were found or not + if matched_findings: + existing_finding = matched_findings[0] + finding, force_continue = self.process_matched_finding( + unsaved_finding, + existing_finding, + user, + new_items, + reactivated_items, + unchanged_items, + **kwargs + ) + # Determine if we should skip the rest of the loop + if force_continue: + continue + # Update endpoints on the existing finding with those on the new finding + if finding.dynamic_finding: + logger.debug( + "Re-import found an existing dynamic finding for this new " + "finding. Checking the status of endpoints" + ) + self.update_endpoint_status(existing_finding, unsaved_finding, user) + else: + finding = self.process_finding_that_was_not_matched( + unsaved_finding, + user, + group_names_to_findings_dict, + new_items, + reactivated_items, + unchanged_items, + **kwargs + ) + # This condition __appears__ to always be true, but am afraid to remove it + if finding: + # Process the rest of the items on the finding + finding = self.finding_post_processing( + finding, + unsaved_finding, + test, + new_items, + reactivated_items, + unchanged_items, + **kwargs + ) + # finding = new finding or existing finding still in the upload report + # to avoid pushing a finding group multiple times, we push those outside of the loop + if is_finding_groups_enabled() and group_by: + finding.save() + else: + finding.save(push_to_jira=push_to_jira) + + to_mitigate = (set(original_items) - set(reactivated_items) - set(unchanged_items)) + # due to #3958 we can have duplicates inside the same report + # this could mean that a new finding is created and right after + # that it is detected as the 'matched existing finding' for a + # following finding in the same report + # this means untouched can have this finding inside it, + # while it is in fact a new finding. So we subtract new_items + untouched = set(unchanged_items) - set(to_mitigate) - set(new_items) + # Process groups + self.process_groups_for_all_findings( + group_names_to_findings_dict, + reactivated_items, + unchanged_items, + **kwargs, + ) + # Process the results and return them back + return self.process_results( + new_items, + reactivated_items, + to_mitigate, + untouched, + **kwargs, + ) + + def close_old_findings( + self, + test: Test, + findings: List[Finding], + user: Dojo_User, + scan_date: datetime = timezone.now(), + **kwargs: dict, + ) -> List[Finding]: + """ + Updates the status of findings that were detected as "old" by the reimport + process findings methods + """ + # First check if close old findings is desired + if kwargs.get("close_old_findings") is False: + return [] + logger.debug("REIMPORT_SCAN: Closing findings no longer present in scan report") + # Determine if pushing to jira or if the finding groups are enabled + push_to_jira = kwargs.get("push_to_jira", False) + finding_groups_enabled = is_finding_groups_enabled() + mitigated_findings = [] + for finding in findings: + if not finding.mitigated or not finding.is_mitigated: + logger.debug("mitigating finding: %i:%s", finding.id, finding) + self.mitigate_finding( + finding, + user, + scan_date, + f"Mitigated by {test.test_type} re-upload.", + finding_groups_enabled, + push_to_jira, + ) + mitigated_findings.append(finding) + # push finding groups to jira since we only only want to push whole groups + if finding_groups_enabled and push_to_jira: + for finding_group in {finding.finding_group for finding in findings if finding.finding_group is not None}: + jira_helper.push_to_jira(finding_group) + + return mitigated_findings + + def parse_findings_static_test_type( + self, + parser: Parser, + scan_type: str, + scan: TemporaryUploadedFile, + test: Test = None, + **kwargs: dict, + ) -> List[Finding]: + """ + Parses the findings from file and assigns them to the test + that was supplied + """ + logger.debug("REIMPORT_SCAN: Parse findings") + # Use the parent method for the rest of this + return BaseImporter.parse_findings_static_test_type( + self, + parser, + scan_type, + scan, + test=test, + **kwargs, + ) + + def parse_findings_dynamic_test_type( + self, + parser: Parser, + scan_type: str, + scan: TemporaryUploadedFile, + **kwargs: dict, + ) -> List[Finding]: + """ + Uses the parser to fetch any tests that may have been created + by the API based parser, aggregates all findings from each test + into a single test, and then renames the test is applicable + """ + logger.debug("REIMPORT_SCAN parser v2: Create parse findings") + return BaseImporter.parse_findings_dynamic_test_type( + self, + parser, + scan_type, + scan, + **kwargs, + ) + + def sync_process_findings( + self, + test: Test, + parsed_findings: List[Finding], + user: Dojo_User, + **kwargs: dict, + ) -> Tuple[List[Finding], List[Finding], List[Finding], List[Finding]]: + """ + Processes findings in a synchronous manner such that all findings + will be processed in a worker/process/thread + """ + return self.process_findings( + test, + parsed_findings, + user, + sync=True, + **kwargs, + ) + + def async_process_findings( + self, + test: Test, + parsed_findings: List[Finding], + user: Dojo_User, + **kwargs: dict, + ) -> Tuple[List[Finding], List[Finding], List[Finding], List[Finding]]: + """ + Processes findings in chunks within N number of processes. The + ASYNC_FINDING_IMPORT_CHUNK_SIZE setting will determine how many + findings will be processed in a given worker/process/thread + """ + chunk_list = self.chunk_objects(parsed_findings) + new_findings = [] + reactivated_findings = [] + findings_to_mitigate = [] + untouched_findings = [] + # First kick off all the workers + for findings_list in chunk_list: + result = self.process_findings( + test, + findings_list, + user, + sync=False, + **kwargs, + ) + # Since I dont want to wait until the task is done right now, save the id + # So I can check on the task later + results_list += [result] + # After all tasks have been started, time to pull the results + logger.debug("REIMPORT_SCAN: Collecting Findings") + for results in results_list: + ( + serial_new_findings, + serial_reactivated_findings, + serial_findings_to_mitigate, + serial_untouched_findings, + ) = results.get() + new_findings += [ + next(deserialize("json", finding)).object + for finding in serial_new_findings + ] + reactivated_findings += [ + next(deserialize("json", finding)).object + for finding in serial_reactivated_findings + ] + findings_to_mitigate += [ + next(deserialize("json", finding)).object + for finding in serial_findings_to_mitigate + ] + untouched_findings += [ + next(deserialize("json", finding)).object + for finding in serial_untouched_findings + ] + logger.debug("REIMPORT_SCAN: All Findings Collected") + # Indicate that the test is not complete yet as endpoints will still be rolling in. + test.percent_complete = 50 + test.save() + self.update_test_progress(test, sync=False) + + return new_findings, reactivated_findings, findings_to_mitigate, untouched_findings + + def match_new_finding_to_existing_finding( + self, + unsaved_finding: Finding, + test: Test, + deduplication_algorithm: str, + ) -> List[Finding]: + """ + Matches a single new finding to N existing findings and then returns those matches + """ + # This code should match the logic used for deduplication out of the re-import feature. + # See utils.py deduplicate_* functions + deduplicationLogger.debug('return findings bases on algorithm: %s', deduplication_algorithm) + if deduplication_algorithm == 'hash_code': + return Finding.objects.filter( + test=test, + hash_code=unsaved_finding.hash_code + ).exclude(hash_code=None).order_by('id') + elif deduplication_algorithm == 'unique_id_from_tool': + return Finding.objects.filter( + test=test, + unique_id_from_tool=unsaved_finding.unique_id_from_tool + ).exclude(unique_id_from_tool=None).order_by('id') + elif deduplication_algorithm == 'unique_id_from_tool_or_hash_code': + query = Finding.objects.filter( + Q(test=test), + (Q(hash_code__isnull=False) & Q(hash_code=unsaved_finding.hash_code)) + | (Q(unique_id_from_tool__isnull=False) & Q(unique_id_from_tool=unsaved_finding.unique_id_from_tool)) + ).order_by('id') + deduplicationLogger.debug(query.query) + return query + elif deduplication_algorithm == 'legacy': + # This is the legacy reimport behavior. Although it's pretty flawed and doesn't match the legacy algorithm for deduplication, + # this is left as is for simplicity. + # Re-writing the legacy deduplication here would be complicated and counter-productive. + # If you have use cases going through this section, you're advised to create a deduplication configuration for your parser + logger.debug("Legacy reimport. In case of issue, you're advised to create a deduplication configuration in order not to go through this section") + return Finding.objects.filter( + title=unsaved_finding.title, + test=test, + severity=unsaved_finding.severity, + numerical_severity=Finding.get_numerical_severity(unsaved_finding.severity)).order_by('id') + else: + logger.error(f"Internal error: unexpected deduplication_algorithm: \"{deduplication_algorithm}\"") + return None + + def process_matched_finding( + self, + unsaved_finding: Finding, + existing_finding: Finding, + user: Dojo_User, + new_items: List[Finding], + reactivated_items: List[Finding], + unchanged_items: List[Finding], + **kwargs: dict, + ) -> Tuple[Finding, bool]: + """ + Determine how to handle the an existing finding based on the status + that is possesses at the time of reimport + """ + if existing_finding.false_p or existing_finding.out_of_scope or existing_finding.risk_accepted: + return self.process_matched_special_status_finding( + unsaved_finding, + existing_finding, + user, + new_items, + reactivated_items, + unchanged_items, + **kwargs + ) + elif existing_finding.is_mitigated: + return self.process_matched_mitigated_finding( + unsaved_finding, + existing_finding, + user, + new_items, + reactivated_items, + unchanged_items, + **kwargs + ) + else: + return self.process_matched_active_finding( + unsaved_finding, + existing_finding, + user, + new_items, + reactivated_items, + unchanged_items, + **kwargs + ) + + def process_matched_special_status_finding( + self, + unsaved_finding: Finding, + existing_finding: Finding, + user: Dojo_User, + new_items: List[Finding], + reactivated_items: List[Finding], + unchanged_items: List[Finding], + **kwargs: dict, + ) -> Tuple[Finding, bool]: + """ + Determine if there is parity between statuses of the new and existing finding. + If so, do not touch either finding, and move on to the next unsaved finding + """ + logger.debug( + f"Skipping existing finding (it is marked as false positive: {existing_finding.false_p} " + f"and/or out of scope: {existing_finding.out_of_scope} or is a risk accepted: " + f"{existing_finding.risk_accepted}) - {existing_finding.id}: {existing_finding.title} " + f"({existing_finding.component_name} - {existing_finding.component_version})" + ) + # If all statuses are the same between findings, we can safely move on to the next + # finding in the report. Return True here to force a continue in the loop + if ( + existing_finding.false_p == unsaved_finding.false_p + and existing_finding.out_of_scope == unsaved_finding.out_of_scope + and existing_finding.risk_accepted == unsaved_finding.risk_accepted + ): + unchanged_items.append(existing_finding) + return existing_finding, True + # The finding was not an exact match, so we need to add more details about from the + # new finding to the existing. Return False here to make process further + return existing_finding, False + + def process_matched_mitigated_finding( + self, + unsaved_finding: Finding, + existing_finding: Finding, + user: Dojo_User, + new_items: List[Finding], + reactivated_items: List[Finding], + unchanged_items: List[Finding], + **kwargs: dict, + ) -> Tuple[Finding, bool]: + """ + Determine how mitigated the existing and new findings really are. We need + to cover circumstances where mitigation timestamps are different, and + decide which one to honor + """ + # if the reimported item has a mitigation time, we can compare + scan_type = kwargs.get("scan_type") + verified = kwargs.get("verified") + if unsaved_finding.is_mitigated: + # The new finding is already mitigated, so nothing to change on the + # the existing finding + unchanged_items.append(existing_finding) + # Look closer at the mitigation timestamp + if unsaved_finding.mitigated: + logger.debug(f"item mitigated time: {unsaved_finding.mitigated.timestamp()}") + logger.debug(f"finding mitigated time: {existing_finding.mitigated.timestamp()}") + # Determine if the mitigation timestamp is the same between the new finding + # and the existing finding. If they are, we do not need any further processing + if unsaved_finding.mitigated.timestamp() == existing_finding.mitigated.timestamp(): + logger.debug( + "New imported finding and already existing finding have the same mitigation " + "date, will skip as they are the same." + ) + # Return True here to force the loop to continue + return existing_finding, True + else: + logger.debug( + "New imported finding and already existing finding are both mitigated but " + "have different dates, not taking action" + ) + # Return True here to force the loop to continue + return existing_finding, True + else: + # even if there is no mitigation time, skip it, because both the current finding and + # the reimported finding are is_mitigated + # Return True here to force the loop to continue + return existing_finding, True + else: + if kwargs.get("do_not_reactivate"): + logger.debug( + "Skipping reactivating by user's choice do_not_reactivate: " + f" - {existing_finding.id}: {existing_finding.title} " + f"({existing_finding.component_name} - {existing_finding.component_version})" + ) + # Search for an existing note that this finding has been skipped for reactivation + # before this current time + existing_note = existing_finding.notes.filter( + entry=f"Finding has skipped reactivation from {scan_type} re-upload with user decision do_not_reactivate.", + author=user, + ) + # If a note has not been left before, we can skip this finding + if len(existing_note) == 0: + note = Notes( + entry=f"Finding has skipped reactivation from {scan_type} re-upload with user decision do_not_reactivate.", + author=user, + ) + note.save() + existing_finding.notes.add(note) + existing_finding.save(dedupe_option=False) + # Return True here to force the loop to continue + return existing_finding, True + else: + logger.debug( + f"Reactivating: - {existing_finding.id}: {existing_finding.title} " + f"({existing_finding.component_name} - {existing_finding.component_version})" + ) + existing_finding.mitigated = None + existing_finding.is_mitigated = False + existing_finding.mitigated_by = None + existing_finding.active = True + if verified is not None: + existing_finding.verified = verified + + component_name = getattr(unsaved_finding, "component_name", None) + component_version = getattr(unsaved_finding, "component_version", None) + existing_finding.component_name = existing_finding.component_name or component_name + existing_finding.component_version = existing_finding.component_version or component_version + existing_finding.save(dedupe_option=False) + # don't dedupe before endpoints are added + existing_finding.save(dedupe_option=False) + note = Notes(entry=f"Re-activated by {scan_type} re-upload.", author=user) + note.save() + endpoint_statuses = existing_finding.status_finding.exclude( + Q(false_positive=True) + | Q(out_of_scope=True) + | Q(risk_accepted=True) + ) + self.chunk_endpoints_and_reactivate(endpoint_statuses) + existing_finding.notes.add(note) + reactivated_items.append(existing_finding) + # The new finding is active while the existing on is mitigated. The existing finding needs to + # be updated in some way + # Return False here to make sure further processing happens + return existing_finding, False + + def process_matched_active_finding( + self, + unsaved_finding: Finding, + existing_finding: Finding, + user: Dojo_User, + new_items: List[Finding], + reactivated_items: List[Finding], + unchanged_items: List[Finding], + **kwargs: dict, + ) -> Tuple[Finding, bool]: + """ + The existing finding must be active here, so we need to compare it + closely with the new finding coming in and determine how to proceed + """ + # if finding associated to new item is none of risk accepted, mitigated, false positive or out of scope + # existing findings may be from before we had component_name/version fields + logger.debug( + f"Updating existing finding: {existing_finding.id}: {existing_finding.title} " + f"({existing_finding.component_name} - {existing_finding.component_version})" + ) + # First check that the existing finding is definitely not mitigated + if not (existing_finding.mitigated and existing_finding.is_mitigated): + verified = kwargs.get("verified") + logger.debug("Reimported item matches a finding that is currently open.") + if unsaved_finding.is_mitigated: + logger.debug("Reimported mitigated item matches a finding that is currently open, closing.") + # TODO: Implement a date comparison for opened defectdojo findings before closing them by reimporting, + # as they could be force closed by the scanner but a DD user forces it open ? + logger.debug( + f"Closing: {existing_finding.id}: {existing_finding.title} " + f"({existing_finding.component_name} - {existing_finding.component_version})" + ) + existing_finding.mitigated = unsaved_finding.mitigated + existing_finding.is_mitigated = True + existing_finding.mitigated_by = unsaved_finding.mitigated_by + existing_finding.active = False + if verified is not None: + existing_finding.verified = verified + elif unsaved_finding.risk_accepted or unsaved_finding.false_p or unsaved_finding.out_of_scope: + logger.debug('Reimported mitigated item matches a finding that is currently open, closing.') + logger.debug( + f"Closing: {existing_finding.id}: {existing_finding.title} " + f"({existing_finding.component_name} - {existing_finding.component_version})" + ) + existing_finding.risk_accepted = unsaved_finding.risk_accepted + existing_finding.false_p = unsaved_finding.false_p + existing_finding.out_of_scope = unsaved_finding.out_of_scope + existing_finding.active = False + if verified is not None: + existing_finding.verified = verified + else: + # if finding is the same but list of affected was changed, finding is marked as unchanged. This is a known issue + unchanged_items.append(existing_finding) + # Set the component name and version on the existing finding if it is present + # on the old finding, but not present on the existing finding (do not override) + component_name = getattr(unsaved_finding, "component_name", None) + component_version = getattr(unsaved_finding, "component_version", None) + if (component_name is not None and not existing_finding.component_name) or ( + component_version is not None and not existing_finding.component_version + ): + existing_finding.component_name = existing_finding.component_name or component_name + existing_finding.component_version = existing_finding.component_version or component_version + existing_finding.save(dedupe_option=False) + # Return False here to make sure further processing happens + return existing_finding, False + + def process_finding_that_was_not_matched( + self, + unsaved_finding: Finding, + user: Dojo_User, + group_names_to_findings_dict: dict, + new_items: List[Finding], + reactivated_items: List[Finding], + unchanged_items: List[Finding], + **kwargs: dict, + ) -> Finding: + """ + Create a new finding from the one parsed from the report + """ + # Set some explicit settings + unsaved_finding.reporter = user + unsaved_finding.last_reviewed = timezone.now() + unsaved_finding.last_reviewed_by = user + # indicates an override. Otherwise, do not change the value of unsaved_finding.active + if (active := kwargs.get("active")) is not None: + unsaved_finding.active = active + # indicates an override. Otherwise, do not change the value of verified + if (verified := kwargs.get("verified")) is not None: + unsaved_finding.verified = verified + # scan_date was provided, override value from parser + if (scan_date := kwargs.get("scan_date")) is not None: + unsaved_finding.date = scan_date.date() + # Save it. Don't dedupe before endpoints are added. + unsaved_finding.save(dedupe_option=False) + finding = unsaved_finding + logger.debug( + "Reimport created new finding as no existing finding match: " + f"{finding.id}: {finding.title} " + f"({finding.component_name} - {finding.component_version})" + ) + # Manage the finding grouping selection + self.process_finding_groups( + unsaved_finding, + kwargs.get("group_by"), + group_names_to_findings_dict, + ) + # Add the new finding to the list + new_items.append(unsaved_finding) + # Process any request/response pairs + self.process_request_response_pairs(unsaved_finding) + return unsaved_finding + + def finding_post_processing( + self, + finding: Finding, + finding_from_report: Finding, + test: Test, + new_items: List[Finding], + reactivated_items: List[Finding], + unchanged_items: List[Finding], + **kwargs: dict, + ) -> None: + """ + Save all associated objects to the finding after it has been saved + for the purpose of foreign key restrictions + """ + self.chunk_endpoints_and_disperse(finding, test, finding_from_report.unsaved_endpoints) + if endpoints_to_add := kwargs.get("endpoints_to_add"): + self.chunk_endpoints_and_disperse(finding, test, endpoints_to_add) + # Update finding tags + if finding_from_report.unsaved_tags: + finding.tags = finding_from_report.unsaved_tags + # Process any files + if finding_from_report.unsaved_files: + finding.unsaved_files = finding_from_report.unsaved_files + self.process_files(finding) + # Process vulnerability IDs + finding = self.process_vulnerability_ids(finding) + + return finding + + def process_groups_for_all_findings( + self, + group_names_to_findings_dict: dict, + reactivated_items: List[Finding], + unchanged_items: List[Finding], + **kwargs: dict, + ) -> None: + """ + Add findings to a group that may or may not exist, based upon the users + selection at import time + """ + push_to_jira = kwargs.get("push_to_jira", False) + for (group_name, findings) in group_names_to_findings_dict.items(): + finding_helper.add_findings_to_auto_group( + group_name, + findings, + **kwargs + ) + if push_to_jira: + if findings[0].finding_group is not None: + jira_helper.push_to_jira(findings[0].finding_group) + else: + jira_helper.push_to_jira(findings[0]) + + if is_finding_groups_enabled() and push_to_jira: + for finding_group in { + finding.finding_group + for finding in reactivated_items + unchanged_items + if finding.finding_group is not None and not finding.is_mitigated + }: + jira_helper.push_to_jira(finding_group) + + def process_results( + self, + new_items: List[Finding], + reactivated_items: List[Finding], + to_mitigate: List[Finding], + untouched: List[Finding], + **kwargs: dict, + ) -> Tuple[List[Finding], List[Finding], List[Finding], List[Finding]]: + """ + Determine how to to return the results based on whether the process was + ran asynchronous or not + """ + if not kwargs.get("sync", False): + serialized_new_items = [ + serialize("json", [finding]) for finding in new_items + ] + serialized_reactivated_items = [ + serialize("json", [finding]) for finding in reactivated_items + ] + serialized_to_mitigate = [ + serialize("json", [finding]) for finding in to_mitigate + ] + serialized_untouched = [ + serialize("json", [finding]) for finding in untouched + ] + return ( + serialized_new_items, + serialized_reactivated_items, + serialized_to_mitigate, + serialized_untouched, + ) + else: + return new_items, reactivated_items, to_mitigate, untouched diff --git a/dojo/importers/endpoint_manager.py b/dojo/importers/endpoint_manager.py new file mode 100644 index 0000000000..0c6ff8a083 --- /dev/null +++ b/dojo/importers/endpoint_manager.py @@ -0,0 +1,144 @@ +import logging +from typing import List + +from django.conf import settings +from django.utils import timezone + +from dojo.celery import app +from dojo.decorators import dojo_async_task +from dojo.models import ( + Dojo_User, + Endpoint_Status, + Finding, +) + +logger = logging.getLogger(__name__) + + +class DefaultReImporterEndpointManager: + @dojo_async_task + @app.task() + def mitigate_endpoint_status( + self, + endpoint_status_list: List[Endpoint_Status], + user: Dojo_User, + **kwargs: dict, + ) -> None: + """ + Mitigates all endpoint status objects that are supplied + """ + now = timezone.now() + for endpoint_status in endpoint_status_list: + # Only mitigate endpoints that are actually active + if endpoint_status.mitigated is False: + endpoint_status.mitigated_time = now + endpoint_status.last_modified = now + endpoint_status.mitigated_by = user + endpoint_status.mitigated = True + endpoint_status.save() + return None + + @dojo_async_task + @app.task() + def reactivate_endpoint_status( + self, + endpoint_status_list: List[Endpoint_Status], + **kwargs: dict, + ) -> None: + """ + Reactivate all endpoint status objects that are supplied + """ + for endpoint_status in endpoint_status_list: + # Only reactivate endpoints that are actually mitigated + if endpoint_status.mitigated: + logger.debug("Re-import: reactivating endpoint %s that is present in this scan", str(endpoint_status.endpoint)) + endpoint_status.mitigated_by = None + endpoint_status.mitigated_time = None + endpoint_status.mitigated = False + endpoint_status.last_modified = timezone.now() + endpoint_status.save() + return None + + def chunk_endpoints_and_reactivate( + self, + endpoint_status_list: List[Endpoint_Status], + **kwargs: dict, + ) -> None: + """ + Reactivates all endpoint status objects. Whether this function will asynchronous or not is dependent + on the ASYNC_FINDING_IMPORT setting. If it is set to true, endpoint statuses will be chunked, + and dispersed over celery workers. + """ + # Determine if this can be run async + if settings.ASYNC_FINDING_IMPORT: + chunked_list = self.chunk_objects(endpoint_status_list) + # If there is only one chunk, then do not bother with async + if len(chunked_list) < 2: + self.reactivate_endpoint_status(endpoint_status_list, sync=True) + logger.debug(f"Split endpoints into {len(chunked_list)} chunks of {len(chunked_list[0])}") + # First kick off all the workers + for endpoint_status_list in chunked_list: + self.reactivate_endpoint_status(endpoint_status_list, sync=False) + else: + self.reactivate_endpoint_status(endpoint_status_list, sync=True) + return None + + def chunk_endpoints_and_mitigate( + self, + endpoint_status_list: List[Endpoint_Status], + user: Dojo_User, + **kwargs: dict, + ) -> None: + """ + Mitigates all endpoint status objects. Whether this function will asynchronous or not is dependent + on the ASYNC_FINDING_IMPORT setting. If it is set to true, endpoint statuses will be chunked, + and dispersed over celery workers. + """ + # Determine if this can be run async + if settings.ASYNC_FINDING_IMPORT: + chunked_list = self.chunk_objects(endpoint_status_list) + # If there is only one chunk, then do not bother with async + if len(chunked_list) < 2: + self.mitigate_endpoint_status(endpoint_status_list, user, sync=True) + logger.debug(f"Split endpoints into {len(chunked_list)} chunks of {len(chunked_list[0])}") + # First kick off all the workers + for endpoint_status_list in chunked_list: + self.mitigate_endpoint_status(endpoint_status_list, user, sync=False) + else: + self.mitigate_endpoint_status(endpoint_status_list, user, sync=True) + return None + + def update_endpoint_status( + self, + existing_finding: Finding, + new_finding: Finding, + user: Dojo_User, + **kwargs: dict, + ) -> None: + """ + Update the list of endpoints from the new finding with the list that is in the old finding + """ + # New endpoints are already added in serializers.py / views.py (see comment "# for existing findings: make sure endpoints are present or created") + # So we only need to mitigate endpoints that are no longer present + # using `.all()` will mark as mitigated also `endpoint_status` with flags `false_positive`, `out_of_scope` and `risk_accepted`. This is a known issue. This is not a bug. This is a future. + existing_finding_endpoint_status_list = existing_finding.status_finding.all() + new_finding_endpoints_list = new_finding.unsaved_endpoints + if new_finding.is_mitigated: + # New finding is mitigated, so mitigate all old endpoints + endpoint_status_to_mitigate = existing_finding_endpoint_status_list + else: + # Mitigate any endpoints in the old finding not found in the new finding + endpoint_status_to_mitigate = list( + filter( + lambda existing_finding_endpoint_status: existing_finding_endpoint_status.endpoint not in new_finding_endpoints_list, + existing_finding_endpoint_status_list) + ) + # Re-activate any endpoints in the old finding that are in the new finding + endpoint_status_to_reactivate = list( + filter( + lambda existing_finding_endpoint_status: existing_finding_endpoint_status.endpoint in new_finding_endpoints_list, + existing_finding_endpoint_status_list) + ) + self.chunk_endpoints_and_reactivate(endpoint_status_to_reactivate) + self.chunk_endpoints_and_mitigate(endpoint_status_to_mitigate, user) + return None diff --git a/dojo/importers/importer/importer.py b/dojo/importers/importer/importer.py deleted file mode 100644 index 19c5acac1a..0000000000 --- a/dojo/importers/importer/importer.py +++ /dev/null @@ -1,409 +0,0 @@ -import base64 -import logging - -from django.conf import settings -from django.core import serializers -from django.core.exceptions import ValidationError -from django.core.files.base import ContentFile -from django.db.models.query_utils import Q -from django.utils import timezone - -import dojo.finding.helper as finding_helper -import dojo.jira_link.helper as jira_helper -import dojo.notifications.helper as notifications_helper -from dojo.celery import app -from dojo.decorators import dojo_async_task -from dojo.importers import utils as importer_utils -from dojo.models import BurpRawRequestResponse, FileUpload, Finding, Test, Test_Import, Test_Type -from dojo.tools.factory import get_parser -from dojo.utils import get_current_user, is_finding_groups_enabled - -logger = logging.getLogger(__name__) -deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") - - -class DojoDefaultImporter: - - def create_test(self, scan_type, test_type_name, engagement, lead, environment, tags=None, - scan_date=None, version=None, branch_tag=None, build_id=None, commit_hash=None, now=timezone.now(), - api_scan_configuration=None, title=None): - - test_type, created = Test_Type.objects.get_or_create( - name=test_type_name) - - if created: - logger.info('Created new Test_Type with name %s because a report is being imported', test_type.name) - - if scan_date and not scan_date.tzinfo: - scan_date = timezone.make_aware(scan_date) - - if now and not now.tzinfo: - now = timezone.make_aware(now) - - test = Test( - title=title, - engagement=engagement, - lead=lead, - test_type=test_type, - scan_type=scan_type, - target_start=scan_date or now, - target_end=scan_date or now, - environment=environment, - percent_complete=100, - version=version, - branch_tag=branch_tag, - build_id=build_id, - commit_hash=commit_hash, - api_scan_configuration=api_scan_configuration, - tags=tags, - ) - - test.full_clean() - test.save() - return test - - @dojo_async_task - @app.task(ignore_result=False) - def process_parsed_findings(self, test, parsed_findings, scan_type, user, active=None, verified=None, minimum_severity=None, - endpoints_to_add=None, push_to_jira=None, group_by=None, now=timezone.now(), service=None, scan_date=None, - create_finding_groups_for_all_findings=True, **kwargs): - logger.debug('endpoints_to_add: %s', endpoints_to_add) - new_findings = [] - items = parsed_findings - logger.debug('starting import of %i items.', len(items) if items else 0) - group_names_to_findings_dict = {} - - for item in items: - # FIXME hack to remove when all parsers have unit tests for this attribute - # Importing the cvss module via: - # `from cvss import CVSS3` - # _and_ given a CVSS vector string such as: - # cvss_vector_str = 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:N', - # the following severity calculation returns the - # string values of, "None" instead of the expected string values - # of "Info": - # ``` - # cvss_obj = CVSS3(cvss_vector_str) - # severities = cvss_obj.severities() - # print(severities) - # ('None', 'None', 'None') - # print(severities[0]) - # 'None' - # print(type(severities[0])) - # - # ``` - if (item.severity.lower().startswith('info') or item.severity.lower() == 'none') and item.severity != 'Info': - item.severity = 'Info' - - item.numerical_severity = Finding.get_numerical_severity(item.severity) - - if minimum_severity and (Finding.SEVERITIES[item.severity] - > Finding.SEVERITIES[minimum_severity]): - # finding's severity is below the configured threshold : ignoring the finding - continue - - # Some parsers provide "mitigated" field but do not set timezone (because they are probably not available in the report) - # Finding.mitigated is DateTimeField and it requires timezone - if item.mitigated and not item.mitigated.tzinfo: - item.mitigated = item.mitigated.replace(tzinfo=now.tzinfo) - - item.test = test - item.reporter = user if user else get_current_user - item.last_reviewed = now - item.last_reviewed_by = user if user else get_current_user - - logger.debug('process_parsed_findings: active from report: %s, verified from report: %s', item.active, item.verified) - if active is not None: - # indicates an override. Otherwise, do not change the value of item.active - item.active = active - - if verified is not None: - # indicates an override. Otherwise, do not change the value of verified - item.verified = verified - - # if scan_date was provided, override value from parser - if scan_date: - item.date = scan_date.date() - - if service: - item.service = service - - item.save(dedupe_option=False) - - if is_finding_groups_enabled() and group_by: - # If finding groups are enabled, group all findings by group name - name = finding_helper.get_group_by_group_name(item, group_by) - if name is not None: - if name in group_names_to_findings_dict: - group_names_to_findings_dict[name].append(item) - else: - group_names_to_findings_dict[name] = [item] - - if (hasattr(item, 'unsaved_req_resp') - and len(item.unsaved_req_resp) > 0): - for req_resp in item.unsaved_req_resp: - burp_rr = BurpRawRequestResponse( - finding=item, - burpRequestBase64=base64.b64encode(req_resp["req"].encode("utf-8")), - burpResponseBase64=base64.b64encode(req_resp["resp"].encode("utf-8"))) - burp_rr.clean() - burp_rr.save() - - if (item.unsaved_request is not None - and item.unsaved_response is not None): - burp_rr = BurpRawRequestResponse( - finding=item, - burpRequestBase64=base64.b64encode(item.unsaved_request.encode()), - burpResponseBase64=base64.b64encode(item.unsaved_response.encode())) - burp_rr.clean() - burp_rr.save() - - importer_utils.chunk_endpoints_and_disperse(item, test, item.unsaved_endpoints) - if endpoints_to_add: - importer_utils.chunk_endpoints_and_disperse(item, test, endpoints_to_add) - - if item.unsaved_tags: - item.tags = item.unsaved_tags - - if item.unsaved_files: - for unsaved_file in item.unsaved_files: - data = base64.b64decode(unsaved_file.get('data')) - title = unsaved_file.get('title', '') - file_upload, _file_upload_created = FileUpload.objects.get_or_create( - title=title, - ) - file_upload.file.save(title, ContentFile(data)) - file_upload.save() - item.files.add(file_upload) - - importer_utils.handle_vulnerability_ids(item) - - new_findings.append(item) - # to avoid pushing a finding group multiple times, we push those outside of the loop - if is_finding_groups_enabled() and group_by: - item.save() - else: - item.save(push_to_jira=push_to_jira) - - for (group_name, findings) in group_names_to_findings_dict.items(): - finding_helper.add_findings_to_auto_group(group_name, findings, group_by, create_finding_groups_for_all_findings, **kwargs) - if push_to_jira: - if findings[0].finding_group is not None: - jira_helper.push_to_jira(findings[0].finding_group) - else: - jira_helper.push_to_jira(findings[0]) - - sync = kwargs.get('sync', False) - if not sync: - return [serializers.serialize('json', [finding, ]) for finding in new_findings] - return new_findings - - def close_old_findings(self, test, scan_date_time, user, push_to_jira=None, service=None, close_old_findings_product_scope=False): - # Close old active findings that are not reported by this scan. - # Refactoring this to only call test.finding_set.values() once. - findings = test.finding_set.values() - mitigated_hash_codes = [] - new_hash_codes = [] - for finding in findings: - new_hash_codes.append(finding["hash_code"]) - if finding["is_mitigated"]: - mitigated_hash_codes.append(finding["hash_code"]) - for hash_code in new_hash_codes: - if hash_code == finding["hash_code"]: - new_hash_codes.remove(hash_code) - if close_old_findings_product_scope: - # Close old findings of the same test type in the same product - old_findings = Finding.objects.exclude(test=test) \ - .exclude(hash_code__in=new_hash_codes) \ - .filter(test__engagement__product=test.engagement.product, - test__test_type=test.test_type, - active=True) - else: - # Close old findings of the same test type in the same engagement - old_findings = Finding.objects.exclude(test=test) \ - .exclude(hash_code__in=new_hash_codes) \ - .filter(test__engagement=test.engagement, - test__test_type=test.test_type, - active=True) - - if service: - old_findings = old_findings.filter(service=service) - else: - old_findings = old_findings.filter(Q(service__isnull=True) | Q(service__exact='')) - - for old_finding in old_findings: - old_finding.active = False - old_finding.is_mitigated = True - old_finding.mitigated = scan_date_time - old_finding.notes.create(author=user, - entry="This finding has been automatically closed" - " as it is not present anymore in recent scans.") - endpoint_status = old_finding.status_finding.all() - for status in endpoint_status: - status.mitigated_by = user - status.mitigated_time = timezone.now() - status.mitigated = True - status.last_modified = timezone.now() - status.save() - - old_finding.tags.add('stale') - - # to avoid pushing a finding group multiple times, we push those outside of the loop - if is_finding_groups_enabled() and old_finding.finding_group: - # don't try to dedupe findings that we are closing - old_finding.save(dedupe_option=False) - else: - old_finding.save(dedupe_option=False, push_to_jira=push_to_jira) - - if is_finding_groups_enabled() and push_to_jira: - for finding_group in set(finding.finding_group for finding in old_findings if finding.finding_group is not None): # noqa: C401 - jira_helper.push_to_jira(finding_group) - - return old_findings - - def import_scan(self, scan, scan_type, engagement, lead, environment, active=None, verified=None, tags=None, minimum_severity=None, - user=None, endpoints_to_add=None, scan_date=None, version=None, branch_tag=None, build_id=None, - commit_hash=None, push_to_jira=None, close_old_findings=False, close_old_findings_product_scope=False, - group_by=None, api_scan_configuration=None, service=None, title=None, create_finding_groups_for_all_findings=True, - apply_tags_to_findings=False, apply_tags_to_endpoints=False): - - logger.debug(f'IMPORT_SCAN: parameters: {locals()}') - - user = user or get_current_user() - - now = timezone.now() - - if api_scan_configuration and api_scan_configuration.product != engagement.product: - msg = 'API Scan Configuration has to be from same product as the Engagement' - raise ValidationError(msg) - - # check if the parser that handle the scan_type manage tests - # if yes, we parse the data first - # after that we customize the Test_Type to reflect the data - # This allow us to support some meta-formats like SARIF or the generic format - parser = get_parser(scan_type) - if hasattr(parser, 'get_tests'): - logger.debug('IMPORT_SCAN parser v2: Create Test and parse findings') - try: - tests = parser.get_tests(scan_type, scan) - except ValueError as e: - logger.warning(e) - raise ValidationError(e) - # for now we only consider the first test in the list and artificially aggregate all findings of all tests - # this is the same as the old behavior as current import/reimporter implementation doesn't handle the case - # when there is more than 1 test - # - # we also aggregate the label of the Test_type to show the user the original scan_type - # only if they are different. This is to support meta format like SARIF - # so a report that have the label 'CodeScanner' will be changed to 'CodeScanner Scan (SARIF)' - test_type_name = scan_type - if len(tests) > 0: - if tests[0].type: - test_type_name = tests[0].type + " Scan" - if test_type_name != scan_type: - test_type_name = f"{test_type_name} ({scan_type})" - - test = self.create_test(scan_type, test_type_name, engagement, lead, environment, scan_date=scan_date, tags=tags, - version=version, branch_tag=branch_tag, build_id=build_id, commit_hash=commit_hash, now=now, - api_scan_configuration=api_scan_configuration, title=title) - # This part change the name of the Test - # we get it from the data of the parser - test_raw = tests[0] - if test_raw.name: - test.name = test_raw.name - if test_raw.description: - test.description = test_raw.description - test.save() - - logger.debug('IMPORT_SCAN parser v2: Parse findings (aggregate)') - # currently we only support import one Test - # so for parser that support multiple tests (like SARIF) - # we aggregate all the findings into one uniq test - parsed_findings = [] - for test_raw in tests: - parsed_findings.extend(test_raw.findings) - else: - logger.info(f'No tests found in import for {scan_type}') - else: - logger.debug('IMPORT_SCAN: Create Test') - # by default test_type == scan_type - test = self.create_test(scan_type, scan_type, engagement, lead, environment, scan_date=scan_date, tags=tags, - version=version, branch_tag=branch_tag, build_id=build_id, commit_hash=commit_hash, now=now, - api_scan_configuration=api_scan_configuration, title=title) - - logger.debug('IMPORT_SCAN: Parse findings') - parser = get_parser(scan_type) - try: - parsed_findings = parser.get_findings(scan, test) - except ValueError as e: - logger.warning(e) - raise ValidationError(e) - - logger.debug('IMPORT_SCAN: Processing findings') - new_findings = [] - if settings.ASYNC_FINDING_IMPORT: - chunk_list = importer_utils.chunk_list(parsed_findings) - results_list = [] - # First kick off all the workers - for findings_list in chunk_list: - result = self.process_parsed_findings(test, findings_list, scan_type, user, active=active, - verified=verified, minimum_severity=minimum_severity, - endpoints_to_add=endpoints_to_add, push_to_jira=push_to_jira, - group_by=group_by, now=now, service=service, scan_date=scan_date, sync=False, - create_finding_groups_for_all_findings=create_finding_groups_for_all_findings) - # Since I dont want to wait until the task is done right now, save the id - # So I can check on the task later - results_list += [result] - # After all tasks have been started, time to pull the results - logger.info('IMPORT_SCAN: Collecting Findings') - for results in results_list: - serial_new_findings = results.get() - new_findings += [next(serializers.deserialize("json", finding)).object for finding in serial_new_findings] - logger.info('IMPORT_SCAN: All Findings Collected') - # Indicate that the test is not complete yet as endpoints will still be rolling in. - test.percent_complete = 50 - test.save() - else: - new_findings = self.process_parsed_findings(test, parsed_findings, scan_type, user, active=active, - verified=verified, minimum_severity=minimum_severity, - endpoints_to_add=endpoints_to_add, push_to_jira=push_to_jira, - group_by=group_by, now=now, service=service, scan_date=scan_date, sync=True, - create_finding_groups_for_all_findings=create_finding_groups_for_all_findings) - - closed_findings = [] - if close_old_findings: - logger.debug('IMPORT_SCAN: Closing findings no longer present in scan report') - closed_findings = self.close_old_findings(test, scan_date, user=user, push_to_jira=push_to_jira, service=service, - close_old_findings_product_scope=close_old_findings_product_scope) - - logger.debug('IMPORT_SCAN: Updating test/engagement timestamps') - importer_utils.update_timestamps(test, version, branch_tag, build_id, commit_hash, now, scan_date) - - test_import = None - if settings.TRACK_IMPORT_HISTORY: - logger.debug('IMPORT_SCAN: Updating Import History') - test_import = importer_utils.update_import_history(Test_Import.IMPORT_TYPE, active, verified, tags, minimum_severity, - endpoints_to_add, version, branch_tag, build_id, commit_hash, - push_to_jira, close_old_findings, test, new_findings, closed_findings) - if apply_tags_to_findings and tags: - for finding in test_import.findings_affected.all(): - for tag in tags: - finding.tags.add(tag) - - if apply_tags_to_endpoints and tags: - for finding in test_import.findings_affected.all(): - for endpoint in finding.endpoints.all(): - for tag in tags: - endpoint.tags.add(tag) - - logger.debug('IMPORT_SCAN: Generating notifications') - notifications_helper.notify_test_created(test) - updated_count = len(new_findings) + len(closed_findings) - notifications_helper.notify_scan_added(test, updated_count, new_findings=new_findings, findings_mitigated=closed_findings) - - logger.debug('IMPORT_SCAN: Updating Test progress') - importer_utils.update_test_progress(test) - - logger.debug('IMPORT_SCAN: Done') - - return test, len(new_findings), len(closed_findings), test_import diff --git a/dojo/importers/reimporter/reimporter.py b/dojo/importers/reimporter/reimporter.py deleted file mode 100644 index 9a3ebda828..0000000000 --- a/dojo/importers/reimporter/reimporter.py +++ /dev/null @@ -1,779 +0,0 @@ -import base64 -import logging - -from django.conf import settings -from django.core import serializers -from django.core.exceptions import ValidationError -from django.core.files.base import ContentFile -from django.db.models import Q -from django.utils import timezone - -import dojo.finding.helper as finding_helper -import dojo.jira_link.helper as jira_helper -import dojo.notifications.helper as notifications_helper -from dojo.celery import app -from dojo.decorators import dojo_async_task -from dojo.importers import utils as importer_utils -from dojo.importers.reimporter import utils as reimporter_utils -from dojo.models import BurpRawRequestResponse, FileUpload, Finding, Notes, Test_Import -from dojo.tools.factory import get_parser -from dojo.utils import get_current_user, is_finding_groups_enabled - -logger = logging.getLogger(__name__) -deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") - - -class DojoDefaultReImporter: - @dojo_async_task - @app.task(ignore_result=False) - def process_parsed_findings( - self, - test, - parsed_findings, - scan_type, - user, - active=None, - verified=None, - minimum_severity=None, - endpoints_to_add=None, - push_to_jira=None, - group_by=None, - now=timezone.now(), - service=None, - scan_date=None, - do_not_reactivate=False, - create_finding_groups_for_all_findings=True, - **kwargs, - ): - - items = parsed_findings - original_items = list(test.finding_set.all()) - new_items = [] - finding_count = 0 - finding_added_count = 0 - reactivated_count = 0 - reactivated_items = [] - unchanged_count = 0 - unchanged_items = [] - - logger.debug("starting reimport of %i items.", len(items) if items else 0) - deduplication_algorithm = test.deduplication_algorithm - - i = 0 - group_names_to_findings_dict = {} - logger.debug( - "STEP 1: looping over findings from the reimported report and trying to match them to existing findings" - ) - deduplicationLogger.debug( - "Algorithm used for matching new findings to existing findings: %s", - deduplication_algorithm, - ) - for item in items: - # FIXME hack to remove when all parsers have unit tests for this attribute - if item.severity.lower().startswith("info") and item.severity != "Info": - item.severity = "Info" - - item.numerical_severity = Finding.get_numerical_severity(item.severity) - - if minimum_severity and ( - Finding.SEVERITIES[item.severity] > Finding.SEVERITIES[minimum_severity] - ): - # finding's severity is below the configured threshold : ignoring the finding - continue - - # existing findings may be from before we had component_name/version fields - component_name = ( - item.component_name if hasattr(item, "component_name") else None - ) - component_version = ( - item.component_version if hasattr(item, "component_version") else None - ) - - # Some parsers provide "mitigated" field but do not set timezone (because it is probably not available in the report) - # Finding.mitigated is DateTimeField and it requires timezone - if item.mitigated and not item.mitigated.tzinfo: - item.mitigated = item.mitigated.replace(tzinfo=now.tzinfo) - - if not hasattr(item, "test"): - item.test = test - - if service: - item.service = service - - if item.dynamic_finding: - for e in item.unsaved_endpoints: - try: - e.clean() - except ValidationError as err: - logger.warning( - "DefectDojo is storing broken endpoint because cleaning wasn't successful: " - f"{err}" - ) - - item.hash_code = item.compute_hash_code() - deduplicationLogger.debug("item's hash_code: %s", item.hash_code) - - findings = reimporter_utils.match_new_finding_to_existing_finding( - item, test, deduplication_algorithm - ) - deduplicationLogger.debug( - "found %i findings matching with current new finding", len(findings) - ) - - if findings: - # existing finding found - finding = findings[0] - if finding.false_p or finding.out_of_scope or finding.risk_accepted: - logger.debug( - "%i: skipping existing finding (it is marked as false positive:%s and/or out of scope:%s or is a risk accepted:%s): %i:%s:%s:%s", - i, - finding.false_p, - finding.out_of_scope, - finding.risk_accepted, - finding.id, - finding, - finding.component_name, - finding.component_version, - ) - if ( - finding.false_p == item.false_p - and finding.out_of_scope == item.out_of_scope - and finding.risk_accepted == item.risk_accepted - ): - unchanged_items.append(finding) - unchanged_count += 1 - continue - elif finding.is_mitigated: - # if the reimported item has a mitigation time, we can compare - if item.is_mitigated: - unchanged_items.append(finding) - unchanged_count += 1 - if item.mitigated: - logger.debug( - "item mitigated time: " - + str(item.mitigated.timestamp()) - ) - logger.debug( - "finding mitigated time: " - + str(finding.mitigated.timestamp()) - ) - if ( - item.mitigated.timestamp() - == finding.mitigated.timestamp() - ): - logger.debug( - "New imported finding and already existing finding have the same mitigation date, will skip as they are the same." - ) - continue - if ( - item.mitigated.timestamp() - != finding.mitigated.timestamp() - ): - logger.debug( - "New imported finding and already existing finding are both mitigated but have different dates, not taking action" - ) - # TODO: implement proper date-aware reimporting mechanism, if an imported finding is closed more recently than the defectdojo finding, then there might be details in the scanner that should be added - continue - else: - # even if there is no mitigation time, skip it, because both the current finding and the reimported finding are is_mitigated - continue - else: - if not do_not_reactivate: - logger.debug( - "%i: reactivating: %i:%s:%s:%s", - i, - finding.id, - finding, - finding.component_name, - finding.component_version, - ) - finding.mitigated = None - finding.is_mitigated = False - finding.mitigated_by = None - finding.active = True - if verified is not None: - finding.verified = verified - if do_not_reactivate: - logger.debug( - "%i: skipping reactivating by user's choice do_not_reactivate: %i:%s:%s:%s", - i, - finding.id, - finding, - finding.component_name, - finding.component_version, - ) - existing_note = finding.notes.filter( - entry=f"Finding has skipped reactivation from {scan_type} re-upload with user decision do_not_reactivate.", - author=user, - ) - if len(existing_note) == 0: - note = Notes( - entry=f"Finding has skipped reactivation from {scan_type} re-upload with user decision do_not_reactivate.", - author=user, - ) - note.save() - finding.notes.add(note) - finding.save(dedupe_option=False) - continue - # existing findings may be from before we had component_name/version fields - finding.component_name = ( - finding.component_name - if finding.component_name - else component_name - ) - finding.component_version = ( - finding.component_version - if finding.component_version - else component_version - ) - - # don't dedupe before endpoints are added - finding.save(dedupe_option=False) - note = Notes( - entry=f"Re-activated by {scan_type} re-upload.", author=user - ) - note.save() - - endpoint_statuses = finding.status_finding.exclude( - Q(false_positive=True) - | Q(out_of_scope=True) - | Q(risk_accepted=True) - ) - reimporter_utils.chunk_endpoints_and_reactivate(endpoint_statuses) - - finding.notes.add(note) - reactivated_items.append(finding) - reactivated_count += 1 - else: - # if finding associated to new item is none of risk accepted, mitigated, false positive or out of scope - # existing findings may be from before we had component_name/version fields - logger.debug( - "%i: updating existing finding: %i:%s:%s:%s", - i, - finding.id, - finding, - finding.component_name, - finding.component_version, - ) - if not (finding.mitigated and finding.is_mitigated): - logger.debug( - "Reimported item matches a finding that is currently open." - ) - if item.is_mitigated: - logger.debug( - "Reimported mitigated item matches a finding that is currently open, closing." - ) - # TODO: Implement a date comparison for opened defectdojo findings before closing them by reimporting, as they could be force closed by the scanner but a DD user forces it open ? - logger.debug( - "%i: closing: %i:%s:%s:%s", - i, - finding.id, - finding, - finding.component_name, - finding.component_version, - ) - finding.mitigated = item.mitigated - finding.is_mitigated = True - finding.mitigated_by = item.mitigated_by - finding.active = False - if verified is not None: - finding.verified = verified - elif item.risk_accepted or item.false_p or item.out_of_scope: - logger.debug('Reimported mitigated item matches a finding that is currently open, closing.') - logger.debug('%i: closing: %i:%s:%s:%s', i, finding.id, finding, finding.component_name, finding.component_version) - finding.risk_accepted = item.risk_accepted - finding.false_p = item.false_p - finding.out_of_scope = item.out_of_scope - finding.active = False - if verified is not None: - finding.verified = verified - else: - # if finding is the same but list of affected was changed, finding is marked as unchanged. This is a known issue - unchanged_items.append(finding) - unchanged_count += 1 - - if (component_name is not None and not finding.component_name) or ( - component_version is not None and not finding.component_version - ): - finding.component_name = ( - finding.component_name - if finding.component_name - else component_name - ) - finding.component_version = ( - finding.component_version - if finding.component_version - else component_version - ) - finding.save(dedupe_option=False) - - if finding.dynamic_finding: - logger.debug( - "Re-import found an existing dynamic finding for this new finding. Checking the status of endpoints" - ) - reimporter_utils.update_endpoint_status(finding, item, user) - else: - # no existing finding found - item.reporter = user - item.last_reviewed = timezone.now() - item.last_reviewed_by = user - - if active is not None: - # indicates an override. Otherwise, do not change the value of item.active - item.active = active - - if verified is not None: - # indicates an override. Otherwise, do not change the value of verified - item.verified = verified - - # if scan_date was provided, override value from parser - if scan_date: - item.date = scan_date.date() - - # Save it. Don't dedupe before endpoints are added. - item.save(dedupe_option=False) - logger.debug( - "%i: reimport created new finding as no existing finding match: %i:%s:%s:%s", - i, - item.id, - item, - item.component_name, - item.component_version, - ) - - # only new items get auto grouped to avoid confusion around already existing items that are already grouped - if is_finding_groups_enabled() and group_by: - # If finding groups are enabled, group all findings by group name - name = finding_helper.get_group_by_group_name(item, group_by) - if name is not None: - if name in group_names_to_findings_dict: - group_names_to_findings_dict[name].append(item) - else: - group_names_to_findings_dict[name] = [item] - - finding_added_count += 1 - new_items.append(item) - finding = item - - if hasattr(item, "unsaved_req_resp"): - for req_resp in item.unsaved_req_resp: - burp_rr = BurpRawRequestResponse( - finding=finding, - burpRequestBase64=base64.b64encode( - req_resp["req"].encode("utf-8") - ), - burpResponseBase64=base64.b64encode( - req_resp["resp"].encode("utf-8") - ), - ) - burp_rr.clean() - burp_rr.save() - - if item.unsaved_request and item.unsaved_response: - burp_rr = BurpRawRequestResponse( - finding=finding, - burpRequestBase64=base64.b64encode( - item.unsaved_request.encode() - ), - burpResponseBase64=base64.b64encode( - item.unsaved_response.encode() - ), - ) - burp_rr.clean() - burp_rr.save() - - # for existing findings: make sure endpoints are present or created - if finding: - finding_count += 1 - importer_utils.chunk_endpoints_and_disperse( - finding, test, item.unsaved_endpoints - ) - if endpoints_to_add: - importer_utils.chunk_endpoints_and_disperse( - finding, test, endpoints_to_add - ) - - if item.unsaved_tags: - finding.tags = item.unsaved_tags - - if item.unsaved_files: - for unsaved_file in item.unsaved_files: - data = base64.b64decode(unsaved_file.get("data")) - title = unsaved_file.get("title", "") - ( - file_upload, - _file_upload_created, - ) = FileUpload.objects.get_or_create( - title=title, - ) - file_upload.file.save(title, ContentFile(data)) - file_upload.save() - finding.files.add(file_upload) - - if finding.unsaved_vulnerability_ids: - importer_utils.handle_vulnerability_ids(finding) - - # existing findings may be from before we had component_name/version fields - finding.component_name = ( - finding.component_name if finding.component_name else component_name - ) - finding.component_version = ( - finding.component_version - if finding.component_version - else component_version - ) - - # finding = new finding or existing finding still in the upload report - # to avoid pushing a finding group multiple times, we push those outside of the loop - if is_finding_groups_enabled() and group_by: - finding.save() - else: - finding.save(push_to_jira=push_to_jira) - - to_mitigate = ( - set(original_items) - set(reactivated_items) - set(unchanged_items) - ) - # due to #3958 we can have duplicates inside the same report - # this could mean that a new finding is created and right after - # that it is detected as the 'matched existing finding' for a - # following finding in the same report - # this means untouched can have this finding inside it, - # while it is in fact a new finding. So we substract new_items - untouched = set(unchanged_items) - set(to_mitigate) - set(new_items) - - for (group_name, findings) in group_names_to_findings_dict.items(): - finding_helper.add_findings_to_auto_group(group_name, findings, group_by, create_finding_groups_for_all_findings, **kwargs) - if push_to_jira: - if findings[0].finding_group is not None: - jira_helper.push_to_jira(findings[0].finding_group) - else: - jira_helper.push_to_jira(findings[0]) - - if is_finding_groups_enabled() and push_to_jira: - for finding_group in set( # noqa: C401 - finding.finding_group - for finding in reactivated_items + unchanged_items - if finding.finding_group is not None and not finding.is_mitigated - ): - jira_helper.push_to_jira(finding_group) - - sync = kwargs.get("sync", False) - if not sync: - serialized_new_items = [ - serializers.serialize( - "json", - [ - finding, - ], - ) - for finding in new_items - ] - serialized_reactivated_items = [ - serializers.serialize( - "json", - [ - finding, - ], - ) - for finding in reactivated_items - ] - serialized_to_mitigate = [ - serializers.serialize( - "json", - [ - finding, - ], - ) - for finding in to_mitigate - ] - serialized_untouched = [ - serializers.serialize( - "json", - [ - finding, - ], - ) - for finding in untouched - ] - return ( - serialized_new_items, - serialized_reactivated_items, - serialized_to_mitigate, - serialized_untouched, - ) - - return new_items, reactivated_items, to_mitigate, untouched - - def close_old_findings( - self, test, to_mitigate, scan_date_time, user, push_to_jira=None - ): - logger.debug("IMPORT_SCAN: Closing findings no longer present in scan report") - mitigated_findings = [] - for finding in to_mitigate: - if not finding.mitigated or not finding.is_mitigated: - logger.debug("mitigating finding: %i:%s", finding.id, finding) - finding.mitigated = scan_date_time - finding.is_mitigated = True - finding.mitigated_by = user - finding.active = False - - endpoint_status = finding.status_finding.all() - reimporter_utils.mitigate_endpoint_status( - endpoint_status, user, kwuser=user, sync=True - ) - - # to avoid pushing a finding group multiple times, we push those outside of the loop - if is_finding_groups_enabled() and finding.finding_group: - # don't try to dedupe findings that we are closing - finding.save(dedupe_option=False) - else: - finding.save(push_to_jira=push_to_jira, dedupe_option=False) - - note = Notes( - entry=f"Mitigated by {test.test_type} re-upload.", author=user - ) - note.save() - finding.notes.add(note) - mitigated_findings.append(finding) - - if is_finding_groups_enabled() and push_to_jira: - for finding_group in set( # noqa: C401 - finding.finding_group - for finding in to_mitigate - if finding.finding_group is not None - ): - jira_helper.push_to_jira(finding_group) - - return mitigated_findings - - def reimport_scan( - self, - scan, - scan_type, - test, - active=None, - verified=None, - tags=None, - minimum_severity=None, - user=None, - endpoints_to_add=None, - scan_date=None, - version=None, - branch_tag=None, - build_id=None, - commit_hash=None, - push_to_jira=None, - close_old_findings=True, - group_by=None, - api_scan_configuration=None, - service=None, - do_not_reactivate=False, - create_finding_groups_for_all_findings=True, - apply_tags_to_findings=False, - apply_tags_to_endpoints=False, - ): - - logger.debug(f"REIMPORT_SCAN: parameters: {locals()}") - - user = user or get_current_user() - - now = timezone.now() - - if api_scan_configuration: - if api_scan_configuration.product != test.engagement.product: - msg = "API Scan Configuration has to be from same product as the Test" - raise ValidationError(msg) - if test.api_scan_configuration != api_scan_configuration: - test.api_scan_configuration = api_scan_configuration - test.save() - - # check if the parser that handle the scan_type manage tests - parser = get_parser(scan_type) - if hasattr(parser, "get_tests"): - logger.debug("REIMPORT_SCAN parser v2: Create parse findings") - try: - tests = parser.get_tests(scan_type, scan) - except ValueError as e: - logger.warning(e) - raise ValidationError(e) - # for now we only consider the first test in the list and artificially aggregate all findings of all tests - # this is the same as the old behavior as current import/reimporter implementation doesn't handle the case - # when there is more than 1 test - parsed_findings = [] - for test_raw in tests: - parsed_findings.extend(test_raw.findings) - else: - logger.debug("REIMPORT_SCAN: Parse findings") - try: - parsed_findings = parser.get_findings(scan, test) - except ValueError as e: - logger.warning(e) - raise ValidationError(e) - - logger.debug("REIMPORT_SCAN: Processing findings") - new_findings = [] - reactivated_findings = [] - findings_to_mitigate = [] - untouched_findings = [] - if settings.ASYNC_FINDING_IMPORT: - chunk_list = importer_utils.chunk_list(parsed_findings) - results_list = [] - # First kick off all the workers - for findings_list in chunk_list: - result = self.process_parsed_findings( - test, - findings_list, - scan_type, - user, - active=active, - verified=verified, - minimum_severity=minimum_severity, - endpoints_to_add=endpoints_to_add, - push_to_jira=push_to_jira, - group_by=group_by, - now=now, - service=service, - scan_date=scan_date, - sync=False, - do_not_reactivate=do_not_reactivate, - create_finding_groups_for_all_findings=create_finding_groups_for_all_findings, - ) - - # Since I dont want to wait until the task is done right now, save the id - # So I can check on the task later - results_list += [result] - # After all tasks have been started, time to pull the results - logger.debug("REIMPORT_SCAN: Collecting Findings") - for results in results_list: - ( - serial_new_findings, - serial_reactivated_findings, - serial_findings_to_mitigate, - serial_untouched_findings, - ) = results.get() - new_findings += [ - next(serializers.deserialize("json", finding)).object - for finding in serial_new_findings - ] - reactivated_findings += [ - next(serializers.deserialize("json", finding)).object - for finding in serial_reactivated_findings - ] - findings_to_mitigate += [ - next(serializers.deserialize("json", finding)).object - for finding in serial_findings_to_mitigate - ] - untouched_findings += [ - next(serializers.deserialize("json", finding)).object - for finding in serial_untouched_findings - ] - logger.debug("REIMPORT_SCAN: All Findings Collected") - # Indicate that the test is not complete yet as endpoints will still be rolling in. - test.percent_complete = 50 - test.save() - importer_utils.update_test_progress(test) - else: - ( - new_findings, - reactivated_findings, - findings_to_mitigate, - untouched_findings, - ) = self.process_parsed_findings( - test, - parsed_findings, - scan_type, - user, - active=active, - verified=verified, - minimum_severity=minimum_severity, - endpoints_to_add=endpoints_to_add, - push_to_jira=push_to_jira, - group_by=group_by, - now=now, - service=service, - scan_date=scan_date, - sync=True, - do_not_reactivate=do_not_reactivate, - create_finding_groups_for_all_findings=create_finding_groups_for_all_findings, - ) - - closed_findings = [] - if close_old_findings: - logger.debug( - "REIMPORT_SCAN: Closing findings no longer present in scan report" - ) - closed_findings = self.close_old_findings( - test, - findings_to_mitigate, - scan_date, - user=user, - push_to_jira=push_to_jira, - ) - - logger.debug("REIMPORT_SCAN: Updating test/engagement timestamps") - importer_utils.update_timestamps( - test, version, branch_tag, build_id, commit_hash, now, scan_date - ) - - logger.debug("REIMPORT_SCAN: Updating test tags") - importer_utils.update_tags(test, tags) - - test_import = None - if settings.TRACK_IMPORT_HISTORY: - logger.debug("REIMPORT_SCAN: Updating Import History") - test_import = importer_utils.update_import_history( - Test_Import.REIMPORT_TYPE, - active, - verified, - tags, - minimum_severity, - endpoints_to_add, - version, - branch_tag, - build_id, - commit_hash, - push_to_jira, - close_old_findings, - test, - new_findings, - closed_findings, - reactivated_findings, - untouched_findings, - ) - - if apply_tags_to_findings and tags: - for finding in test_import.findings_affected.all(): - for tag in tags: - finding.tags.add(tag) - - if apply_tags_to_endpoints and tags: - for finding in test_import.findings_affected.all(): - for endpoint in finding.endpoints.all(): - for tag in tags: - endpoint.tags.add(tag) - - logger.debug("REIMPORT_SCAN: Generating notifications") - - updated_count = ( - len(closed_findings) + len(reactivated_findings) + len(new_findings) - ) - notifications_helper.notify_scan_added( - test, - updated_count, - new_findings=new_findings, - findings_mitigated=closed_findings, - findings_reactivated=reactivated_findings, - findings_untouched=untouched_findings, - ) - - logger.debug("REIMPORT_SCAN: Done") - - return ( - test, - updated_count, - len(new_findings), - len(closed_findings), - len(reactivated_findings), - len(untouched_findings), - test_import, - ) diff --git a/dojo/importers/reimporter/utils.py b/dojo/importers/reimporter/utils.py deleted file mode 100644 index 4ec9ce1752..0000000000 --- a/dojo/importers/reimporter/utils.py +++ /dev/null @@ -1,263 +0,0 @@ -import logging -from datetime import timedelta - -from crum import get_current_user -from django.conf import settings -from django.utils import timezone - -from dojo.celery import app -from dojo.decorators import dojo_async_task -from dojo.importers import utils as importer_utils -from dojo.models import Engagement, Finding, Product, Product_Member, Product_Type, Product_Type_Member, Q, Role, Test -from dojo.utils import get_last_object_or_none, get_object_or_none - -logger = logging.getLogger(__name__) -deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") - -""" -Common code for reimporting from APIV2 or from the GUI -""" - - -def match_new_finding_to_existing_finding(new_finding, test, deduplication_algorithm): - # This code should match the logic used for deduplication out of the re-import feature. - # See utils.py deduplicate_* functions - deduplicationLogger.debug('return findings bases on algorithm: %s', deduplication_algorithm) - if deduplication_algorithm == 'hash_code': - return Finding.objects.filter( - test=test, - hash_code=new_finding.hash_code).exclude( - hash_code=None).order_by('id') - elif deduplication_algorithm == 'unique_id_from_tool': - return Finding.objects.filter( - test=test, - unique_id_from_tool=new_finding.unique_id_from_tool).exclude( - unique_id_from_tool=None).order_by('id') - elif deduplication_algorithm == 'unique_id_from_tool_or_hash_code': - query = Finding.objects.filter( - Q(test=test), - (Q(hash_code__isnull=False) & Q(hash_code=new_finding.hash_code)) - | (Q(unique_id_from_tool__isnull=False) & Q(unique_id_from_tool=new_finding.unique_id_from_tool))).order_by('id') - deduplicationLogger.debug(query.query) - return query - elif deduplication_algorithm == 'legacy': - # This is the legacy reimport behavior. Although it's pretty flawed and doesn't match the legacy algorithm for deduplication, - # this is left as is for simplicity. - # Re-writing the legacy deduplication here would be complicated and counter-productive. - # If you have use cases going through this section, you're advised to create a deduplication configuration for your parser - logger.debug("Legacy reimport. In case of issue, you're advised to create a deduplication configuration in order not to go through this section") - return Finding.objects.filter( - title=new_finding.title, - test=test, - severity=new_finding.severity, - numerical_severity=Finding.get_numerical_severity(new_finding.severity)).order_by('id') - else: - logger.error("Internal error: unexpected deduplication_algorithm: '%s' ", deduplication_algorithm) - return None - - -def update_endpoint_status(existing_finding, new_finding, user): - # New endpoints are already added in serializers.py / views.py (see comment "# for existing findings: make sure endpoints are present or created") - # So we only need to mitigate endpoints that are no longer present - # using `.all()` will mark as mitigated also `endpoint_status` with flags `false_positive`, `out_of_scope` and `risk_accepted`. This is a known issue. This is not a bug. This is a future. - existing_finding_endpoint_status_list = existing_finding.status_finding.all() - new_finding_endpoints_list = new_finding.unsaved_endpoints - if new_finding.is_mitigated: - # New finding is mitigated, so mitigate all old endpoints - endpoint_status_to_mitigate = existing_finding_endpoint_status_list - else: - # Mitigate any endpoints in the old finding not found in the new finding - endpoint_status_to_mitigate = list( - filter( - lambda existing_finding_endpoint_status: existing_finding_endpoint_status.endpoint not in new_finding_endpoints_list, - existing_finding_endpoint_status_list) - ) - # Re-activate any endpoints in the old finding that are in the new finding - endpoint_status_to_reactivate = list( - filter( - lambda existing_finding_endpoint_status: existing_finding_endpoint_status.endpoint in new_finding_endpoints_list, - existing_finding_endpoint_status_list) - ) - chunk_endpoints_and_reactivate(endpoint_status_to_reactivate) - - # Determine if this can be run async - if settings.ASYNC_FINDING_IMPORT: - chunk_list = importer_utils.chunk_list(endpoint_status_to_mitigate) - # If there is only one chunk, then do not bother with async - if len(chunk_list) < 2: - mitigate_endpoint_status(endpoint_status_to_mitigate, user, kwuser=user, sync=True) - return - # First kick off all the workers - for endpoint_status_list in chunk_list: - mitigate_endpoint_status(endpoint_status_list, user, kwuser=user, sync=False) - else: - mitigate_endpoint_status(endpoint_status_to_mitigate, user, kwuser=user, sync=True) - - -@dojo_async_task -@app.task() -def mitigate_endpoint_status(endpoint_status_list, user, **kwargs): - """ Only mitigate endpoints that are actually active """ - for endpoint_status in endpoint_status_list: - # Only mitigate endpoints that are actually active - if not endpoint_status.mitigated: - logger.debug("Re-import: mitigating endpoint %s that is no longer present", str(endpoint_status.endpoint)) - endpoint_status.mitigated_by = user - endpoint_status.mitigated_time = timezone.now() - endpoint_status.mitigated = True - endpoint_status.last_modified = timezone.now() - endpoint_status.save() - - -def chunk_endpoints_and_reactivate(endpoint_statuses, **kwargs): - # Determine if this can be run async - if settings.ASYNC_FINDING_IMPORT: - chunk_list = importer_utils.chunk_list(endpoint_statuses) - # If there is only one chunk, then do not bother with async - if len(chunk_list) < 2: - reactivate_endpoint_status(endpoint_statuses, sync=True) - logger.debug('IMPORT_SCAN: Split endpoints into ' + str(len(chunk_list)) + ' chunks of ' + str(chunk_list[0])) - # First kick off all the workers - for endpoint_status_list in chunk_list: - reactivate_endpoint_status(endpoint_status_list, sync=False) - else: - reactivate_endpoint_status(endpoint_statuses, sync=True) - - -@dojo_async_task -@app.task() -def reactivate_endpoint_status(endpoint_status_list, **kwargs): - for endpoint_status in endpoint_status_list: - # Only reactivate endpoints that are actually mitigated - if endpoint_status.mitigated: - logger.debug("Re-import: reactivating endpoint %s that is present in this scan", str(endpoint_status.endpoint)) - endpoint_status.mitigated_by = None - endpoint_status.mitigated_time = None - endpoint_status.mitigated = False - endpoint_status.last_modified = timezone.now() - endpoint_status.save() - - -def get_target_product_if_exists(product_name=None, product_type_name=None): - if product_name: - product = get_object_or_none(Product, name=product_name) - if product: - # product type name must match if provided - if product_type_name: - if product.prod_type.name == product_type_name: - return product - else: - return product - - return None - - -def get_target_product_type_if_exists(product_type_name=None): - if product_type_name: - return get_object_or_none(Product_Type, name=product_type_name) - else: - return None - - -def get_target_product_by_id_if_exists(product_id=None): - product = None - if product_id: - product = get_object_or_none(Product, pk=product_id) - logger.debug('Using existing product by id: %s', product_id) - return product - - -def get_target_engagement_if_exists(engagement_id=None, engagement_name=None, product=None): - if engagement_id: - engagement = get_object_or_none(Engagement, pk=engagement_id) - logger.debug('Using existing engagement by id: %s', engagement_id) - return engagement - - if not product: - # if there's no product, then for sure there's no engagement either - return None - - # engagement name is not unique unfortunately - engagement = get_last_object_or_none(Engagement, product=product, name=engagement_name) - return engagement - - -def get_target_test_if_exists(test_id=None, test_title=None, scan_type=None, engagement=None): - """ - Retrieves the target test to reimport. This can be as simple as looking up the test via the `test_id` parameter. - If there is no `test_id` provided, we lookup the latest test inside the provided engagement that satisfies - the provided scan_type and test_title. - """ - if test_id: - test = get_object_or_none(Test, pk=test_id) - logger.debug('Using existing Test by id: %s', test_id) - return test - - if not engagement: - return None - - if test_title: - return get_last_object_or_none(Test, engagement=engagement, title=test_title, scan_type=scan_type) - - return get_last_object_or_none(Test, engagement=engagement, scan_type=scan_type) - - -def get_or_create_product(product_name=None, product_type_name=None, auto_create_context=None): - # try to find the product (withing the provided product_type) - product = get_target_product_if_exists(product_name, product_type_name) - if product: - return product - - # not found .... create it - if not auto_create_context: - msg = 'auto_create_context not True, unable to create non-existing product' - raise ValueError(msg) - else: - product_type, created = Product_Type.objects.get_or_create(name=product_type_name) - if created: - member = Product_Type_Member() - member.user = get_current_user() - member.product_type = product_type - member.role = Role.objects.get(is_owner=True) - member.save() - - product, created = Product.objects.get_or_create(name=product_name, prod_type=product_type, description=product_name) - if created: - member = Product_Member() - member.user = get_current_user() - member.product = product - member.role = Role.objects.get(is_owner=True) - member.save() - - return product - - -def get_or_create_engagement(engagement_id=None, engagement_name=None, product_name=None, product_type_name=None, auto_create_context=None, - deduplication_on_engagement=False, source_code_management_uri=None, target_end=None): - # try to find the engagement (and product) - product = get_target_product_if_exists(product_name, product_type_name) - engagement = get_target_engagement_if_exists(engagement_id, engagement_name, product) - if engagement: - return engagement - - # not found .... create it - if not auto_create_context: - msg = 'auto_create_context not True, unable to create non-existing engagement' - raise ValueError(msg) - else: - product = get_or_create_product(product_name, product_type_name, auto_create_context) - - if not product: - msg = 'no product, unable to create engagement' - raise ValueError(msg) - - target_start = timezone.now().date() - if (target_end is None) or (target_start > target_end): - target_end = (timezone.now() + timedelta(days=365)).date() - - engagement = Engagement.objects.create(engagement_type="CI/CD", name=engagement_name, product=product, lead=get_current_user(), - target_start=target_start, target_end=target_end, status="In Progress", - deduplication_on_engagement=deduplication_on_engagement, - source_code_management_uri=source_code_management_uri) - - return engagement diff --git a/dojo/importers/utils.py b/dojo/importers/utils.py deleted file mode 100644 index 255e2ffa2e..0000000000 --- a/dojo/importers/utils.py +++ /dev/null @@ -1,209 +0,0 @@ -import logging - -from django.conf import settings -from django.core.exceptions import MultipleObjectsReturned, ValidationError -from django.urls import reverse -from django.utils.timezone import make_aware - -from dojo.celery import app -from dojo.decorators import dojo_async_task -from dojo.endpoint.utils import endpoint_get_or_create -from dojo.models import ( - IMPORT_CLOSED_FINDING, - IMPORT_CREATED_FINDING, - IMPORT_REACTIVATED_FINDING, - IMPORT_UNTOUCHED_FINDING, - Endpoint_Status, - Test_Import, - Test_Import_Finding_Action, - Vulnerability_Id, -) -from dojo.utils import max_safe - -logger = logging.getLogger(__name__) - - -def update_timestamps(test, version, branch_tag, build_id, commit_hash, now, scan_date): - if not scan_date: - scan_date = now - - if test.engagement.engagement_type == 'CI/CD': - test.engagement.target_end = max_safe([scan_date.date(), test.engagement.target_end]) - - max_test_start_date = max_safe([scan_date, test.target_end]) - if not max_test_start_date.tzinfo: - max_test_start_date = make_aware(max_test_start_date) - test.target_end = max_test_start_date - - if version: - test.version = version - - if branch_tag: - test.branch_tag = branch_tag - - if build_id: - test.build_id = build_id - - if commit_hash: - test.commit_hash = commit_hash - - test.save() - test.engagement.save() - - -def update_tags(test, tags): - if tags: - test.tags = tags - - test.save() - - -def update_import_history(type, active, verified, tags, minimum_severity, endpoints_to_add, version, branch_tag, - build_id, commit_hash, push_to_jira, close_old_findings, test, - new_findings=[], closed_findings=[], reactivated_findings=[], untouched_findings=[]): - logger.debug("new: %d closed: %d reactivated: %d untouched: %d", len(new_findings), len(closed_findings), len(reactivated_findings), len(untouched_findings)) - # json field - import_settings = {} - import_settings['active'] = active - import_settings['verified'] = verified - import_settings['minimum_severity'] = minimum_severity - import_settings['close_old_findings'] = close_old_findings - import_settings['push_to_jira'] = push_to_jira - import_settings['tags'] = tags - - if endpoints_to_add: - import_settings['endpoints'] = [str(endpoint) for endpoint in endpoints_to_add] - - test_import = Test_Import(test=test, import_settings=import_settings, version=version, branch_tag=branch_tag, build_id=build_id, commit_hash=commit_hash, type=type) - test_import.save() - - test_import_finding_action_list = [] - for finding in closed_findings: - logger.debug('preparing Test_Import_Finding_Action for closed finding: %i', finding.id) - test_import_finding_action_list.append(Test_Import_Finding_Action(test_import=test_import, finding=finding, action=IMPORT_CLOSED_FINDING)) - for finding in new_findings: - logger.debug('preparing Test_Import_Finding_Action for created finding: %i', finding.id) - test_import_finding_action_list.append(Test_Import_Finding_Action(test_import=test_import, finding=finding, action=IMPORT_CREATED_FINDING)) - for finding in reactivated_findings: - logger.debug('preparing Test_Import_Finding_Action for reactivated finding: %i', finding.id) - test_import_finding_action_list.append(Test_Import_Finding_Action(test_import=test_import, finding=finding, action=IMPORT_REACTIVATED_FINDING)) - for finding in untouched_findings: - logger.debug('preparing Test_Import_Finding_Action for untouched finding: %i', finding.id) - test_import_finding_action_list.append(Test_Import_Finding_Action(test_import=test_import, finding=finding, action=IMPORT_UNTOUCHED_FINDING)) - - Test_Import_Finding_Action.objects.bulk_create(test_import_finding_action_list) - - return test_import - - -def construct_imported_message(scan_type, finding_count=0, new_finding_count=0, closed_finding_count=0, reactivated_finding_count=0, untouched_finding_count=0): - if finding_count: - message = f'{scan_type} processed a total of {finding_count} findings' - - if new_finding_count: - message = message + ' created %d findings' % (new_finding_count) - if closed_finding_count: - message = message + ' closed %d findings' % (closed_finding_count) - if reactivated_finding_count: - message = message + ' reactivated %d findings' % (reactivated_finding_count) - if untouched_finding_count: - message = message + ' did not touch %d findings' % (untouched_finding_count) - - message = message + "." - else: - message = 'No findings were added/updated/closed/reactivated as the findings in Defect Dojo are identical to those in the uploaded report.' - - return message - - -def chunk_list(list): - chunk_size = settings.ASYNC_FINDING_IMPORT_CHUNK_SIZE - # Break the list of parsed findings into "chunk_size" lists - chunk_list = [list[i:i + chunk_size] for i in range(0, len(list), chunk_size)] - logger.debug('IMPORT_SCAN: Split endpoints into ' + str(len(chunk_list)) + ' chunks of ' + str(chunk_size)) - return chunk_list - - -def chunk_endpoints_and_disperse(finding, test, endpoints, **kwargs): - if settings.ASYNC_FINDING_IMPORT: - chunked_list = chunk_list(endpoints) - # If there is only one chunk, then do not bother with async - if len(chunked_list) < 2: - add_endpoints_to_unsaved_finding(finding, test, endpoints, sync=True) - return [] - # First kick off all the workers - for endpoints_list in chunked_list: - add_endpoints_to_unsaved_finding(finding, test, endpoints_list, sync=False) - else: - add_endpoints_to_unsaved_finding(finding, test, endpoints, sync=True) - - -# Since adding a model to a ManyToMany relationship does not require an additional -# save, there is no need to keep track of when the task finishes. -@dojo_async_task -@app.task() -def add_endpoints_to_unsaved_finding(finding, test, endpoints, **kwargs): - logger.debug('IMPORT_SCAN: Adding ' + str(len(endpoints)) + ' endpoints to finding:' + str(finding)) - for endpoint in endpoints: - try: - endpoint.clean() - except ValidationError as e: - logger.warning("DefectDojo is storing broken endpoint because cleaning wasn't successful: " - f"{e}") - ep = None - try: - ep, _created = endpoint_get_or_create( - protocol=endpoint.protocol, - userinfo=endpoint.userinfo, - host=endpoint.host, - port=endpoint.port, - path=endpoint.path, - query=endpoint.query, - fragment=endpoint.fragment, - product=test.engagement.product) - except (MultipleObjectsReturned): - msg = "Endpoints in your database are broken. Please access {} and migrate them to new format or " \ - "remove them.".format(reverse('endpoint_migrate')) - raise Exception(msg) - - _eps, _created = Endpoint_Status.objects.get_or_create( - finding=finding, - endpoint=ep, - defaults={'date': finding.date}) - - logger.debug('IMPORT_SCAN: ' + str(len(endpoints)) + ' imported') - - -# This function is added to the async queue at the end of all finding import tasks -# and after endpoint task, so this should only run after all the other ones are done -@dojo_async_task -@app.task() -def update_test_progress(test, **kwargs): - test.percent_complete = 100 - test.save() - - -def handle_vulnerability_ids(finding): - # Synchronize the cve field with the unsaved_vulnerability_ids - # We do this to be as flexible as possible to handle the fields until - # the cve field is not needed anymore and can be removed. - if finding.unsaved_vulnerability_ids and finding.cve: - # Make sure the first entry of the list is the value of the cve field - finding.unsaved_vulnerability_ids.insert(0, finding.cve) - elif finding.unsaved_vulnerability_ids and not finding.cve: - # If the cve field is not set, use the first entry of the list to set it - finding.cve = finding.unsaved_vulnerability_ids[0] - elif not finding.unsaved_vulnerability_ids and finding.cve: - # If there is no list, make one with the value of the cve field - finding.unsaved_vulnerability_ids = [finding.cve] - - if finding.unsaved_vulnerability_ids: - # Remove duplicates - finding.unsaved_vulnerability_ids = list(dict.fromkeys(finding.unsaved_vulnerability_ids)) - - # Add all vulnerability ids to the database - for vulnerability_id in finding.unsaved_vulnerability_ids: - Vulnerability_Id( - vulnerability_id=vulnerability_id, - finding=finding, - ).save() diff --git a/dojo/product/urls.py b/dojo/product/urls.py index 5daa8a2ce4..f2e05a613f 100644 --- a/dojo/product/urls.py +++ b/dojo/product/urls.py @@ -12,8 +12,10 @@ name='view_product_components'), re_path(r'^product/(?P\d+)/engagements$', views.view_engagements, name='view_engagements'), - re_path(r'^product/(?P\d+)/import_scan_results$', - dojo_engagement_views.ImportScanResultsView.as_view(), name='import_scan_results_prod'), + re_path( + r'^product/(?P\d+)/import_scan_results$', + dojo_engagement_views.ImportScanResultsView.as_view(), + name='import_scan_results_prod'), re_path(r'^product/(?P\d+)/metrics$', views.view_product_metrics, name='view_product_metrics'), re_path(r'^product/(?P\d+)/async_burndown_metrics$', views.async_burndown_metrics, diff --git a/dojo/test/urls.py b/dojo/test/urls.py index 7791e1319c..c77aca7690 100644 --- a/dojo/test/urls.py +++ b/dojo/test/urls.py @@ -25,5 +25,8 @@ re_path(r'^test/(?P\d+)/add_findings/(?P\d+)$', views.add_temp_finding, name='add_temp_finding'), re_path(r'^test/(?P\d+)/search$', views.search, name='search'), - re_path(r'^test/(?P\d+)/re_import_scan_results', views.re_import_scan_results, name='re_import_scan_results'), + re_path( + r'^test/(?P\d+)/re_import_scan_results', + views.ReImportScanResultsView.as_view(), + name='re_import_scan_results'), ] diff --git a/dojo/test/views.py b/dojo/test/views.py index d23c4f2164..7eee27829e 100644 --- a/dojo/test/views.py +++ b/dojo/test/views.py @@ -4,8 +4,8 @@ import operator from datetime import datetime from functools import reduce +from typing import Tuple -from django.conf import settings from django.contrib import messages from django.contrib.admin.utils import NestedObjects from django.core.exceptions import ValidationError @@ -41,8 +41,7 @@ TestForm, TypedNoteForm, ) -from dojo.importers.reimporter.reimporter import DojoDefaultReImporter as ReImporter -from dojo.importers.utils import construct_imported_message +from dojo.importers.default_reimporter import DefaultReImporter from dojo.models import ( IMPORT_UNTOUCHED_FINDING, BurpRawRequestResponse, @@ -76,7 +75,6 @@ get_setting, get_system_setting, get_words_for_field, - is_scan_file_too_large, process_notifications, redirect_to_return_url_or_else, ) @@ -337,9 +335,9 @@ def delete_test(request, tid): message, extra_tags='alert-success') create_notification(event='other', - title=_('Deletion of %(title)s') % {"title": test.title}, + title=_(f"Deletion of {test.title}"), product=product, - description=_('The test "%(title)s" was deleted by %(user)s') % {"title": test.title, "user": request.user}, + description=_(f'The test "{test.title}" was deleted by {request.user}'), url=request.build_absolute_uri(reverse('view_engagement', args=(eng.id, ))), recipients=[test.engagement.lead], icon="exclamation-triangle") @@ -440,19 +438,17 @@ def test_ics(request, tid): test = get_object_or_404(Test, id=tid) start_date = datetime.combine(test.target_start, datetime.min.time()) end_date = datetime.combine(test.target_end, datetime.max.time()) - uid = "dojo_test_%d_%d_%d" % (test.id, test.engagement.id, test.engagement.product.id) - cal = get_cal_event(start_date, - end_date, - _("Test: %(test_type_name)s (%(product_name)s)") % { - 'test_type_name': test.test_type.name, - 'product_name': test.engagement.product.name - }, - _("Set aside for test %(test_type_name)s, on product %(product_name)s. Additional detail can be found at %(detail_url)s") % { - 'test_type_name': test.test_type.name, - 'product_name': test.engagement.product.name, - 'detail_url': request.build_absolute_uri(reverse("view_test", args=(test.id,))) - }, - uid) + uid = f"dojo_test_{test.id}_{test.engagement.id}_{test.engagement.product.id}" + cal = get_cal_event( + start_date, + end_date, + _(f"Test: {test.test_type.name} ({test.engagement.product.name}"), + _( + f"Set aside for test {test.test_type.name}, on product {test.engagement.product.name}. " + f"Additional detail can be found at {request.build_absolute_uri(reverse('view_test', args=(test.id,)))}" + ), + uid + ) output = cal.serialize() response = HttpResponse(content=output) response['Content-Type'] = 'text/calendar' @@ -631,11 +627,9 @@ def process_forms(self, request: HttpRequest, test: Test, context: dict): # Create a notification create_notification( event='other', - title=_('Addition of %(title)s') % {'title': finding.title}, + title=_(f'Addition of {finding.title}'), finding=finding, - description=_('Finding "%(title)s" was added by %(user)s') % { - 'title': finding.title, 'user': request.user - }, + description=_(f'Finding "{finding.title}" was added by {request.user}'), url=reverse("view_finding", args=(finding.id,)), icon="exclamation-triangle") # Add a success message @@ -694,7 +688,7 @@ def add_temp_finding(request, tid, fid): form = AddFindingForm(request.POST, req_resp=None, product=test.engagement.product) if jira_helper.get_jira_project(test): jform = JIRAFindingForm(push_all=jira_helper.is_push_all_issues(test), prefix='jiraform', jira_project=jira_helper.get_jira_project(test), finding_form=form) - logger.debug('jform valid: %s', jform.is_valid()) + logger.debug(f'jform valid: {jform.is_valid()}') if (form['active'].value() is False or form['false_p'].value()) and form['duplicate'].value() is False: closing_disabled = Note_Type.objects.filter(is_mandatory=True, is_active=True).count() @@ -779,12 +773,6 @@ def add_temp_finding(request, tid, fid): if jira_helper.get_jira_project(test): jform = JIRAFindingForm(push_all=jira_helper.is_push_all_issues(test), prefix='jiraform', jira_project=jira_helper.get_jira_project(test), finding_form=form) - # logger.debug('form valid: %s', form.is_valid()) - # logger.debug('jform valid: %s', jform.is_valid()) - # logger.debug('form errors: %s', form.errors) - # logger.debug('jform errors: %s', jform.errors) - # logger.debug('jform errors: %s', vars(jform)) - product_tab = Product_Tab(test.engagement.product, title=_("Add Finding"), tab="engagements") product_tab.setEngagement(test.engagement) return render(request, 'dojo/add_findings.html', @@ -818,121 +806,281 @@ def search(request, tid): }) -@user_is_authorized(Test, Permissions.Import_Scan_Result, 'tid') -def re_import_scan_results(request, tid): - additional_message = _("When re-uploading a scan, any findings not found in original scan will be updated as " - "mitigated. The process attempts to identify the differences, however manual verification " - "is highly recommended.") - test = get_object_or_404(Test, id=tid) - # by default we keep a trace of the scan_type used to create the test - # if it's not here, we use the "name" of the test type - # this feature exists to provide custom label for tests for some parsers - if test.scan_type: - scan_type = test.scan_type - else: - scan_type = test.test_type.name - engagement = test.engagement - form = ReImportScanForm(test=test) - jform = None - jira_project = jira_helper.get_jira_project(test) - push_all_jira_issues = jira_helper.is_push_all_issues(test) - - # Decide if we need to present the Push to JIRA form - if get_system_setting('enable_jira') and jira_project: - jform = JIRAImportScanForm(push_all=push_all_jira_issues, prefix='jiraform') - - if request.method == "POST": - form = ReImportScanForm(request.POST, request.FILES, test=test) - if jira_project: - jform = JIRAImportScanForm(request.POST, push_all=push_all_jira_issues, prefix='jiraform') - if form.is_valid() and (jform is None or jform.is_valid()): - scan_date = form.cleaned_data['scan_date'] - - minimum_severity = form.cleaned_data['minimum_severity'] - scan = request.FILES.get('file', None) - activeChoice = form.cleaned_data.get('active', None) - verifiedChoice = form.cleaned_data.get('verified', None) - do_not_reactivate = form.cleaned_data['do_not_reactivate'] - tags = form.cleaned_data['tags'] - version = form.cleaned_data.get('version', None) - branch_tag = form.cleaned_data.get('branch_tag', None) - build_id = form.cleaned_data.get('build_id', None) - commit_hash = form.cleaned_data.get('commit_hash', None) - api_scan_configuration = form.cleaned_data.get('api_scan_configuration', None) - service = form.cleaned_data.get('service', None) - - endpoints_to_add = None # not available on reimport UI - - close_old_findings = form.cleaned_data.get('close_old_findings', True) - - group_by = form.cleaned_data.get('group_by', None) - create_finding_groups_for_all_findings = form.cleaned_data.get('create_finding_groups_for_all_findings') - apply_tags_to_findings = form.cleaned_data.get('apply_tags_to_findings', False) - apply_tags_to_endpoints = form.cleaned_data.get('apply_tags_to_endpoints', False) - - active = None - if activeChoice: - if activeChoice == 'force_to_true': - active = True - elif activeChoice == 'force_to_false': - active = False - verified = None - if verifiedChoice: - if verifiedChoice == 'force_to_true': - verified = True - elif verifiedChoice == 'force_to_false': - verified = False - - # Tags are replaced, same behaviour as with django-tagging - test.tags = tags - test.version = version - if scan and is_scan_file_too_large(scan): - messages.add_message(request, - messages.ERROR, - _("Report file is too large. Maximum supported size is %(size)d MB") % {'size': settings.SCAN_FILE_MAX_SIZE}, - extra_tags='alert-danger') - return HttpResponseRedirect(reverse('re_import_scan_results', args=(test.id,))) - - push_to_jira = push_all_jira_issues or (jform and jform.cleaned_data.get('push_to_jira')) - error = False - finding_count, new_finding_count, closed_finding_count, reactivated_finding_count, untouched_finding_count = 0, 0, 0, 0, 0 - reimporter = ReImporter() - try: - test, finding_count, new_finding_count, closed_finding_count, reactivated_finding_count, untouched_finding_count, _test_import = \ - reimporter.reimport_scan(scan, scan_type, test, active=active, verified=verified, - tags=tags, minimum_severity=minimum_severity, - endpoints_to_add=endpoints_to_add, scan_date=scan_date, - version=version, branch_tag=branch_tag, build_id=build_id, - commit_hash=commit_hash, push_to_jira=push_to_jira, - close_old_findings=close_old_findings, group_by=group_by, - api_scan_configuration=api_scan_configuration, service=service, do_not_reactivate=do_not_reactivate, - create_finding_groups_for_all_findings=create_finding_groups_for_all_findings, - apply_tags_to_findings=apply_tags_to_findings, apply_tags_to_endpoints=apply_tags_to_endpoints) - except Exception as e: - logger.exception(e) - add_error_message_to_response(f'An exception error occurred during the report import:{str(e)}') - error = True - - if not error: - message = construct_imported_message(scan_type, finding_count, new_finding_count=new_finding_count, - closed_finding_count=closed_finding_count, - reactivated_finding_count=reactivated_finding_count, - untouched_finding_count=untouched_finding_count) - add_success_message_to_response(message) +class ReImportScanResultsView(View): + def get_template(self) -> str: + """ + Returns the template that will be presented to the user + """ + return "dojo/import_scan_results.html" + + def get_form( + self, + request: HttpRequest, + test: Test, + **kwargs: dict, + ) -> ReImportScanForm: + """ + Returns the default import form for importing findings + """ + if request.method == "POST": + return ReImportScanForm(request.POST, request.FILES, test=test, **kwargs) + else: + return ReImportScanForm(test=test, **kwargs) + + def get_jira_form( + self, + request: HttpRequest, + test: Test, + ) -> Tuple[JIRAImportScanForm | None, bool]: + """ + Returns a JiraImportScanForm if jira is enabled + """ + jira_form = None + push_all_jira_issues = False + # Decide if we need to present the Push to JIRA form + if get_system_setting('enable_jira'): + # Determine if jira issues should be pushed automatically + push_all_jira_issues = jira_helper.is_push_all_issues(test) + # Only return the form if the jira is enabled on this engagement or product + if jira_helper.get_jira_project(test): + if request.method == "POST": + jira_form = JIRAImportScanForm( + request.POST, + push_all=push_all_jira_issues, + prefix='jiraform' + ) + else: + jira_form = JIRAImportScanForm( + push_all=push_all_jira_issues, + prefix='jiraform' + ) + return jira_form, push_all_jira_issues + + def handle_request( + self, + request: HttpRequest, + test_id: int, + ) -> Tuple[HttpRequest, dict]: + """ + Process the common behaviors between request types, and then return + the request and context dict back to be rendered + """ + # Get the test object + test = get_object_or_404(Test, id=test_id) + # Ensure the supplied user has access to import to the engagement or product + user_has_permission_or_403(request.user, test, Permissions.Import_Scan_Result) + # by default we keep a trace of the scan_type used to create the test + # if it's not here, we use the "name" of the test type + # this feature exists to provide custom label for tests for some parsers + if test.scan_type: + scan_type = test.scan_type + else: + scan_type = test.test_type.name + # Set the product tab + product_tab = Product_Tab(test.engagement.product, title=_(f"Re-upload a {scan_type}"), tab="engagements") + product_tab.setEngagement(test.engagement) + # Get the import form with some initial data in place + form = self.get_form( + request, + test, + endpoints=Endpoint.objects.filter(product__id=product_tab.product.id), + api_scan_configuration=test.api_scan_configuration, + api_scan_configuration_queryset=Product_API_Scan_Configuration.objects.filter(product__id=product_tab.product.id), + ) + # Get the jira form + jira_form, push_all_jira_issues = self.get_jira_form(request, test) + # Return the request and the context + return request, { + "test": test, + "form": form, + "product_tab": product_tab, + "eid": test.engagement.id, + "jform": jira_form, + "scan_type": scan_type, + "scan_types": get_scan_types_sorted(), + "push_all_jira_issues": push_all_jira_issues, + "additional_message": ( + "When re-uploading a scan, any findings not found in original scan will be updated as " + "mitigated. The process attempts to identify the differences, however manual verification " + "is highly recommended." + ), + } - return HttpResponseRedirect(reverse('view_test', args=(test.id,))) + def validate_forms( + self, + context: dict, + ) -> bool: + """ + Validates each of the forms to ensure all errors from the form + level are bubbled up to the user first before we process too much + """ + form_validation_list = [] + if context.get("form") is not None: + form_validation_list.append(context.get("form").is_valid()) + if context.get("jform") is not None: + form_validation_list.append(context.get("jform").is_valid()) + return all(form_validation_list) + + def process_form( + self, + request: HttpRequest, + form: ReImportScanForm, + context: dict, + ) -> str | None: + """ + Process the form and manipulate the input in any way that is appropriate + """ + # Update the running context dict with cleaned form input + context.update({ + "scan": request.FILES.get("file", None), + "scan_date": form.cleaned_data.get("scan_date"), + "minimum_severity": form.cleaned_data.get("minimum_severity"), + "do_not_reactivate": form.cleaned_data.get("do_not_reactivate"), + "tags": form.cleaned_data.get("tags"), + "version": form.cleaned_data.get("version"), + "branch_tag": form.cleaned_data.get("branch_tag", None), + "build_id": form.cleaned_data.get("build_id", None), + "commit_hash": form.cleaned_data.get("commit_hash", None), + "api_scan_configuration": form.cleaned_data.get("api_scan_configuration", None), + "service": form.cleaned_data.get("service", None), + "apply_tags_to_findings": form.cleaned_data.get("apply_tags_to_findings", False), + "apply_tags_to_endpoints": form.cleaned_data.get("apply_tags_to_endpoints", False), + "group_by": form.cleaned_data.get("group_by", None), + "close_old_findings": form.cleaned_data.get("close_old_findings", None), + "create_finding_groups_for_all_findings": form.cleaned_data.get("create_finding_groups_for_all_findings"), + }) + # Override the form values of active and verified + if activeChoice := form.cleaned_data.get('active', None): + if activeChoice == 'force_to_true': + context["active"] = True + elif activeChoice == 'force_to_false': + context["active"] = False + if verifiedChoice := form.cleaned_data.get('verified', None): + if verifiedChoice == 'force_to_true': + context["verified"] = True + elif verifiedChoice == 'force_to_false': + context["verified"] = False + # Override the tags and version + context.get("test").tags = context.get("tags") + context.get("test").version = context.get("version") + return None - product_tab = Product_Tab(engagement.product, title=_("Re-upload a %(scan_type)s") % {"scan_type": scan_type}, tab="engagements") - product_tab.setEngagement(engagement) - form.fields['endpoints'].queryset = Endpoint.objects.filter(product__id=product_tab.product.id) - form.initial['api_scan_configuration'] = test.api_scan_configuration - form.fields['api_scan_configuration'].queryset = Product_API_Scan_Configuration.objects.filter(product__id=product_tab.product.id) - return render(request, - 'dojo/import_scan_results.html', - {'form': form, - 'product_tab': product_tab, - 'eid': engagement.id, - 'additional_message': additional_message, - 'jform': jform, - 'scan_types': get_scan_types_sorted(), - }) + def process_jira_form( + self, + request: HttpRequest, + form: JIRAImportScanForm, + context: dict, + ) -> str | None: + """ + Process the jira form by first making sure one was supplied + and then setting any values supplied by the user. An error + may be returned and will be bubbled up in the form of a message + """ + # Determine if push all issues is enabled + push_all_jira_issues = context.get("push_all_jira_issues", False) + context["push_to_jira"] = push_all_jira_issues or (form and form.cleaned_data.get("push_to_jira")) + return None + + def reimport_findings( + self, + context: dict, + ) -> str | None: + """ + Attempt to import with all the supplied information + """ + try: + importer_client = DefaultReImporter() + ( + context["test"], + finding_count, + new_finding_count, + closed_finding_count, + reactivated_finding_count, + untouched_finding_count, + _, + ) = importer_client.process_scan( + **context, + ) + # Add a message to the view for the user to see the results + add_success_message_to_response(importer_client.construct_imported_message( + context.get("scan_type"), + Test_Import.REIMPORT_TYPE, + finding_count=finding_count, + new_finding_count=new_finding_count, + closed_finding_count=closed_finding_count, + reactivated_finding_count=reactivated_finding_count, + untouched_finding_count=untouched_finding_count, + close_old_findings=context.get("close_old_findings"), + )) + except Exception as e: + logger.exception(e) + return f"An exception error occurred during the report import: {e}" + return None + + def success_redirect( + self, + context: dict, + ) -> HttpResponseRedirect: + """ + Redirect the user to a place that indicates a successful import + """ + return HttpResponseRedirect(reverse("view_test", args=(context.get("test").id, ))) + + def failure_redirect( + self, + context: dict, + ) -> HttpResponseRedirect: + """ + Redirect the user to a place that indicates a failed import + """ + return HttpResponseRedirect(reverse( + "re_import_scan_results", + args=(context.get("test").id, ), + )) + + def get( + self, + request: HttpRequest, + test_id: int, + ) -> HttpResponse: + """ + Process GET requests for the ReImport View + """ + # process the request and path parameters + request, context = self.handle_request( + request, + test_id=test_id, + ) + # Render the form + return render(request, self.get_template(), context) + + def post( + self, + request: HttpRequest, + test_id: int, + ) -> HttpResponse: + """ + Process POST requests for the ReImport View + """ + # process the request and path parameters + request, context = self.handle_request( + request, + test_id=test_id, + ) + # ensure all three forms are valid first before moving forward + if not self.validate_forms(context): + return self.failure_redirect(context) + # Process the jira form if it is present + if form_error := self.process_jira_form(request, context.get("jform"), context): + add_error_message_to_response(form_error) + return self.failure_redirect(context) + # Process the import form + if form_error := self.process_form(request, context.get("form"), context): + add_error_message_to_response(form_error) + return self.failure_redirect(context) + # Kick off the import process + if import_error := self.reimport_findings(context): + add_error_message_to_response(import_error) + return self.failure_redirect(context) + # Otherwise return the user back to the engagement (if present) or the product + return self.success_redirect(context) diff --git a/unittests/test_importers_closeold.py b/unittests/test_importers_closeold.py index 1b16cde9ba..fb9d46ce5d 100644 --- a/unittests/test_importers_closeold.py +++ b/unittests/test_importers_closeold.py @@ -2,7 +2,7 @@ from django.utils import timezone -from dojo.importers.importer.importer import DojoDefaultImporter as Importer +from dojo.importers.default_importer import DefaultImporter from dojo.models import Development_Environment, Engagement, Product, Product_Type, User from .dojo_test_case import DojoTestCase, get_unit_tests_path @@ -12,66 +12,62 @@ class TestDojoCloseOld(DojoTestCase): def test_close_old_same_engagement(self): - scan = get_unit_tests_path() + "/scans/acunetix/many_findings.xml" + importer = DefaultImporter() scan_type = "Acunetix Scan" - user, _ = User.objects.get_or_create(username="admin") - _user_reporter, _ = User.objects.get_or_create(username="user_reporter") - product_type, _ = Product_Type.objects.get_or_create(name="closeold") + environment, _ = Development_Environment.objects.get_or_create(name="Development") product, _ = Product.objects.get_or_create( name="TestDojoCloseOldImporter1", prod_type=product_type, ) - engagement, _ = Engagement.objects.get_or_create( name="Close Old Same Engagement", product=product, target_start=timezone.now(), target_end=timezone.now(), ) - importer = Importer() - scan_date = None - environment, _ = Development_Environment.objects.get_or_create(name="Development") + import_options = { + "user": user, + "lead": user, + "scan_date": None, + "environment": environment, + "active": True, + "verified": False, + } # Import first test - _test, len_new_findings, len_closed_findings, _ = importer.import_scan(scan, scan_type, engagement, lead=None, environment=environment, - active=True, verified=False, tags=None, minimum_severity=None, - user=user, endpoints_to_add=None, scan_date=scan_date, version=None, branch_tag=None, build_id=None, - commit_hash=None, push_to_jira=None, close_old_findings=False, group_by=None, api_scan_configuration=None) - - self.assertEqual(4, len_new_findings) - self.assertEqual(0, len_closed_findings) + with open(f"{get_unit_tests_path()}/scans/acunetix/many_findings.xml", "r+") as many_findings_scan: + _, _, len_new_findings, len_closed_findings, _, _, _ = importer.process_scan( + many_findings_scan, scan_type, engagement, close_old_findings=False, **import_options, + ) + self.assertEqual(4, len_new_findings) + self.assertEqual(0, len_closed_findings) # Import same test, should close no findings - _test, len_new_findings, len_closed_findings, _ = importer.import_scan(scan, scan_type, engagement, lead=None, environment=environment, - active=True, verified=False, tags=None, minimum_severity=None, - user=user, endpoints_to_add=None, scan_date=scan_date, version=None, branch_tag=None, build_id=None, - commit_hash=None, push_to_jira=None, close_old_findings=True, group_by=None, api_scan_configuration=None) - self.assertEqual(4, len_new_findings) - self.assertEqual(0, len_closed_findings) + with open(f"{get_unit_tests_path()}/scans/acunetix/many_findings.xml", "r+") as many_findings_scan: + _, _, len_new_findings, len_closed_findings, _, _, _ = importer.process_scan( + many_findings_scan, scan_type, engagement, close_old_findings=True, **import_options, + ) + self.assertEqual(4, len_new_findings) + self.assertEqual(0, len_closed_findings) # Import test with only one finding. Remaining findings should close - with open(get_unit_tests_path() + "/scans/acunetix/one_finding.xml") as scan: - _test, len_new_findings, len_closed_findings, _ = importer.import_scan(scan, scan_type, engagement, lead=None, environment=environment, - active=True, verified=False, tags=None, minimum_severity=None, - user=user, endpoints_to_add=None, scan_date=scan_date, version=None, branch_tag=None, build_id=None, - commit_hash=None, push_to_jira=None, close_old_findings=True, group_by=None, api_scan_configuration=None) + with open(f"{get_unit_tests_path()}/scans/acunetix/one_finding.xml", "r+") as single_finding_scan: + _, _, len_new_findings, len_closed_findings, _, _, _ = importer.process_scan( + single_finding_scan, scan_type, engagement, close_old_findings=True, **import_options, + ) self.assertEqual(1, len_new_findings) # Dedupe is off and close old findings does not close old findings if they are the same finding. - # If this behaviour changes, or dedupe is on, the number of closed findings will be 4 + # If this behavior changes, or dedupe is on, the number of closed findings will be 4 self.assertEqual(8, len_closed_findings) def test_close_old_same_product_scan(self): - scan = get_unit_tests_path() + "/scans/acunetix/many_findings.xml" + importer = DefaultImporter() scan_type = "Acunetix Scan" - user, _ = User.objects.get_or_create(username="admin") - _user_reporter, _ = User.objects.get_or_create(username="user_reporter") - product_type, _ = Product_Type.objects.get_or_create(name="test2") product, _ = Product.objects.get_or_create( name="TestDojoCloseOldImporter2", prod_type=product_type, ) - engagement1, _ = Engagement.objects.get_or_create( name="Close Old Same Product 1", product=product, @@ -90,31 +86,36 @@ def test_close_old_same_product_scan(self): target_start=timezone.now(), target_end=timezone.now(), ) - importer = Importer() - scan_date = None environment, _ = Development_Environment.objects.get_or_create(name="Development") + import_options = { + "user": user, + "lead": user, + "scan_date": None, + "environment": environment, + "active": True, + "verified": False, + "close_old_findings_product_scope": True, + } # Import first test - _test, len_new_findings, len_closed_findings, _ = importer.import_scan(scan, scan_type, engagement1, lead=None, environment=environment, - active=True, verified=False, tags=None, minimum_severity=None, - user=user, endpoints_to_add=None, scan_date=scan_date, version=None, branch_tag=None, build_id=None, - commit_hash=None, push_to_jira=None, close_old_findings=False, close_old_findings_product_scope=True, group_by=None, api_scan_configuration=None) - - self.assertEqual(4, len_new_findings) - self.assertEqual(0, len_closed_findings) + with open(f"{get_unit_tests_path()}/scans/acunetix/many_findings.xml", "r+") as many_findings_scan: + _, _, len_new_findings, len_closed_findings, _, _, _ = importer.process_scan( + many_findings_scan, scan_type, engagement1, close_old_findings=False, **import_options, + ) + self.assertEqual(4, len_new_findings) + self.assertEqual(0, len_closed_findings) # Import same test, should close no findings - _test, len_new_findings, len_closed_findings, _ = importer.import_scan(scan, scan_type, engagement2, lead=None, environment=environment, - active=True, verified=False, tags=None, minimum_severity=None, - user=user, endpoints_to_add=None, scan_date=scan_date, version=None, branch_tag=None, build_id=None, - commit_hash=None, push_to_jira=None, close_old_findings=True, close_old_findings_product_scope=True, group_by=None, api_scan_configuration=None) - self.assertEqual(4, len_new_findings) - self.assertEqual(0, len_closed_findings) + with open(f"{get_unit_tests_path()}/scans/acunetix/many_findings.xml", "r+") as many_findings_scan: + _, _, len_new_findings, len_closed_findings, _, _, _ = importer.process_scan( + many_findings_scan, scan_type, engagement2, close_old_findings=True, **import_options, + ) + self.assertEqual(4, len_new_findings) + self.assertEqual(0, len_closed_findings) # Import test with only one finding. Remaining findings should close - with open(get_unit_tests_path() + "/scans/acunetix/one_finding.xml") as scan: - _test, len_new_findings, len_closed_findings, _ = importer.import_scan(scan, scan_type, engagement3, lead=None, environment=environment, - active=True, verified=False, tags=None, minimum_severity=None, - user=user, endpoints_to_add=None, scan_date=scan_date, version=None, branch_tag=None, build_id=None, - commit_hash=None, push_to_jira=None, close_old_findings=True, close_old_findings_product_scope=True, group_by=None, api_scan_configuration=None) + with open(f"{get_unit_tests_path()}/scans/acunetix/one_finding.xml", "r+") as single_finding_scan: + _, _, len_new_findings, len_closed_findings, _, _, _ = importer.process_scan( + single_finding_scan, scan_type, engagement3, close_old_findings=True, **import_options, + ) self.assertEqual(1, len_new_findings) # Dedupe is off, and close old findings does not close old findings if they are the same finding. - # If this behaviour changes, or dedupe is on, the number of closed findings will be 4 + # If this behavior changes, or dedupe is on, the number of closed findings will be 4 self.assertEqual(8, len_closed_findings) diff --git a/unittests/test_importers_importer.py b/unittests/test_importers_importer.py index 5a41fc927d..40caea86f9 100644 --- a/unittests/test_importers_importer.py +++ b/unittests/test_importers_importer.py @@ -6,10 +6,8 @@ from rest_framework.authtoken.models import Token from rest_framework.test import APIClient -from dojo.importers.importer.importer import DojoDefaultImporter as Importer -from dojo.importers.utils import handle_vulnerability_ids +from dojo.importers.default_importer import DefaultImporter from dojo.models import Development_Environment, Engagement, Finding, Product, Product_Type, Test, User -from dojo.tools.factory import get_parser from dojo.tools.gitlab_sast.parser import GitlabSastParser from dojo.tools.sarif.parser import SarifParser from dojo.utils import get_object_or_none @@ -41,118 +39,111 @@ class TestDojoDefaultImporter(DojoTestCase): def test_parse_findings(self): - scan_type = "Acunetix Scan" with open(get_unit_tests_path() + "/scans/acunetix/one_finding.xml") as scan: - + importer = DefaultImporter() + scan_type = "Acunetix Scan" user, _created = User.objects.get_or_create(username="admin") - product_type, _created = Product_Type.objects.get_or_create(name="test") product, _created = Product.objects.get_or_create( name="TestDojoDefaultImporter", prod_type=product_type, ) - - engagement_name = "Test Create Engagement" engagement, _created = Engagement.objects.get_or_create( - name=engagement_name, + name="Test Create Engagement", product=product, target_start=timezone.now(), target_end=timezone.now(), ) lead, _ = User.objects.get_or_create(username="admin") environment, _ = Development_Environment.objects.get_or_create(name="Development") - - # boot - importer = Importer() - + import_options = { + "user": user, + "lead": lead, + "scan_date": None, + "environment": environment, + "minimum_severity": "Info", + "active": True, + "verified": True, + "sync": True, + } # create the test - # by defaut test_type == scan_type - test = importer.create_test(scan_type, scan_type, engagement, lead, environment) - + # by default test_type == scan_type + test = importer.create_test(scan_type, scan_type, engagement=engagement, **import_options) # parse the findings - parser = get_parser(scan_type) + parser = importer.get_parser(scan_type) parsed_findings = parser.get_findings(scan, test) - # process - minimum_severity = "Info" - active = True - verified = True - scan_date = None - new_findings = importer.process_parsed_findings( + new_findings = importer.process_findings( test, parsed_findings, - scan_type, - user, - active, - verified, - minimum_severity=minimum_severity, - scan_date=scan_date, - sync=True + **import_options, ) - for finding in new_findings: self.assertIn(finding.numerical_severity, ["S0", "S1", "S2", "S3", "S4"]) def test_import_scan(self): with open(get_unit_tests_path() + "/scans/sarif/spotbugs.sarif") as scan: + importer = DefaultImporter() scan_type = SarifParser().get_scan_types()[0] # SARIF format implement the new method - user, _ = User.objects.get_or_create(username="admin") - _user_reporter, _ = User.objects.get_or_create(username="user_reporter") - product_type, _ = Product_Type.objects.get_or_create(name="test2") product, _ = Product.objects.get_or_create( name="TestDojoDefaultImporter2", prod_type=product_type, ) - engagement, _ = Engagement.objects.get_or_create( name="Test Create Engagement2", product=product, target_start=timezone.now(), target_end=timezone.now(), ) - importer = Importer() - scan_date = None environment, _ = Development_Environment.objects.get_or_create(name="Development") - test, len_new_findings, len_closed_findings, _ = importer.import_scan(scan, scan_type, engagement, lead=None, environment=environment, - active=True, verified=True, tags=None, minimum_severity=None, - user=user, endpoints_to_add=None, scan_date=scan_date, version=None, branch_tag=None, build_id=None, - commit_hash=None, push_to_jira=None, close_old_findings=False, group_by=None, api_scan_configuration=None) - + import_options = { + "user": user, + "lead": user, + "scan_date": None, + "environment": environment, + "minimum_severity": "Info", + "active": True, + "verified": True, + } + test, _, len_new_findings, len_closed_findings, _, _, _ = importer.process_scan( + scan, scan_type, engagement, close_old_findings=False, **import_options, + ) self.assertEqual(f"SpotBugs Scan ({scan_type})", test.test_type.name) self.assertEqual(56, len_new_findings) self.assertEqual(0, len_closed_findings) def test_import_scan_without_test_scan_type(self): - # GitLabSastParser implements get_tests but report has no scanner name with open(f"{get_unit_tests_path()}/scans/gitlab_sast/gl-sast-report-1-vuln_v15.json") as scan: + importer = DefaultImporter() + # GitLabSastParser implements get_tests but report has no scanner name scan_type = GitlabSastParser().get_scan_types()[0] - user, _ = User.objects.get_or_create(username="admin") - _user_reporter, _ = User.objects.get_or_create(username="user_reporter") - product_type, _ = Product_Type.objects.get_or_create(name="test2") product, _ = Product.objects.get_or_create( name="TestDojoDefaultImporter2", prod_type=product_type, ) - engagement, _ = Engagement.objects.get_or_create( name="Test Create Engagement2", product=product, target_start=timezone.now(), target_end=timezone.now(), ) - - importer = Importer() - scan_date = None environment, _ = Development_Environment.objects.get_or_create(name="Development") - test, len_new_findings, len_closed_findings, _ = importer.import_scan(scan, scan_type, engagement, lead=None, environment=environment, - active=True, verified=True, tags=None, minimum_severity=None, - user=user, endpoints_to_add=None, scan_date=scan_date, version=None, branch_tag=None, build_id=None, - commit_hash=None, push_to_jira=None, close_old_findings=False, group_by=None, api_scan_configuration=None) - + import_options = { + "user": user, + "lead": user, + "scan_date": None, + "environment": environment, + "minimum_severity": "Info", + "active": True, + "verified": True, + } + test, _, len_new_findings, len_closed_findings, _, _, _ = importer.process_scan( + scan, scan_type, engagement, close_old_findings=False, **import_options, + ) self.assertEqual("GitLab SAST Report", test.test_type.name) self.assertEqual(1, len_new_findings) self.assertEqual(0, len_closed_findings) @@ -185,18 +176,15 @@ def create_default_data(self): # engagement name is not unique by itself and not unique inside a product self.engagement_last = self.create_engagement(ENGAGEMENT_NAME_DEFAULT, product=self.product) - @patch('dojo.jira_link.helper.get_jira_project') - def test_import_by_engagement_id(self, mock): + def test_import_by_engagement_id(self): with assertImportModelsCreated(self, tests=1, engagements=0, products=0, product_types=0, endpoints=0): import0 = self.import_scan_with_params(NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, engagement=self.engagement.id, test_title=TEST_TITLE_DEFAULT) test_id = import0['test'] self.assertEqual(get_object_or_none(Test, id=test_id).title, TEST_TITLE_DEFAULT) self.assertEqual(import0['engagement_id'], self.engagement.id) self.assertEqual(import0['product_id'], self.engagement.product.id) - mock.assert_called_with(self.engagement) - @patch('dojo.jira_link.helper.get_jira_project') - def test_import_by_product_name_exists_engagement_name_exists(self, mock): + def test_import_by_product_name_exists_engagement_name_exists(self): with assertImportModelsCreated(self, tests=1, engagements=0, products=0, product_types=0, endpoints=0): import0 = self.import_scan_with_params(NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, product_name=PRODUCT_NAME_DEFAULT, engagement=None, engagement_name=ENGAGEMENT_NAME_DEFAULT) @@ -204,16 +192,13 @@ def test_import_by_product_name_exists_engagement_name_exists(self, mock): self.assertEqual(Test.objects.get(id=test_id).engagement, self.engagement_last) self.assertEqual(import0['engagement_id'], self.engagement_last.id) self.assertEqual(import0['product_id'], self.engagement_last.product.id) - mock.assert_called_with(self.engagement_last) def test_import_by_product_name_exists_engagement_name_not_exists(self): with assertImportModelsCreated(self, tests=0, engagements=0, products=0, product_types=0, endpoints=0): self.import_scan_with_params(NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, product_name=PRODUCT_NAME_DEFAULT, engagement=None, engagement_name=ENGAGEMENT_NAME_NEW, expected_http_status_code=400) - @patch('dojo.jira_link.helper.get_jira_project') - def test_import_by_product_name_exists_engagement_name_not_exists_auto_create(self, mock): - mock.return_value = None + def test_import_by_product_name_exists_engagement_name_not_exists_auto_create(self): with assertImportModelsCreated(self, tests=1, engagements=1, products=0, product_types=0, endpoints=0): import0 = self.import_scan_with_params(NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, product_name=PRODUCT_NAME_DEFAULT, engagement=None, engagement_name=ENGAGEMENT_NAME_NEW, auto_create_context=True) @@ -221,9 +206,6 @@ def test_import_by_product_name_exists_engagement_name_not_exists_auto_create(se self.assertEqual(get_object_or_none(Test, id=test_id).title, None) self.assertEqual(get_object_or_none(Engagement, id=import0['engagement_id']).name, ENGAGEMENT_NAME_NEW) self.assertEqual(import0['product_id'], self.engagement.product.id) - # the new engagement should inherit the jira settings from the product - # the jira settings are retrieved before an engagement is auto created - mock.assert_called_with(self.product) def test_import_by_product_name_not_exists_engagement_name(self): with assertImportModelsCreated(self, tests=0, engagements=0, products=0, product_types=0, endpoints=0): @@ -289,7 +271,7 @@ def test_import_with_invalid_parameters(self): with self.subTest('invalid product type'): import0 = self.import_scan_with_params(NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, engagement=None, product_type_name='valentijn', product_name='67283', engagement_name='valentijn', expected_http_status_code=400) - self.assertEqual(import0, ["Product Type 'valentijn' doesn't exist"]) + self.assertEqual(import0, ['Product Type "valentijn" does not exist']) with self.subTest('invalid product'): # random product type to avoid collision with other tests @@ -297,12 +279,16 @@ def test_import_with_invalid_parameters(self): Product_Type.objects.create(name=another_product_type_name) import0 = self.import_scan_with_params(NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, engagement=None, product_type_name=another_product_type_name, product_name=PRODUCT_NAME_DEFAULT, engagement_name='valentijn', expected_http_status_code=400) - self.assertEqual(import0, [f"Product '{PRODUCT_NAME_DEFAULT}' doesn't exist in Product_Type '{another_product_type_name}'"]) + self.assertEqual(import0, [( + "The fetched product has a conflict with the supplied product type name: " + f"existing product type name - {PRODUCT_TYPE_NAME_DEFAULT} vs " + f"supplied product type name - {another_product_type_name}" + )]) with self.subTest('invalid engagement'): import0 = self.import_scan_with_params(NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, engagement=1254235, expected_http_status_code=400) - self.assertEqual(import0, ["Engagement '1254235' doesn't exist"]) + self.assertEqual(import0, ['Engagement "1254235" does not exist']) with self.subTest('invalid engagement, but exists in another product'): # random product to avoid collision with other tests @@ -310,7 +296,7 @@ def test_import_with_invalid_parameters(self): self.product = self.create_product(another_product_name) import0 = self.import_scan_with_params(NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, engagement=None, engagement_name=ENGAGEMENT_NAME_DEFAULT, product_name=another_product_name, expected_http_status_code=400) - self.assertEqual(import0, [f"Engagement 'Engagement 1' doesn't exist in Product '{another_product_name}'"]) + self.assertEqual(import0, [f'Engagement "Engagement 1" does not exist in Product "{another_product_name}"']) with self.subTest('invalid engagement not id'): import0 = self.import_scan_with_params(NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, @@ -320,7 +306,7 @@ def test_import_with_invalid_parameters(self): with self.subTest('autocreate product but no product type name'): import0 = self.import_scan_with_params(NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, product_name=PRODUCT_NAME_NEW, engagement=None, engagement_name=ENGAGEMENT_NAME_NEW, auto_create_context=True, expected_http_status_code=400) - self.assertEqual(import0, [f"Product '{PRODUCT_NAME_NEW}' doesn't exist and no product_type_name provided to create the new product in"]) + self.assertEqual(import0, [f'Product "{PRODUCT_NAME_NEW}" does not exist and no product_type_name provided to create the new product in']) with self.subTest('autocreate engagement but no product_name'): import0 = self.import_scan_with_params(NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, product_name=None, @@ -382,23 +368,20 @@ def test_reimport_by_product_name_exists_engagement_name_exists_scan_type_not_ex self.reimport_scan_with_params(None, NPM_AUDIT_NO_VULN_FILENAME, scan_type='Acunetix Scan', product_name=PRODUCT_NAME_DEFAULT, engagement=None, engagement_name=ENGAGEMENT_NAME_DEFAULT, test_title=TEST_TITLE_DEFAULT, expected_http_status_code=400) - @patch('dojo.jira_link.helper.get_jira_project') - def test_reimport_by_product_name_exists_engagement_name_exists_scan_type_not_exsists_test_title_exists_auto_create(self, mock): + def test_reimport_by_product_name_exists_engagement_name_exists_scan_type_not_exsists_test_title_exists_auto_create(self): with assertImportModelsCreated(self, tests=1, engagements=0, products=0, product_types=0, endpoints=1): import0 = self.reimport_scan_with_params(None, ACUNETIX_AUDIT_ONE_VULN_FILENAME, scan_type='Acunetix Scan', product_name=PRODUCT_NAME_DEFAULT, engagement=None, engagement_name=ENGAGEMENT_NAME_DEFAULT, test_title=TEST_TITLE_DEFAULT, auto_create_context=True) test_id = import0['test'] self.assertEqual(get_object_or_none(Test, id=test_id).title, TEST_TITLE_DEFAULT) self.assertEqual(import0['engagement_id'], self.engagement.id) - mock.assert_called_with(self.engagement) def test_reimport_by_product_name_exists_engagement_name_exists_scan_type_not_exsists_test_title_not_exists(self): with assertImportModelsCreated(self, tests=0, engagements=0, products=0, product_types=0, endpoints=0): self.reimport_scan_with_params(None, NPM_AUDIT_NO_VULN_FILENAME, scan_type='Acunetix Scan', product_name=PRODUCT_NAME_DEFAULT, engagement=None, engagement_name=ENGAGEMENT_NAME_DEFAULT, test_title='bogus title', expected_http_status_code=400) - @patch('dojo.jira_link.helper.get_jira_project') - def test_reimport_by_product_name_exists_engagement_name_exists_scan_type_not_exsists_test_title_not_exists_auto_create(self, mock): + def test_reimport_by_product_name_exists_engagement_name_exists_scan_type_not_exsists_test_title_not_exists_auto_create(self): with assertImportModelsCreated(self, tests=1, engagements=0, products=0, product_types=0, endpoints=1): import0 = self.reimport_scan_with_params(None, ACUNETIX_AUDIT_ONE_VULN_FILENAME, scan_type='Acunetix Scan', product_name=PRODUCT_NAME_DEFAULT, engagement=None, engagement_name=ENGAGEMENT_NAME_DEFAULT, test_title='bogus title', auto_create_context=True) @@ -406,9 +389,6 @@ def test_reimport_by_product_name_exists_engagement_name_exists_scan_type_not_ex self.assertEqual(get_object_or_none(Test, id=test_id).scan_type, 'Acunetix Scan') self.assertEqual(get_object_or_none(Test, id=test_id).title, 'bogus title') self.assertEqual(import0['engagement_id'], self.engagement.id) - # the new test should inherit the jira settings from the engagement - # the jira settings are retrieved before an test is auto created - mock.assert_called_with(self.engagement) def test_reimport_by_product_name_exists_engagement_name_exists_test_title_exists(self): with assertImportModelsCreated(self, tests=0, engagements=0, products=0, product_types=0, endpoints=0): @@ -422,8 +402,7 @@ def test_reimport_by_product_name_exists_engagement_name_not_exists(self): self.reimport_scan_with_params(None, NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, product_name=PRODUCT_NAME_DEFAULT, engagement=None, engagement_name=ENGAGEMENT_NAME_NEW, expected_http_status_code=400) - @patch('dojo.jira_link.helper.get_jira_project') - def test_reimport_by_product_name_exists_engagement_name_not_exists_auto_create(self, mock): + def test_reimport_by_product_name_exists_engagement_name_not_exists_auto_create(self): with assertImportModelsCreated(self, tests=1, engagements=1, products=0, product_types=0, endpoints=0): import0 = self.reimport_scan_with_params(None, NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, product_name=PRODUCT_NAME_DEFAULT, engagement=None, engagement_name=ENGAGEMENT_NAME_NEW, auto_create_context=True) @@ -432,9 +411,6 @@ def test_reimport_by_product_name_exists_engagement_name_not_exists_auto_create( self.assertEqual(get_object_or_none(Engagement, id=import0['engagement_id']).name, ENGAGEMENT_NAME_NEW) self.assertEqual(import0['product_id'], self.engagement.product.id) self.assertEqual(import0['product_type_id'], self.engagement.product.prod_type.id) - # the new engagement should inherit the jira settings from the product - # the jira settings are retrieved before an engagement is auto created - mock.assert_called_with(self.product) def test_reimport_by_product_name_not_exists_engagement_name(self): with assertImportModelsCreated(self, tests=0, engagements=0, products=0, product_types=0, endpoints=0): @@ -491,12 +467,12 @@ def test_reimport_with_invalid_parameters(self): with self.subTest('invalid product type'): import0 = self.reimport_scan_with_params(None, NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, engagement=None, product_type_name='valentijn', product_name='67283', engagement_name='valentijn', expected_http_status_code=400) - self.assertEqual(import0, ["Product Type 'valentijn' doesn't exist"]) + self.assertEqual(import0, ['Product Type "valentijn" does not exist']) with self.subTest('invalid product'): import0 = self.reimport_scan_with_params(None, NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, engagement=None, product_name='67283', engagement_name='valentijn', expected_http_status_code=400) - self.assertEqual(import0, ["Product '67283' doesn't exist"]) + self.assertEqual(import0, ['Product "67283" does not exist']) with self.subTest('valid product, but other product type'): # random product type to avoid collision with other tests @@ -505,7 +481,11 @@ def test_reimport_with_invalid_parameters(self): import0 = self.reimport_scan_with_params(None, NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, engagement=None, product_type_name=another_product_type_name, product_name=PRODUCT_NAME_DEFAULT, engagement_name='valentijn', expected_http_status_code=400) - self.assertEqual(import0, [f"Product '{PRODUCT_NAME_DEFAULT}' doesn't exist in Product_Type '{another_product_type_name}'"]) + self.assertEqual(import0, [( + "The fetched product has a conflict with the supplied product type name: " + f"existing product type name - {PRODUCT_TYPE_NAME_DEFAULT} vs " + f"supplied product type name - {another_product_type_name}" + )]) with self.subTest('invalid engagement'): import0 = self.reimport_scan_with_params(None, NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, @@ -518,7 +498,7 @@ def test_reimport_with_invalid_parameters(self): self.product = self.create_product(another_product_name) import0 = self.reimport_scan_with_params(None, NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, engagement_name=ENGAGEMENT_NAME_DEFAULT, product_name=another_product_name, expected_http_status_code=400) - self.assertEqual(import0, [f"Engagement 'Engagement 1' doesn't exist in Product '{another_product_name}'"]) + self.assertEqual(import0, [f'Engagement "Engagement 1" does not exist in Product "{another_product_name}"']) with self.subTest('invalid engagement not id'): import0 = self.reimport_scan_with_params(None, NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, @@ -528,7 +508,7 @@ def test_reimport_with_invalid_parameters(self): with self.subTest('autocreate product but no product type name'): import0 = self.reimport_scan_with_params(None, NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, product_name=PRODUCT_NAME_NEW, engagement=None, engagement_name=ENGAGEMENT_NAME_NEW, auto_create_context=True, expected_http_status_code=400) - self.assertEqual(import0, [f"Product '{PRODUCT_NAME_NEW}' doesn't exist and no product_type_name provided to create the new product in"]) + self.assertEqual(import0, [f'Product "{PRODUCT_NAME_NEW}" does not exist and no product_type_name provided to create the new product in']) with self.subTest('autocreate engagement but no product_name'): import0 = self.reimport_scan_with_params(None, NPM_AUDIT_NO_VULN_FILENAME, scan_type=NPM_AUDIT_SCAN_TYPE, @@ -537,13 +517,13 @@ def test_reimport_with_invalid_parameters(self): class TestImporterUtils(DojoAPITestCase): - @patch('dojo.importers.utils.Vulnerability_Id', autospec=True) + @patch('dojo.importers.base_importer.Vulnerability_Id', autospec=True) def test_handle_vulnerability_ids_references_and_cve(self, mock): finding = Finding() finding.cve = 'CVE' finding.unsaved_vulnerability_ids = ['REF-1', 'REF-2'] - handle_vulnerability_ids(finding) + DefaultImporter().process_vulnerability_ids(finding) vulnerability_ids = ['CVE', 'REF-1', 'REF-2'] @@ -558,12 +538,12 @@ def test_handle_vulnerability_ids_references_and_cve(self, mock): self.assertEqual('CVE', mock.mock_calls[4].kwargs['finding'].cve) self.assertEqual(vulnerability_ids, mock.mock_calls[2].kwargs['finding'].unsaved_vulnerability_ids) - @patch('dojo.importers.utils.Vulnerability_Id', autospec=True) + @patch('dojo.importers.base_importer.Vulnerability_Id', autospec=True) def test_handle_no_vulnerability_ids_references_and_cve(self, mock): finding = Finding() finding.cve = 'CVE' - handle_vulnerability_ids(finding) + DefaultImporter().process_vulnerability_ids(finding) vulnerability_ids = ['CVE'] @@ -572,12 +552,12 @@ def test_handle_no_vulnerability_ids_references_and_cve(self, mock): self.assertEqual('CVE', mock.mock_calls[0].kwargs['finding'].cve) self.assertEqual(vulnerability_ids, mock.mock_calls[0].kwargs['finding'].unsaved_vulnerability_ids) - @patch('dojo.importers.utils.Vulnerability_Id', autospec=True) + @patch('dojo.importers.base_importer.Vulnerability_Id', autospec=True) def test_handle_vulnerability_ids_references_and_no_cve(self, mock): finding = Finding() finding.unsaved_vulnerability_ids = ['REF-1', 'REF-2'] - handle_vulnerability_ids(finding) + DefaultImporter().process_vulnerability_ids(finding) vulnerability_ids = ['REF-1', 'REF-2'] @@ -589,10 +569,10 @@ def test_handle_vulnerability_ids_references_and_no_cve(self, mock): self.assertEqual('REF-1', mock.mock_calls[2].kwargs['finding'].cve) self.assertEqual(vulnerability_ids, mock.mock_calls[2].kwargs['finding'].unsaved_vulnerability_ids) - @patch('dojo.importers.utils.Vulnerability_Id', autospec=True) + @patch('dojo.importers.base_importer.Vulnerability_Id', autospec=True) def test_no_handle_vulnerability_ids_references_and_no_cve(self, mock): finding = Finding() - handle_vulnerability_ids(finding) + DefaultImporter().process_vulnerability_ids(finding) mock.assert_not_called() diff --git a/unittests/test_rest_framework.py b/unittests/test_rest_framework.py index 5e2adac7a0..0427ceb1d9 100644 --- a/unittests/test_rest_framework.py +++ b/unittests/test_rest_framework.py @@ -143,7 +143,7 @@ TYPE_ARRAY = "array" #: TYPE_FILE = "file" #: -IMPORTER_MOCK_RETURN_VALUE = None, 0, 0, None +IMPORTER_MOCK_RETURN_VALUE = None, 0, 0, 0, 0, 0, MagicMock() REIMPORTER_MOCK_RETURN_VALUE = None, 0, 0, 0, 0, 0, MagicMock() @@ -1804,8 +1804,8 @@ def __init__(self, *args, **kwargs): def __del__(self: object): self.payload['file'].close() - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + @patch('dojo.importers.default_reimporter.DefaultReImporter.process_scan') + @patch('dojo.importers.default_importer.DefaultImporter.process_scan') @patch('dojo.api_v2.permissions.user_has_permission') def test_create_not_authorized_product_name_engagement_name(self, mock, importer_mock, reimporter_mock): mock.return_value = False @@ -1834,8 +1834,8 @@ def test_create_not_authorized_product_name_engagement_name(self, mock, importer importer_mock.assert_not_called() reimporter_mock.assert_not_called() - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + @patch('dojo.importers.default_reimporter.DefaultReImporter.process_scan') + @patch('dojo.importers.default_importer.DefaultImporter.process_scan') @patch('dojo.api_v2.permissions.user_has_permission') def test_create_not_authorized_product_name_engagement_name_auto_create_engagement(self, mock, importer_mock, reimporter_mock): mock.return_value = False @@ -1865,8 +1865,8 @@ def test_create_not_authorized_product_name_engagement_name_auto_create_engageme importer_mock.assert_not_called() reimporter_mock.assert_not_called() - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + @patch('dojo.importers.default_reimporter.DefaultReImporter.process_scan') + @patch('dojo.importers.default_importer.DefaultImporter.process_scan') @patch('dojo.api_v2.permissions.user_has_permission') def test_create_not_authorized_product_name_engagement_name_auto_create_product(self, mock, importer_mock, reimporter_mock): mock.return_value = False @@ -1897,8 +1897,8 @@ def test_create_not_authorized_product_name_engagement_name_auto_create_product( importer_mock.assert_not_called() reimporter_mock.assert_not_called() - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + @patch('dojo.importers.default_reimporter.DefaultReImporter.process_scan') + @patch('dojo.importers.default_importer.DefaultImporter.process_scan') @patch('dojo.api_v2.permissions.user_has_global_permission') def test_create_not_authorized_product_name_engagement_name_auto_create_product_type(self, mock, importer_mock, reimporter_mock): mock.return_value = False @@ -1928,8 +1928,8 @@ def test_create_not_authorized_product_name_engagement_name_auto_create_product_ importer_mock.assert_not_called() reimporter_mock.assert_not_called() - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + @patch('dojo.importers.default_reimporter.DefaultReImporter.process_scan') + @patch('dojo.importers.default_importer.DefaultImporter.process_scan') @patch('dojo.api_v2.permissions.user_has_permission') def test_create_authorized_product_name_engagement_name_auto_create_engagement(self, mock, importer_mock, reimporter_mock): """ @@ -1967,8 +1967,8 @@ def test_create_authorized_product_name_engagement_name_auto_create_engagement(s importer_mock.assert_called_once() reimporter_mock.assert_not_called() - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + @patch('dojo.importers.default_reimporter.DefaultReImporter.process_scan') + @patch('dojo.importers.default_importer.DefaultImporter.process_scan') @patch('dojo.api_v2.permissions.user_has_permission') def test_create_authorized_product_name_engagement_name_auto_create_product(self, mock, importer_mock, reimporter_mock): mock.return_value = True @@ -1998,8 +1998,8 @@ def test_create_authorized_product_name_engagement_name_auto_create_product(self importer_mock.assert_called_once() reimporter_mock.assert_not_called() - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + @patch('dojo.importers.default_reimporter.DefaultReImporter.process_scan') + @patch('dojo.importers.default_importer.DefaultImporter.process_scan') @patch('dojo.api_v2.permissions.user_has_global_permission') def test_create_authorized_product_name_engagement_name_auto_create_product_type(self, mock, importer_mock, reimporter_mock): mock.return_value = True @@ -2042,8 +2042,8 @@ def setUp(self): # Specific tests for reimport - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + @patch('dojo.importers.default_reimporter.DefaultReImporter.process_scan') + @patch('dojo.importers.default_importer.DefaultImporter.process_scan') def test_reimport_zap_xml(self, importer_mock, reimporter_mock): importer_mock.return_value = IMPORTER_MOCK_RETURN_VALUE reimporter_mock.return_value = REIMPORTER_MOCK_RETURN_VALUE @@ -2066,8 +2066,8 @@ def test_reimport_zap_xml(self, importer_mock, reimporter_mock): importer_mock.assert_not_called() reimporter_mock.assert_called_once() - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + @patch('dojo.importers.default_reimporter.DefaultReImporter.process_scan') + @patch('dojo.importers.default_importer.DefaultImporter.process_scan') @patch('dojo.api_v2.permissions.user_has_permission') def test_create_not_authorized_product_name_engagement_name(self, mock, importer_mock, reimporter_mock): mock.return_value = False @@ -2096,8 +2096,8 @@ def test_create_not_authorized_product_name_engagement_name(self, mock, importer importer_mock.assert_not_called() reimporter_mock.assert_not_called() - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + @patch('dojo.importers.default_reimporter.DefaultReImporter.process_scan') + @patch('dojo.importers.default_importer.DefaultImporter.process_scan') @patch('dojo.api_v2.permissions.user_has_permission') def test_create_authorized_product_name_engagement_name_scan_type_title_auto_create(self, mock, importer_mock, reimporter_mock): mock.return_value = True @@ -2126,8 +2126,8 @@ def test_create_authorized_product_name_engagement_name_scan_type_title_auto_cre importer_mock.assert_called_once() reimporter_mock.assert_not_called() - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + @patch('dojo.importers.default_reimporter.DefaultReImporter.process_scan') + @patch('dojo.importers.default_importer.DefaultImporter.process_scan') @patch('dojo.api_v2.permissions.user_has_permission') def test_create_authorized_product_name_engagement_name_auto_create_engagement(self, mock, importer_mock, reimporter_mock): """ @@ -2165,8 +2165,8 @@ def test_create_authorized_product_name_engagement_name_auto_create_engagement(s importer_mock.assert_called_once() reimporter_mock.assert_not_called() - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + @patch('dojo.importers.default_reimporter.DefaultReImporter.process_scan') + @patch('dojo.importers.default_importer.DefaultImporter.process_scan') @patch('dojo.api_v2.permissions.user_has_permission') def test_create_authorized_product_name_engagement_name_auto_create_product(self, mock, importer_mock, reimporter_mock): mock.return_value = True @@ -2197,8 +2197,8 @@ def test_create_authorized_product_name_engagement_name_auto_create_product(self importer_mock.assert_called_once() reimporter_mock.assert_not_called() - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + @patch('dojo.importers.default_reimporter.DefaultReImporter.process_scan') + @patch('dojo.importers.default_importer.DefaultImporter.process_scan') @patch('dojo.api_v2.permissions.user_has_global_permission') def test_create_authorized_product_name_engagement_name_auto_create_product_type(self, mock, importer_mock, reimporter_mock): mock.return_value = True @@ -2228,8 +2228,8 @@ def test_create_authorized_product_name_engagement_name_auto_create_product_type importer_mock.assert_called_once() reimporter_mock.assert_not_called() - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + @patch('dojo.importers.default_reimporter.DefaultReImporter.process_scan') + @patch('dojo.importers.default_importer.DefaultImporter.process_scan') @patch('dojo.api_v2.permissions.user_has_permission') def test_create_not_authorized_test_id(self, mock, importer_mock, reimporter_mock): mock.return_value = False @@ -2256,8 +2256,8 @@ def test_create_not_authorized_test_id(self, mock, importer_mock, reimporter_moc # copied tests from import, unsure how to use inheritance/mixins with test_ methods - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + @patch('dojo.importers.default_reimporter.DefaultReImporter.process_scan') + @patch('dojo.importers.default_importer.DefaultImporter.process_scan') @patch('dojo.api_v2.permissions.user_has_permission') def test_create_not_authorized_product_name_engagement_name_auto_create_engagement(self, mock, importer_mock, reimporter_mock): mock.return_value = False @@ -2287,8 +2287,8 @@ def test_create_not_authorized_product_name_engagement_name_auto_create_engageme importer_mock.assert_not_called() reimporter_mock.assert_not_called() - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + @patch('dojo.importers.default_reimporter.DefaultReImporter.process_scan') + @patch('dojo.importers.default_importer.DefaultImporter.process_scan') @patch('dojo.api_v2.permissions.user_has_permission') def test_create_not_authorized_product_name_engagement_name_auto_create_product(self, mock, importer_mock, reimporter_mock): mock.return_value = False @@ -2319,8 +2319,8 @@ def test_create_not_authorized_product_name_engagement_name_auto_create_product( importer_mock.assert_not_called() reimporter_mock.assert_not_called() - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + @patch('dojo.importers.default_reimporter.DefaultReImporter.process_scan') + @patch('dojo.importers.default_importer.DefaultImporter.process_scan') @patch('dojo.api_v2.permissions.user_has_global_permission') def test_create_not_authorized_product_name_engagement_name_auto_create_product_type(self, mock, importer_mock, reimporter_mock): mock.return_value = False @@ -2350,8 +2350,8 @@ def test_create_not_authorized_product_name_engagement_name_auto_create_product_ importer_mock.assert_not_called() reimporter_mock.assert_not_called() - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + @patch('dojo.importers.default_reimporter.DefaultReImporter.process_scan') + @patch('dojo.importers.default_importer.DefaultImporter.process_scan') @patch('dojo.api_v2.permissions.user_has_permission') def test_create_not_authorized_product_name_engagement_name_scan_type(self, mock, importer_mock, reimporter_mock): mock.return_value = False @@ -2378,8 +2378,8 @@ def test_create_not_authorized_product_name_engagement_name_scan_type(self, mock importer_mock.assert_not_called() reimporter_mock.assert_not_called() - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + @patch('dojo.importers.default_reimporter.DefaultReImporter.process_scan') + @patch('dojo.importers.default_importer.DefaultImporter.process_scan') @patch('dojo.api_v2.permissions.user_has_permission') def test_create_not_authorized_product_name_engagement_name_scan_type_title(self, mock, importer_mock, reimporter_mock): mock.return_value = False From 227d06960f058be3227bf518cfd9bbb5fa4d83bf Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Fri, 3 May 2024 04:58:39 +0200 Subject: [PATCH 125/138] fix awssecurityhub findings (#10072) --- dojo/tools/awssecurityhub/compliance.py | 13 ++++++++++++- dojo/tools/awssecurityhub/guardduty.py | 18 +++++++++++------- dojo/tools/awssecurityhub/inspector.py | 9 ++++++--- unittests/tools/test_awssecurityhub_parser.py | 4 +++- 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/dojo/tools/awssecurityhub/compliance.py b/dojo/tools/awssecurityhub/compliance.py index 3898442d69..fe365c76f8 100644 --- a/dojo/tools/awssecurityhub/compliance.py +++ b/dojo/tools/awssecurityhub/compliance.py @@ -7,13 +7,24 @@ def get_item(self, finding: dict, test): finding_id = finding.get("Id", "") title = finding.get("Title", "") severity = finding.get("Severity", {}).get("Label", "INFORMATIONAL").title() + resource_arns = [] + for resource in finding.get("Resources", []): + if arn := resource.get("Id"): + resource_arns.append(arn) mitigation = "" impact = [] references = [] unsaved_vulnerability_ids = [] epss_score = None mitigation = finding.get("Remediation", {}).get("Recommendation", {}).get("Text", "") - description = "This is a Security Hub Finding \n" + finding.get("Description", "") + mitigation += "\n" + finding.get("Remediation", {}).get("Recommendation", {}).get("Url", "") + description = "This is a Security Hub Finding \n" + finding.get("Description", "") + "\n" + description += f"**AWS Finding ARN:** {finding_id}\n" + description += f"**Resource IDs:** {', '.join(set(resource_arns))}\n" + description += f"**AwsAccountId:** {finding.get('AwsAccountId', '')}\n" + if finding.get('Region'): + description += f"**Region:** {finding.get('Region', '')}\n" + description += f"**Generator ID:** {finding.get('GeneratorId', '')}\n" if finding.get("Compliance", {}).get("Status", "PASSED") == "PASSED": is_Mitigated = True active = False diff --git a/dojo/tools/awssecurityhub/guardduty.py b/dojo/tools/awssecurityhub/guardduty.py index 3b22498ddc..66914938e3 100644 --- a/dojo/tools/awssecurityhub/guardduty.py +++ b/dojo/tools/awssecurityhub/guardduty.py @@ -15,7 +15,7 @@ def get_item(self, finding: dict, test): mitigations = finding.get("FindingProviderFields", {}).get("Types") for mitigate in mitigations: mitigation += mitigate + "\n" - mitigation += "https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_finding-types-active.html" + mitigation += "[https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_finding-types-active.html](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_finding-types-active.html)" active = True if finding.get("RecordState") == "ACTIVE": is_Mitigated = False @@ -29,12 +29,16 @@ def get_item(self, finding: dict, test): mitigated = datetime.strptime(finding.get("LastObservedAt"), "%Y-%m-%dT%H:%M:%fZ") else: mitigated = datetime.utcnow() - description = f"This is a GuardDuty Finding\n{finding.get('Description', '')}" - description += f"SourceURL: {finding.get('SourceUrl', '')}\n" - description += f"AwsAccountId: {finding.get('AwsAccountId', '')}\n" - description += f"Region: {finding.get('Region', '')}\n" + description = f"This is a GuardDuty Finding\n{finding.get('Description', '')}" + "\n" + description += f"**AWS Finding ARN:** {finding_id}\n" + if finding.get('SourceUrl'): + sourceurl = "[" + finding.get('SourceUrl') + "](" + finding.get('SourceUrl') + ")" + description += f"**SourceURL:** {sourceurl}\n" + description += f"**AwsAccountId:** {finding.get('AwsAccountId', '')}\n" + description += f"**Region:** {finding.get('Region', '')}\n" + description += f"**Generator ID:** {finding.get('GeneratorId', '')}\n" title_suffix = "" - hosts = list() + hosts = [] for resource in finding.get("Resources", []): component_name = resource.get("Type") if component_name in ("AwsEcrContainerImage", "AwsEc2Instance"): @@ -73,7 +77,7 @@ def get_item(self, finding: dict, test): dynamic_finding=False, component_name=component_name, ) - result.unsaved_endpoints = list() + result.unsaved_endpoints = [] result.unsaved_endpoints.extend(hosts) if epss_score is not None: result.epss_score = epss_score diff --git a/dojo/tools/awssecurityhub/inspector.py b/dojo/tools/awssecurityhub/inspector.py index 2c4c79db4e..da58cc28c8 100644 --- a/dojo/tools/awssecurityhub/inspector.py +++ b/dojo/tools/awssecurityhub/inspector.py @@ -12,7 +12,10 @@ def get_item(self, finding: dict, test): references = [] unsaved_vulnerability_ids = [] epss_score = None - description = f"This is an Inspector Finding\n{finding.get('Description', '')}" + description = f"This is an Inspector Finding\n{finding.get('Description', '')}" + "\n" + description += f"**AWS Finding ARN:** {finding_id}\n" + description += f"**AwsAccountId:** {finding.get('AwsAccountId', '')}\n" + description += f"**Region:** {finding.get('Region', '')}\n" vulnerabilities = finding.get("Vulnerabilities", []) for vulnerability in vulnerabilities: # Save the CVE if it is present @@ -47,7 +50,7 @@ def get_item(self, finding: dict, test): else: mitigated = datetime.utcnow() title_suffix = "" - hosts = list() + hosts = [] for resource in finding.get("Resources", []): component_name = resource.get("Type") hosts.append(Endpoint(host=f"{component_name} {resource.get('Id')}")) @@ -85,7 +88,7 @@ def get_item(self, finding: dict, test): dynamic_finding=False, component_name=component_name, ) - result.unsaved_endpoints = list() + result.unsaved_endpoints = [] result.unsaved_endpoints.extend(hosts) if epss_score is not None: result.epss_score = epss_score diff --git a/unittests/tools/test_awssecurityhub_parser.py b/unittests/tools/test_awssecurityhub_parser.py index 5f3621a609..464733c460 100644 --- a/unittests/tools/test_awssecurityhub_parser.py +++ b/unittests/tools/test_awssecurityhub_parser.py @@ -39,6 +39,7 @@ def test_many_findings(self): self.assertEqual(3, len(findings)) finding = findings[0] self.assertEqual(finding.component_name, "AwsAccount") + self.assertEqual("This is a Security Hub Finding \nThis AWS control checks whether AWS Multi-Factor Authentication (MFA) is enabled for all AWS Identity and Access Management (IAM) users that use a console password.\n**AWS Finding ARN:** arn:aws:securityhub:us-east-1:012345678912:subscription/aws-foundational-security-best-practices/v/1.0.0/IAM.5/finding/de861909-2d26-4e45-bd86-19d2ab6ceef1\n**Resource IDs:** AWS::::Account:012345678912\n**AwsAccountId:** 012345678912\n**Generator ID:** aws-foundational-security-best-practices/v/1.0.0/IAM.5\n", finding.description) def test_repeated_findings(self): with open(get_unit_tests_path() + sample_path("config_repeated_findings.json")) as test_file: @@ -121,6 +122,7 @@ def test_guardduty(self): self.assertEqual("Low", finding.severity) self.assertTrue(finding.active) self.assertEqual("User AssumedRole : 123123123 is anomalously invoking APIs commonly used in Discovery tactics. - Resource: 123123123", finding.title) - self.assertEqual("TTPs/Discovery/IAMUser-AnomalousBehavior\nhttps://docs.aws.amazon.com/guardduty/latest/ug/guardduty_finding-types-active.html", finding.mitigation) + self.assertEqual("TTPs/Discovery/IAMUser-AnomalousBehavior\n[https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_finding-types-active.html](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_finding-types-active.html)", finding.mitigation) endpoint = findings[0].unsaved_endpoints[0] self.assertEqual('AwsEc2Instance arn:aws:ec2:us-east-1:123456789012:instance/i-1234567890', endpoint.host) + self.assertEqual("This is a GuardDuty Finding\nAPIs commonly used in Discovery tactics were invoked by user AssumedRole : 123123123, under anomalous circumstances. Such activity is not typically seen from this user.\n**AWS Finding ARN:** arn:aws:guardduty:us-east-1:123456789012:detector/123456789/finding/2123123123123\n**SourceURL:** [https://us-east-1.console.aws.amazon.com/guardduty/home?region=us-east-1#/findings?macros=current&fId=2123123123123](https://us-east-1.console.aws.amazon.com/guardduty/home?region=us-east-1#/findings?macros=current&fId=2123123123123)\n**AwsAccountId:** 123456789012\n**Region:** us-east-1\n**Generator ID:** arn:aws:guardduty:us-east-1:123456789012:detector/123456789\n", finding.description) From 425ec145aaa29eabfd73f0826fca8f346c356b25 Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Fri, 3 May 2024 04:59:07 +0200 Subject: [PATCH 126/138] :bug: Fix RedHatSatellite components (#10082) --- dojo/tools/redhatsatellite/parser.py | 2 +- .../scans/redhatsatellite/many_packages.json | 258 ++++++++++++++++++ .../tools/test_redhatsatellite_parser.py | 7 + 3 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 unittests/scans/redhatsatellite/many_packages.json diff --git a/dojo/tools/redhatsatellite/parser.py b/dojo/tools/redhatsatellite/parser.py index 4ca94bdf5b..36e2f732f4 100644 --- a/dojo/tools/redhatsatellite/parser.py +++ b/dojo/tools/redhatsatellite/parser.py @@ -62,13 +62,13 @@ def get_findings(self, filename, test): description += "**installable:** " + str(installable) + "\n" description += "**bugs:** " + str(bugs) + "\n" description += "**module_streams:** " + str(module_streams) + "\n" + description += "**packages:** " + ', '.join(packages) find = Finding( title=title, test=test, description=description, severity=self.severity_mapping(input=severity), mitigation=solution, - component_name=packages, dynamic_finding=True, ) if errata_id is not None: diff --git a/unittests/scans/redhatsatellite/many_packages.json b/unittests/scans/redhatsatellite/many_packages.json new file mode 100644 index 0000000000..3a6b021301 --- /dev/null +++ b/unittests/scans/redhatsatellite/many_packages.json @@ -0,0 +1,258 @@ +{ + "total": 24, + "subtotal": 24, + "selectable": 24, + "page": "1", + "per_page": "100", + "error": null, + "search": null, + "sort": { + "by": "updated", + "order": "desc" + }, + "results": [ + { + "id": 1234, + "pulp_id": "RHBA-1999:5678", + "title": "glibc bug fix update", + "errata_id": "RHBA-1999:5678", + "issued": "1999-03-05", + "updated": "1999-03-05", + "severity": "None", + "description": "description", + "solution": "solution", + "summary": "summary", + "reboot_suggested": true, + "uuid": "RHBA-1999:5678", + "name": "bug fix update", + "type": "bugfix", + "cves": [], + "bugs": [], + "hosts_available_count": 9, + "hosts_applicable_count": 9, + "packages": [ + "asdf-123456.i111", + "asdf-123456.99_11", + "asdf-asdf-fjewios-123456.99_11", + "asdf-asdf-123456.99_11", + "asdf-asdf-123456.99_11", + "asdf-asdf-123456.i111", + "asdf-asdf-123456.99_11", + "asdf-asdf-123456.asdf", + "asdf-asdf-asdf-123456.i111", + "asdf-asdf-asdf-123456.99_11", + "asdf-asdf-123456.99_11", + "asdf-fjewio-aa-123456.99_11", + "asdf-fjewio-af-123456.99_11", + "asdf-fjewio-agr-123456.99_11", + "asdf-fjewio-ak-123456.99_11", + "asdf-fjewio-am-123456.99_11", + "asdf-fjewio-an-123456.99_11", + "asdf-fjewio-anp-123456.99_11", + "asdf-fjewio-ar-123456.99_11", + "asdf-fjewio-as-123456.99_11", + "asdf-fjewio-ast-123456.99_11", + "asdf-fjewio-ayc-123456.99_11", + "asdf-fjewio-az-123456.99_11", + "asdf-fjewio-be-123456.99_11", + "asdf-fjewio-bem-123456.99_11", + "asdf-fjewio-ber-123456.99_11", + "asdf-fjewio-bg-123456.99_11", + "asdf-fjewio-bhb-123456.99_11", + "asdf-fjewio-bho-123456.99_11", + "asdf-fjewio-bi-123456.99_11", + "asdf-fjewio-bn-123456.99_11", + "asdf-fjewio-bo-123456.99_11", + "asdf-fjewio-br-123456.99_11", + "asdf-fjewio-brx-123456.99_11", + "asdf-fjewio-bs-123456.99_11", + "asdf-fjewio-byn-123456.99_11", + "asdf-fjewio-ca-123456.99_11", + "asdf-fjewio-ce-123456.99_11", + "asdf-fjewio-chr-123456.99_11", + "asdf-fjewio-ckb-123456.99_11", + "asdf-fjewio-cmn-123456.99_11", + "asdf-fjewio-crh-123456.99_11", + "asdf-fjewio-cs-123456.99_11", + "asdf-fjewio-csb-123456.99_11", + "asdf-fjewio-cv-123456.99_11", + "asdf-fjewio-cy-123456.99_11", + "asdf-fjewio-da-123456.99_11", + "asdf-fjewio-de-123456.99_11", + "asdf-fjewio-doi-123456.99_11", + "asdf-fjewio-dsb-123456.99_11", + "asdf-fjewio-dv-123456.99_11", + "asdf-fjewio-dz-123456.99_11", + "asdf-fjewio-el-123456.99_11", + "asdf-fjewio-en-123456.99_11", + "asdf-fjewio-eo-123456.99_11", + "asdf-fjewio-es-123456.99_11", + "asdf-fjewio-et-123456.99_11", + "asdf-fjewio-eu-123456.99_11", + "asdf-fjewio-fa-123456.99_11", + "asdf-fjewio-ff-123456.99_11", + "asdf-fjewio-fi-123456.99_11", + "asdf-fjewio-fil-123456.99_11", + "asdf-fjewio-fo-123456.99_11", + "asdf-fjewio-fr-123456.99_11", + "asdf-fjewio-fur-123456.99_11", + "asdf-fjewio-fy-123456.99_11", + "asdf-fjewio-ga-123456.99_11", + "asdf-fjewio-gd-123456.99_11", + "asdf-fjewio-gez-123456.99_11", + "asdf-fjewio-gl-123456.99_11", + "asdf-fjewio-gu-123456.99_11", + "asdf-fjewio-gv-123456.99_11", + "asdf-fjewio-ha-123456.99_11", + "asdf-fjewio-hak-123456.99_11", + "asdf-fjewio-he-123456.99_11", + "asdf-fjewio-hi-123456.99_11", + "asdf-fjewio-hif-123456.99_11", + "asdf-fjewio-hne-123456.99_11", + "asdf-fjewio-hr-123456.99_11", + "asdf-fjewio-hsb-123456.99_11", + "asdf-fjewio-ht-123456.99_11", + "asdf-fjewio-hu-123456.99_11", + "asdf-fjewio-hy-123456.99_11", + "asdf-fjewio-ia-123456.99_11", + "asdf-fjewio-id-123456.99_11", + "asdf-fjewio-ig-123456.99_11", + "asdf-fjewio-ik-123456.99_11", + "asdf-fjewio-is-123456.99_11", + "asdf-fjewio-it-123456.99_11", + "asdf-fjewio-iu-123456.99_11", + "asdf-fjewio-ja-123456.99_11", + "asdf-fjewio-ka-123456.99_11", + "asdf-fjewio-kab-123456.99_11", + "asdf-fjewio-kk-123456.99_11", + "asdf-fjewio-kl-123456.99_11", + "asdf-fjewio-km-123456.99_11", + "asdf-fjewio-kn-123456.99_11", + "asdf-fjewio-ko-123456.99_11", + "asdf-fjewio-kok-123456.99_11", + "asdf-fjewio-ks-123456.99_11", + "asdf-fjewio-ku-123456.99_11", + "asdf-fjewio-kw-123456.99_11", + "asdf-fjewio-ky-123456.99_11", + "asdf-fjewio-lb-123456.99_11", + "asdf-fjewio-lg-123456.99_11", + "asdf-fjewio-li-123456.99_11", + "asdf-fjewio-lij-123456.99_11", + "asdf-fjewio-ln-123456.99_11", + "asdf-fjewio-lo-123456.99_11", + "asdf-fjewio-lt-123456.99_11", + "asdf-fjewio-lv-123456.99_11", + "asdf-fjewio-lzh-123456.99_11", + "asdf-fjewio-mag-123456.99_11", + "asdf-fjewio-mai-123456.99_11", + "asdf-fjewio-mfe-123456.99_11", + "asdf-fjewio-mg-123456.99_11", + "asdf-fjewio-mhr-123456.99_11", + "asdf-fjewio-mi-123456.99_11", + "asdf-fjewio-miq-123456.99_11", + "asdf-fjewio-mjw-123456.99_11", + "asdf-fjewio-mk-123456.99_11", + "asdf-fjewio-ml-123456.99_11", + "asdf-fjewio-mn-123456.99_11", + "asdf-fjewio-mni-123456.99_11", + "asdf-fjewio-mnw-123456.99_11", + "asdf-fjewio-mr-123456.99_11", + "asdf-fjewio-ms-123456.99_11", + "asdf-fjewio-mt-123456.99_11", + "asdf-fjewio-my-123456.99_11", + "asdf-fjewio-nan-123456.99_11", + "asdf-fjewio-nb-123456.99_11", + "asdf-fjewio-nds-123456.99_11", + "asdf-fjewio-ne-123456.99_11", + "asdf-fjewio-nhn-123456.99_11", + "asdf-fjewio-niu-123456.99_11", + "asdf-fjewio-nl-123456.99_11", + "asdf-fjewio-nn-123456.99_11", + "asdf-fjewio-nr-123456.99_11", + "asdf-fjewio-nso-123456.99_11", + "asdf-fjewio-oc-123456.99_11", + "asdf-fjewio-om-123456.99_11", + "asdf-fjewio-or-123456.99_11", + "asdf-fjewio-os-123456.99_11", + "asdf-fjewio-pa-123456.99_11", + "asdf-fjewio-pap-123456.99_11", + "asdf-fjewio-pl-123456.99_11", + "asdf-fjewio-ps-123456.99_11", + "asdf-fjewio-pt-123456.99_11", + "asdf-fjewio-quz-123456.99_11", + "asdf-fjewio-raj-123456.99_11", + "asdf-fjewio-ro-123456.99_11", + "asdf-fjewio-ru-123456.99_11", + "asdf-fjewio-rw-123456.99_11", + "asdf-fjewio-sa-123456.99_11", + "asdf-fjewio-sah-123456.99_11", + "asdf-fjewio-sat-123456.99_11", + "asdf-fjewio-sc-123456.99_11", + "asdf-fjewio-sd-123456.99_11", + "asdf-fjewio-se-123456.99_11", + "asdf-fjewio-sgs-123456.99_11", + "asdf-fjewio-shn-123456.99_11", + "asdf-fjewio-shs-123456.99_11", + "asdf-fjewio-si-123456.99_11", + "asdf-fjewio-sid-123456.99_11", + "asdf-fjewio-sk-123456.99_11", + "asdf-fjewio-sl-123456.99_11", + "asdf-fjewio-sm-123456.99_11", + "asdf-fjewio-so-123456.99_11", + "asdf-fjewio-sq-123456.99_11", + "asdf-fjewio-sr-123456.99_11", + "asdf-fjewio-ss-123456.99_11", + "asdf-fjewio-st-123456.99_11", + "asdf-fjewio-sv-123456.99_11", + "asdf-fjewio-sw-123456.99_11", + "asdf-fjewio-szl-123456.99_11", + "asdf-fjewio-ta-123456.99_11", + "asdf-fjewio-tcy-123456.99_11", + "asdf-fjewio-te-123456.99_11", + "asdf-fjewio-tg-123456.99_11", + "asdf-fjewio-th-123456.99_11", + "asdf-fjewio-the-123456.99_11", + "asdf-fjewio-ti-123456.99_11", + "asdf-fjewio-tig-123456.99_11", + "asdf-fjewio-tk-123456.99_11", + "asdf-fjewio-tl-123456.99_11", + "asdf-fjewio-tn-123456.99_11", + "asdf-fjewio-to-123456.99_11", + "asdf-fjewio-tpi-123456.99_11", + "asdf-fjewio-tr-123456.99_11", + "asdf-fjewio-ts-123456.99_11", + "asdf-fjewio-tt-123456.99_11", + "asdf-fjewio-ug-123456.99_11", + "asdf-fjewio-uk-123456.99_11", + "asdf-fjewio-unm-123456.99_11", + "asdf-fjewio-ur-123456.99_11", + "asdf-fjewio-uz-123456.99_11", + "asdf-fjewio-ve-123456.99_11", + "asdf-fjewio-vi-123456.99_11", + "asdf-fjewio-wa-123456.99_11", + "asdf-fjewio-wae-123456.99_11", + "asdf-fjewio-wal-123456.99_11", + "asdf-fjewio-wo-123456.99_11", + "asdf-fjewio-xh-123456.99_11", + "asdf-fjewio-yi-123456.99_11", + "asdf-fjewio-yo-123456.99_11", + "asdf-fjewio-yue-123456.99_11", + "asdf-fjewio-yuw-123456.99_11", + "asdf-fjewio-zh-123456.99_11", + "asdf-fjewio-zu-123456.99_11", + "asdf-locale-source-123456.99_11", + "asdf-asdf-fjewio-123456.99_11", + "asdf-asdf-123456.i111", + "asdf-asdf-123456.99_11", + "asdf--123456.i111", + "asdf--123456.99_11", + "asdf-123456.99_11", + "asfd-123456.i111", + "asdf-123456.99_11", + "asdf-123456.99_11" + ], + "module_streams": [], + "installable": true + } + ] +} \ No newline at end of file diff --git a/unittests/tools/test_redhatsatellite_parser.py b/unittests/tools/test_redhatsatellite_parser.py index b1c2771bcf..6c87cbfd61 100644 --- a/unittests/tools/test_redhatsatellite_parser.py +++ b/unittests/tools/test_redhatsatellite_parser.py @@ -25,3 +25,10 @@ def test_parse_file_with_multiple_findingse(self): self.assertEqual("RHSA-1966:12313", findings[0].unsaved_vulnerability_ids[0]) self.assertEqual("CVE-1990-1", findings[0].unsaved_vulnerability_ids[1]) self.assertEqual("CVE-1990-2", findings[0].unsaved_vulnerability_ids[2]) + + def test_parse_file_with_many_packages(self): + with open("unittests/scans/redhatsatellite/many_packages.json") as testfile: + parser = RedHatSatelliteParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(1, len(findings)) + self.assertEqual("RHBA-1999:5678", findings[0].unsaved_vulnerability_ids[0]) From 1391d31e481895b6ce1254694f4cec20f98887f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 May 2024 16:12:17 -0500 Subject: [PATCH 127/138] Bump boto3 from 1.34.96 to 1.34.97 (#10106) Bumps [boto3](https://github.com/boto/boto3) from 1.34.96 to 1.34.97. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.34.96...1.34.97) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a04a000cc4..6c86c9c6d8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -75,7 +75,7 @@ django-ratelimit==4.1.0 argon2-cffi==23.1.0 blackduck==1.1.3 pycurl==7.45.3 # Required for Celery Broker AWS (SQS) support -boto3==1.34.96 # Required for Celery Broker AWS (SQS) support +boto3==1.34.97 # Required for Celery Broker AWS (SQS) support netaddr==1.2.1 vulners==2.1.5 fontawesomefree==6.5.1 From af8509a9ca27c0b2db4b3c45fcd3a79f9530e9a3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 3 May 2024 16:37:00 -0500 Subject: [PATCH 128/138] Update rabbitmq Docker tag from 3.13.1 to v3.13.2 (docker-compose.yml) (#10103) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 69319da2c2..3dd8ac76ee 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -148,7 +148,7 @@ services: volumes: - defectdojo_postgres:/var/lib/postgresql/data rabbitmq: - image: rabbitmq:3.13.1-alpine@sha256:4bcec9fde55c9baf6c73a6969bd9070fb109ced1a5daa9679eb90c8145940809 + image: rabbitmq:3.13.2-alpine@sha256:9880c790e61a6ba7f2740b208f5584c08ce2fe668ef4852d30e554a1c07b6f63 profiles: - mysql-rabbitmq - postgres-rabbitmq From afc2a0824c903c4502d947f6c2b84b91c3cc1e67 Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Fri, 3 May 2024 23:46:50 +0200 Subject: [PATCH 129/138] :bug: fix hcl_appscan, handle severity is None #10074 (#10101) * :bug: fix hcl_appscan, handle severity is None #10074 * fix according to review --- dojo/tools/hcl_appscan/parser.py | 9 +- unittests/scans/hcl_appscan/issue_10074.xml | 861 ++++++++++++++++++++ unittests/tools/test_hcl_appscan_parser.py | 8 + 3 files changed, 876 insertions(+), 2 deletions(-) create mode 100644 unittests/scans/hcl_appscan/issue_10074.xml diff --git a/dojo/tools/hcl_appscan/parser.py b/dojo/tools/hcl_appscan/parser.py index 8f559acc53..16a808a6ac 100755 --- a/dojo/tools/hcl_appscan/parser.py +++ b/dojo/tools/hcl_appscan/parser.py @@ -14,7 +14,9 @@ def get_description_for_scan_types(self, scan_type): return "Import XML output of HCL AppScan." def xmltreehelper(self, input): - if "\n" in input.text: + if input.text is None: + output = None + elif "\n" in input.text: output = "" for i in input: output = output + " " + i.text @@ -39,7 +41,10 @@ def get_findings(self, file, test): match item.tag: case 'severity': output = self.xmltreehelper(item) - severity = output.strip(" ").capitalize() + if output is None: + severity = "Info" + else: + severity = output.strip(" ").capitalize() case 'cwe': cwe = int(self.xmltreehelper(item)) case 'remediation': diff --git a/unittests/scans/hcl_appscan/issue_10074.xml b/unittests/scans/hcl_appscan/issue_10074.xml new file mode 100644 index 0000000000..4e4f3e0cbc --- /dev/null +++ b/unittests/scans/hcl_appscan/issue_10074.xml @@ -0,0 +1,861 @@ + + + + + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + + + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + CENSURED + + + CENSURED + + <report-type /> + <description /> + <header /> + <footer /> + <include-date>CENSURED</include-date> + <report-date-and-time>CENSURED</report-date-and-time> + <company-logo-path /> + <additional-logo-path /> + <margins>CENSURED</margins> + <node-path /> + <coverage>CENSURED</coverage> + </layout> + <scan-information> + <scan-name>CENSURED</scan-name> + <scan-file-name>CENSURED</scan-file-name> + <scan-date-and-time>CENSURED</scan-date-and-time> + <scan-date-and-time-iso>CENSURED</scan-date-and-time-iso> + <product-name>CENSURED</product-name> + <product-version>CENSURED</product-version> + <cvss-version>CENSURED</cvss-version> + </scan-information> + <scan-configuration> + <login-settings-group> + <allow-concurrent-logins>CENSURED</allow-concurrent-logins> + <enable-Jsx-In-login-replay>CENSURED</enable-Jsx-In-login-replay> + <session-management-mode>CENSURED</session-management-mode> + <session-verifier-enabled>CENSURED</session-verifier-enabled> + <session-verifier-pattern>CENSURED</session-verifier-pattern> + <tracked-cookies> + <cookie>CENSURED</cookie> + <cookie>CENSURED</cookie> + </tracked-cookies> + <tracked-parameters /> + <recorded-urls-sequence> + <url>CENSURED</url> + <url>CENSURED</url> + </recorded-urls-sequence> + </login-settings-group> + <test-policy-name>CENSURED</test-policy-name> + <test-optimization-level>CENSURED</test-optimization-level> + <starting-url>CENSURED</starting-url> + <link-limit-state>CENSURED</link-limit-state> + <link-limit>CENSURED</link-limit> + <depth-limit-state>CENSURED</depth-limit-state> + <depth-limit>CENSURED</depth-limit> + <path-limit-state>CENSURED</path-limit-state> + <path-limit>CENSURED</path-limit> + <form-filler-state>CENSURED</form-filler-state> + <java-script-links-execution>CENSURED</java-script-links-execution> + <java-script-links-extraction>CENSURED</java-script-links-extraction> + <flash-execution-state>CENSURED</flash-execution-state> + <flash-links-extraction-state>CENSURED</flash-links-extraction-state> + <additional-servers-and-domains /> + <multi-phase-operation-names /> + <path-filters> + <path-filter> + <path>CENSURED</path> + <type>CENSURED</type> + <matching>CENSURED</matching> + </path-filter> + <path-filter> + <path>CENSURED</path> + <type>CENSURED</type> + <matching>CENSURED</matching> + </path-filter> + <path-filter> + <path>CENSURED</path> + <type>CENSURED</type> + <matching>CENSURED</matching> + </path-filter> + <path-filter> + <path>CENSURED</path> + <type>CENSURED</type> + <matching>CENSURED</matching> + </path-filter> + <path-filter> + <path>CENSURED</path> + <type>CENSURED</type> + <matching>CENSURED</matching> + </path-filter> + <path-filter> + <path>CENSURED</path> + <type>CENSURED</type> + <matching>CENSURED</matching> + </path-filter> + <path-filter> + <path>CENSURED</path> + <type>CENSURED</type> + <matching>CENSURED</matching> + </path-filter> + <path-filter> + <path>CENSURED</path> + <type>CENSURED</type> + <matching>CENSURED</matching> + </path-filter> + <path-filter> + <path>CENSURED</path> + <type>CENSURED</type> + <matching>CENSURED</matching> + </path-filter> + </path-filters> + <custom-proxy-settings>CENSURED</custom-proxy-settings> + <use-ie-proxy-settings>CENSURED</use-ie-proxy-settings> + <proxy-settings-ip-address /> + <proxy-settings-port>CENSURED</proxy-settings-port> + <scanned-hosts> + <item> + <host>CENSURED</host> + <port>CENSURED</port> + <operating-system>CENSURED</operating-system> + <web-server>CENSURED</web-server> + <application-server>CENSURED</application-server> + </item> + </scanned-hosts> + </scan-configuration> + <scan-summary> + <scan-Duration>CENSURED</scan-Duration> + <num-pages-scanned>CENSURED</num-pages-scanned> + <total-num-pages>CENSURED</total-num-pages> + <num-security-entities-tested>CENSURED</num-security-entities-tested> + <total-num-security-entities>CENSURED</total-num-security-entities> + <num-issues-found>CENSURED</num-issues-found> + <total-issues-severity-critical>CENSURED</total-issues-severity-critical> + <total-issues-severity-high>CENSURED</total-issues-severity-high> + <total-issues-severity-medium>CENSURED</total-issues-severity-medium> + <total-issues-severity-low>CENSURED</total-issues-severity-low> + <total-issues-severity-informational>CENSURED</total-issues-severity-informational> + <test-policy>CENSURED</test-policy> + </scan-summary> + <issue-type-group> + <item id="attBlindSqlInjectionStrings" count="4" maxIssueSeverity="6"> + <name>CENSURED</name> + <cve /> + <cwe>123</cwe> + <xfid>CENSURED</xfid> + <remediation> + <ref>CENSURED</ref> + </remediation> + <advisory> + <ref>CENSURED</ref> + </advisory> + <threat-class> + <ref>CENSURED</ref> + </threat-class> + <fix-recommendation> + <ref>CENSURED</ref> + </fix-recommendation> + <causes> + <ref>CENSURED</ref> + </causes> + <security-risks> + <ref>CENSURED</ref> + </security-risks> + <affected-products /> + </item> + <item id="attIntegerOverflow" count="65" maxIssueSeverity="3"> + <name>CENSURED</name> + <cve /> + <cwe>123</cwe> + <xfid>CENSURED</xfid> + <remediation> + <ref>CENSURED</ref> + </remediation> + <advisory> + <ref>CENSURED</ref> + </advisory> + <threat-class> + <ref>CENSURED</ref> + </threat-class> + <fix-recommendation> + <ref>CENSURED</ref> + </fix-recommendation> + <causes> + <ref>CENSURED</ref> + </causes> + <security-risks> + <ref>CENSURED</ref> + </security-risks> + <affected-products /> + </item> + <item id="attAPIImproperAssetsManagement" count="1" maxIssueSeverity="3"> + <name>CENSURED</name> + <cve /> + <cwe>123</cwe> + <xfid>CENSURED</xfid> + <remediation> + <ref>CENSURED</ref> + </remediation> + <advisory> + <ref>CENSURED</ref> + </advisory> + <threat-class> + <ref>CENSURED</ref> + </threat-class> + <fix-recommendation> + <ref>CENSURED</ref> + </fix-recommendation> + <causes> + <ref>CENSURED</ref> + </causes> + <security-risks> + <ref>CENSURED</ref> + </security-risks> + <affected-products /> + </item> + <item id="attJSCookie" count="1" maxIssueSeverity="0"> + <name>CENSURED</name> + <cve /> + <cwe>123</cwe> + <xfid>CENSURED</xfid> + <remediation> + <ref>CENSURED</ref> + </remediation> + <advisory> + <ref>CENSURED</ref> + </advisory> + <threat-class> + <ref>CENSURED</ref> + </threat-class> + <fix-recommendation> + <ref>CENSURED</ref> + </fix-recommendation> + <causes> + <ref>CENSURED</ref> + </causes> + <security-risks> + <ref>CENSURED</ref> + </security-risks> + <affected-products /> + </item> + </issue-type-group> + <fix-recommendation-group> + <item id="attBlindSqlInjectionStrings"> + <general> + <fixRecommendation type="General"> + <link target="http://msdn2.microsoft.com/en-us/library/ms533046.aspx">http://msdn2.microsoft.com/en-us/library/ms533046.aspx</link> + <text>CENSURED</text> + <link target="http://phpsec.org/">http://phpsec.org/</link> + <text>CENSURED</text> + <link target="http://shiflett.org/">http://shiflett.org/</link> + </fixRecommendation> + </general> + </item> + <item id="attIntegerOverflow"> + <general> + <fixRecommendation type="General"> + <text>CENSURED</text> + </fixRecommendation> + </general> + </item> + <item id="attAPIImproperAssetsManagement"> + <general> + <fixRecommendation type="General"> + <text>CENSURED</text> + </fixRecommendation> + </general> + </item> + <item id="attNXDOMAIN"> + <general> + <fixRecommendation type="General"> + <text>CENSURED</text> + <text>CENSURED</text> + </fixRecommendation> + </general> + </item> + <item id="attLoginNotOverSSL"> + <general> + <fixRecommendation type="General"> + <text /> + <text>CENSURED</text> + </fixRecommendation> + </general> + </item> + <item id="attSameSiteCookie"> + <general> + <fixRecommendation type="General"> + <text>CENSURED</text> + <text>CENSURED</text> + </fixRecommendation> + </general> + </item> + <item id="GV_SQLErr"> + <general> + <fixRecommendation type="General"> + <text>CENSURED</text> + <link target="http://msdn2.microsoft.com/en-us/library/ms533046.aspx">http://msdn2.microsoft.com/en-us/library/ms533046.aspx</link> + <text>CENSURED</text> + <link target="http://phpsec.org/">http://phpsec.org/</link> + <text>CENSURED</text> + <link target="http://shiflett.org/">http://shiflett.org/</link> + </fixRecommendation> + </general> + </item> + <item id="attReferrerPolicyHeaderExist"> + <general> + <fixRecommendation type="General"> + <text>CENSURED</text> + <text>CENSURED</text> + <text>CENSURED</text> + <text /> + <text>CENSURED</text> + <link target="https://developers.google.com/web/updates/2020/07/referrer-policy-new-chrome-default">https://developers.google.com/web/updates/2020/07/referrer-policy-new-chrome-default</link> + <text>CENSURED</text> + <link target="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy.">https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy.</link> + </fixRecommendation> + </general> + </item> + <item id="attJSCookie"> + <general> + <fixRecommendation type="General"> + <text>CENSURED</text> + <text>CENSURED</text> + </fixRecommendation> + </general> + </item> + </fix-recommendation-group> + <threat-class-group> + <item id="catSQLInjection" href="">CENSURED</item> + <item id="catIntegerOverflow" href="http://projects.webappsec.org/Integer-Overflows">Desbordamiento de enteros</item> + <item id="catAPIImproperAssetsManagement" href="">CENSURED</item> + <item id="catURLRedirectoryAbuse" href="http://projects.webappsec.org/URL-Redirector-Abuse">Abuso de redireccionamiento URL</item> + <item id="catInsufficientTransLayerProtection" href="http://projects.webappsec.org/Insufficient-Transport-Layer-Protection">Protección de capa de transporte insuficiente</item> + <item id="catServerMisconfiguration" href="http://projects.webappsec.org/Server-Misconfiguration">Error de configuración del servidor</item> + <item id="catCrossSiteRequestForgery" href="http://projects.webappsec.org/Cross-Site-Request-Forgery">Falsificación de solicitud entre sitios</item> + <item id="catXPathInjection" href="">CENSURED</item> + <item id="catInformationLeakage" href="http://projects.webappsec.org/Information-Leakage">Filtraje de información</item> + <item id="catAbuseOfFunctionality" href="">CENSURED</item> + </threat-class-group> + <issue-group total="384"> + <item id="-4714581656683135232" id-v2="626236621786310400"> + <severity /> + <severity-id>CENSURED</severity-id> + <cvss-score>CENSURED</cvss-score> + <cvss-vector> + <vector>CENSURED</vector> + </cvss-vector> + <cwe>123</cwe> + <issue-type> + <ref>CENSURED</ref> + </issue-type> + <remediation> + <ref>CENSURED</ref> + </remediation> + <advisory> + <ref>CENSURED</ref> + </advisory> + <threat-class> + <ref>CENSURED</ref> + </threat-class> + <entity> + <ref>CENSURED</ref> + </entity> + <url original_request_method="POST"> + <ref>CENSURED</ref> + </url> + <security-risks> + <ref>CENSURED</ref> + </security-risks> + <cause-id> + <ref>CENSURED</ref> + <ref>CENSURED</ref> + </cause-id> + <user-image-group /> + <variant-group> + <item id="74517"> + <issue-information> + <template>CENSURED</template> + <variant-id>CENSURED</variant-id> + <issue-tip>CENSURED</issue-tip> + <issue-tips> + <issue-tip>CENSURED</issue-tip> + </issue-tips> + <variantID>CENSURED</variantID> + <testResponseChunk>CENSURED</testResponseChunk> + </issue-information> + <comments /> + <reasoning id="3002">CENSURED</reasoning> + <additional-data /> + <cwe /> + <image-comment /> + <differences> + <item altered="%00" original="2019-01-01" name="DateTime$DDD$C$TE" difference-type="changed" difference-element="parameter" /> + </differences> + <iast-info /> + <test-http-traffic>CENSURED</test-http-traffic> + </item> + </variant-group> + </item> + <item id="1444716459353270272" id-v2="-7755935851978403328"> + <severity>High</severity> + <severity-id>CENSURED</severity-id> + <cvss-score>CENSURED</cvss-score> + <cvss-vector> + <vector>CENSURED</vector> + </cvss-vector> + <cwe>123</cwe> + <issue-type> + <ref>CENSURED</ref> + </issue-type> + <remediation> + <ref>CENSURED</ref> + </remediation> + <advisory> + <ref>CENSURED</ref> + </advisory> + <threat-class> + <ref>CENSURED</ref> + </threat-class> + <entity> + <ref>CENSURED</ref> + </entity> + <url original_request_method="POST"> + <ref>CENSURED</ref> + </url> + <security-risks> + <ref>CENSURED</ref> + </security-risks> + <cause-id> + <ref>CENSURED</ref> + <ref>CENSURED</ref> + </cause-id> + <user-image-group /> + <variant-group> + <item id="75906"> + <issue-information> + <template>CENSURED</template> + <variant-id>CENSURED</variant-id> + <issue-tip>CENSURED</issue-tip> + <issue-tips> + <issue-tip>CENSURED</issue-tip> + </issue-tips> + <variantID>CENSURED</variantID> + <testResponseChunk>CENSURED</testResponseChunk> + </issue-information> + <comments /> + <reasoning id="3002">CENSURED</reasoning> + <additional-data /> + <cwe /> + <image-comment /> + <differences> + <item altered="%00" original="C" name="cklValidTypes$RB3" difference-type="changed" difference-element="parameter" /> + </differences> + <iast-info /> + <test-http-traffic>CENSURED</test-http-traffic> + </item> + </variant-group> + </item> + <item id="-3181974832126986240" id-v2="1677351463514414080"> + <severity>High</severity> + <severity-id>CENSURED</severity-id> + <cvss-score>CENSURED</cvss-score> + <cvss-vector> + <vector>CENSURED</vector> + </cvss-vector> + <cwe>123</cwe> + <issue-type> + <ref>CENSURED</ref> + </issue-type> + <remediation> + <ref>CENSURED</ref> + </remediation> + <advisory> + <ref>CENSURED</ref> + </advisory> + <threat-class> + <ref>CENSURED</ref> + </threat-class> + <entity> + <ref>CENSURED</ref> + </entity> + <url original_request_method="POST"> + <ref>CENSURED</ref> + </url> + <security-risks> + <ref>CENSURED</ref> + </security-risks> + <cause-id> + <ref>CENSURED</ref> + <ref>CENSURED</ref> + </cause-id> + <user-image-group /> + <variant-group> + <item id="75769"> + <issue-information> + <template>CENSURED</template> + <variant-id>CENSURED</variant-id> + <issue-tip>CENSURED</issue-tip> + <issue-tips> + <issue-tip>CENSURED</issue-tip> + </issue-tips> + <variantID>CENSURED</variantID> + <testResponseChunk>CENSURED</testResponseChunk> + </issue-information> + <comments /> + <reasoning id="3002">CENSURED</reasoning> + <additional-data /> + <cwe /> + <image-comment /> + <differences> + <item altered="%00" original="I" name="cklValidTypes$RB9" difference-type="changed" difference-element="parameter" /> + </differences> + <iast-info /> + <test-http-traffic>CENSURED</test-http-traffic> + </item> + </variant-group> + </item> + <item id="-4966231569722402304" id-v2="5278767978099256320"> + <severity>High</severity> + <severity-id>CENSURED</severity-id> + <cvss-score>CENSURED</cvss-score> + <cvss-vector> + <vector>CENSURED</vector> + </cvss-vector> + <cwe>123</cwe> + <issue-type> + <ref>CENSURED</ref> + </issue-type> + <remediation> + <ref>CENSURED</ref> + </remediation> + <advisory> + <ref>CENSURED</ref> + </advisory> + <threat-class> + <ref>CENSURED</ref> + </threat-class> + <entity> + <ref>CENSURED</ref> + </entity> + <url original_request_method="POST"> + <ref>CENSURED</ref> + </url> + <security-risks> + <ref>CENSURED</ref> + </security-risks> + <cause-id> + <ref>CENSURED</ref> + <ref>CENSURED</ref> + </cause-id> + <user-image-group /> + <variant-group> + <item id="75868"> + <issue-information> + <template>CENSURED</template> + <variant-id>CENSURED</variant-id> + <issue-tip>CENSURED</issue-tip> + <issue-tips> + <issue-tip>CENSURED</issue-tip> + </issue-tips> + <variantID>CENSURED</variantID> + <testResponseChunk>CENSURED</testResponseChunk> + </issue-information> + <comments /> + <reasoning id="3002">CENSURED</reasoning> + <additional-data /> + <cwe /> + <image-comment /> + <differences> + <item altered="%00" original="1234" name="ReportSchedule.ExportPath" difference-type="changed" difference-element="parameter" /> + </differences> + <iast-info /> + <test-http-traffic>CENSURED</test-http-traffic> + </item> + </variant-group> + </item> + </issue-group> +</xml-report> \ No newline at end of file diff --git a/unittests/tools/test_hcl_appscan_parser.py b/unittests/tools/test_hcl_appscan_parser.py index daaf04f4a5..6c28f3c9c2 100644 --- a/unittests/tools/test_hcl_appscan_parser.py +++ b/unittests/tools/test_hcl_appscan_parser.py @@ -37,3 +37,11 @@ def test_issue_9279(self): self.assertEqual(findings[5].mitigation, "Remediation: fix_61771\nAdvisory: attReferrerPolicyHeaderExist") self.assertEqual(findings[1].description, "Issue-Type:attHttpsToHttp\nThreat-Class: catInformationLeakage\nEntity: 7089695691196187648\nSecurity-Risks: sensitiveNotOverSSL\nCause-Id: sensitiveDataNotSSL\n") self.assertEqual(findings[10].cwe, 1275) + + def test_issue_10074(self): + with open("unittests/scans/hcl_appscan/issue_10074.xml") as my_file_handle: + parser = HCLAppScanParser() + findings = parser.get_findings(my_file_handle, None) + my_file_handle.close() + self.assertEqual(4, len(findings)) + self.assertEqual(findings[0].severity, "Info") From a39c5fc36099b52a89d9f9cd3e272218bc592905 Mon Sep 17 00:00:00 2001 From: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> Date: Fri, 3 May 2024 17:39:20 -0500 Subject: [PATCH 130/138] Checkmarx One: Add additional parsing for different report formats (#10102) * Checkmarx One: Add additional parsing for different report formats * Add unit tests --- .../templates/dojo/findings_list_snippet.html | 2 +- dojo/templates/dojo/view_test.html | 5 +- dojo/tools/checkmarx_one/parser.py | 388 +- .../vulnerabilities_from_scan_results.json | 10627 ++++++++++++++++ unittests/tools/test_checkmarx_one_parser.py | 76 + 5 files changed, 10991 insertions(+), 107 deletions(-) create mode 100644 unittests/scans/checkmarx_one/vulnerabilities_from_scan_results.json diff --git a/dojo/templates/dojo/findings_list_snippet.html b/dojo/templates/dojo/findings_list_snippet.html index 85a5d45862..486d327fd5 100644 --- a/dojo/templates/dojo/findings_list_snippet.html +++ b/dojo/templates/dojo/findings_list_snippet.html @@ -536,7 +536,7 @@ <h3 class="has-filters"> {% if finding.file_path %} <i class="fa-solid fa-folder has-popover dojo-sup" data-trigger="hover" - data-content="{{ finding.file_path }}" + data-content="{{ finding.file_path }}{% if finding.line %}:{{finding.line}}{% endif %}" data-placement="right" data-container="body" data-original-title="Files" diff --git a/dojo/templates/dojo/view_test.html b/dojo/templates/dojo/view_test.html index 61015f2521..5ba5574134 100644 --- a/dojo/templates/dojo/view_test.html +++ b/dojo/templates/dojo/view_test.html @@ -1128,7 +1128,10 @@ <h4 class="has-filters"> {% if finding.file_path %} <i class="fa-solid fa-folder has-popover dojo-sup" data-trigger="hover" - data-content="{{ finding.file_path }}" + data-html="true" + data-content=" + {{ finding.file_path }}{% if finding.line %}:{{finding.line}}{% endif %} + " data-placement="right" data-container="body" data-original-title="Files" diff --git a/dojo/tools/checkmarx_one/parser.py b/dojo/tools/checkmarx_one/parser.py index d3ef4c77fd..381f705f82 100644 --- a/dojo/tools/checkmarx_one/parser.py +++ b/dojo/tools/checkmarx_one/parser.py @@ -1,9 +1,11 @@ import datetime import json +from typing import List from dateutil import parser +from django.conf import settings -from dojo.models import Finding +from dojo.models import Finding, Test class CheckmarxOneParser: @@ -24,116 +26,292 @@ def _parse_date(self, value): else: return None - def get_findings(self, file, test): - data = json.load(file) + def parse_vulnerabilities_from_scan_list( + self, + test: Test, + data: dict, + ) -> List[Finding]: findings = [] - if "vulnerabilities" in data: - results = data.get("vulnerabilities", []) - for result in results: - id = result.get("identifiers")[0].get("value") - cwe = None - if 'vulnerabilityDetails' in result: - cwe = result.get("vulnerabilites").get("cweId") - severity = result.get("severity") - locations_uri = result.get("location").get("file") - locations_startLine = result.get("location").get("start_line") - locations_endLine = result.get("location").get("end_line") - finding = Finding( - unique_id_from_tool=id, - file_path=locations_uri, - title=id + "_" + locations_uri, - test=test, - cwe=cwe, - severity=severity, - description="**id**: " + str(id) + "\n" - + "**uri**: " + locations_uri + "\n" - + "**startLine**: " + str(locations_startLine) + "\n" - + "**endLine**: " + str(locations_endLine) + "\n", - false_p=False, - duplicate=False, - out_of_scope=False, - static_finding=True, - dynamic_finding=False, - ) - findings.append(finding) - elif "results" in data: - results = data.get("results", []) - for vulnerability in results: - result_type = vulnerability.get("type") - date = self._parse_date(vulnerability.get("firstFoundAt")) - cwe = None - if 'vulnerabilityDetails' in vulnerability: - cwe = vulnerability.get("vulnerabilites", {}).get("cweId") - if result_type == "sast": - descriptionDetails = vulnerability.get("description") - file_path = vulnerability.get("data").get("nodes")[0].get("fileName") - finding = Finding( - description=descriptionDetails, - title=descriptionDetails, - file_path=file_path, - date=date, - cwe=cwe, - severity=vulnerability.get("severity").title(), - test=test, - static_finding=True, - ) - if vulnerability.get("id"): - finding.unique_id_from_tool = ( - vulnerability.get("id") - ) + cwe_store = data.get("vulnerabilityDetails", []) + # SAST + if (results := data.get("scanResults", {}).get("resultsList")) is not None: + findings += self.parse_sast_vulnerabilities(test, results, cwe_store) + # IaC + if (results := data.get("iacScanResults", {}).get("technology")) is not None: + findings += self.parse_iac_vulnerabilities(test, results, cwe_store) + # SCA + if (results := data.get("scaScanResults", {}).get("packages")) is not None: + findings += self.parse_sca_vulnerabilities(test, results, cwe_store) + return findings + + def parse_iac_vulnerabilities( + self, + test: Test, + results: list, + cwe_store: list, + ) -> List[Finding]: + findings = [] + for technology in results: + # Set the name aside for use in the title + name = technology.get("name", "IaC Finding") + for query in technology.get("queries", []): + # Set up some base findings to be used by each + # instance of the vulnerability + base_finding_details = { + "title": f"{name}: {query.get('queryName')}", + "description": ( + f"{query.get('description')}\n\n" + f"**Category**: {query.get('category')}\n"), + "verified": query.get("state") != "TO_VERIFY", + "test": test, + } + # Iterate over the individual issues + for instance in query.get("resultsList"): + # Set the date depending on the first seen flag + if settings.USE_FIRST_SEEN: + date = self._parse_date(instance.get("firstDetectionDate")) else: - finding.unique_id_from_tool = str( - vulnerability.get("similarityId") - ) - findings.append(finding) - elif result_type == "kics": - description = vulnerability.get("description") - file_path = vulnerability.get("data").get("filename", vulnerability.get("data").get("fileName")) + date = self._parse_date(instance.get("lastDetectionDate")) + # Create the finding object finding = Finding( - title=f'{description}', - description=description, + severity=instance.get("severity").title(), date=date, - cwe=cwe, - severity=vulnerability.get("severity").title(), - verified=vulnerability.get("state") != "TO_VERIFY", - file_path=file_path, - test=test, - static_finding=True, + file_path=instance.get("fileName"), + mitigation=( + f"**Actual Value**: {instance.get('actualValue')}\n" + f"**Expected Value**: {instance.get('expectedValue')}\n" + ), + **base_finding_details, ) - if vulnerability.get("id"): - finding.unique_id_from_tool = vulnerability.get( - "id" - ) - else: - finding.unique_id_from_tool = str( - vulnerability.get("similarityId") - ) - findings.append(finding) - elif result_type in ["sca", "sca-container"]: - description = vulnerability.get("description") - finding = Finding( - title=description, - description=description, - date=date, - severity=vulnerability.get("severity").title(), - verified=vulnerability.get("state") != "TO_VERIFY", - test=test, - cwe=cwe, - static_finding=True, + # Add some details to the description + finding.description += ( + f"**Issue Type**: {instance.get('issueType')}\n" + f"[View in Checkmarx One]({instance.get('resultViewerLink')})" ) - if vulnerability.get("cveId"): - finding.unsaved_vulnerability_ids = [ - vulnerability.get("cveId") - ] - if vulnerability.get("id"): - finding.unique_id_from_tool = vulnerability.get( - "id" - ) - else: - finding.unique_id_from_tool = str( - vulnerability.get("similarityId") - ) - finding.unsaved_tags = [result_type] + # Add at tag indicating what kind of finding this is + finding.unsaved_tags = ["iac"] + # Add the finding to the running list findings.append(finding) + return findings + + def parse_sca_vulnerabilities( + self, + test: Test, + results: list, + cwe_store: list, + ) -> List[Finding]: + # Not implemented yet + findings = [] + return findings + + def parse_sast_vulnerabilities( + self, + test: Test, + results: list, + cwe_store: list, + ) -> List[Finding]: + def get_cwe_store_entry(cwe_store: list, cwe: int) -> dict: + # Quick base case + if cwe is None: + return {} + # Iterate through the store to find a match + for entry in cwe_store: + if entry.get("cweId", 0) == cwe: + return entry + return {} + + def get_markdown_categories(categories: list) -> str: + value = "" + for category in categories: + value += f"- {category.get('name')}\n" + for sub_category in category.get("subCategories", []): + value += f"\t- {sub_category}\n" + return value + + def get_node_snippet(nodes: list) -> str: + formatted_nodes = [] + for node in nodes: + formatted_nodes.append( + f"**File Name**: {node.get('fileName')}\n" + f"**Method**: {node.get('method')}\n" + f"**Line**: {node.get('line')}\n" + f"**Code Snippet**: {node.get('code')}\n" + ) + return "\n---\n".join(formatted_nodes) + + findings = [] + for result in results: + # Get some info from the CWE + cwe = result.get("cweId") + cwe_info = get_cwe_store_entry(cwe_store, cwe) + # Set up some base findings to be used by each + # instance of the vulnerability + base_finding_details = { + "title": result.get( + "queryPath", result.get("queryName", "SAST Finding") + ).replace("_", " "), + "description": ( + f"{result.get('description')}\n\n" + f"{cwe_info.get('cause', '')}"), + "references": get_markdown_categories(result.get("categories", [])), + "impact": cwe_info.get("risk", ""), + "mitigation": cwe_info.get("generalRecommendations", ""), + "cwe": cwe, + "test": test, + } + # Iterate over the individual issues + for instance in result.get("vulnerabilities"): + # Set the date depending on the first seen flag + if settings.USE_FIRST_SEEN: + date = self._parse_date(instance.get("firstFoundDate")) + else: + date = self._parse_date(instance.get("foundDate")) + # Create the finding object + finding = Finding( + severity=instance.get("severity").title(), + date=date, + file_path=instance.get("destinationFileName"), + line=instance.get("destinationLine"), + verified=instance.get("state") != "TO_VERIFY", + **base_finding_details, + ) + # Add some details to the description + if node_snippet := get_node_snippet(instance.get("nodes", [])): + finding.description += f"\n---\n{node_snippet}" + # Add at tag indicating what kind of finding this is + finding.unsaved_tags = ["sast"] + # Add the finding to the running list + findings.append(finding) + return findings + + def parse_vulnerabilities( + self, + test: Test, + results: list, + ) -> List[Finding]: + findings = [] + for result in results: + id = result.get("identifiers")[0].get("value") + cwe = None + if 'vulnerabilityDetails' in result: + cwe = result.get("vulnerabilites").get("cweId") + severity = result.get("severity") + locations_uri = result.get("location").get("file") + locations_startLine = result.get("location").get("start_line") + locations_endLine = result.get("location").get("end_line") + finding = Finding( + unique_id_from_tool=id, + file_path=locations_uri, + line=locations_startLine, + title=id + "_" + locations_uri, + test=test, + cwe=cwe, + severity=severity, + description="**id**: " + str(id) + "\n" + + "**uri**: " + locations_uri + "\n" + + "**startLine**: " + str(locations_startLine) + "\n" + + "**endLine**: " + str(locations_endLine) + "\n", + false_p=False, + duplicate=False, + out_of_scope=False, + static_finding=True, + dynamic_finding=False, + ) + findings.append(finding) + return findings + + def parse_results( + self, + test: Test, + results: list, + ) -> List[Finding]: + findings = [] + for vulnerability in results: + result_type = vulnerability.get("type") + date = self._parse_date(vulnerability.get("firstFoundAt")) + cwe = vulnerability.get("vulnerabilityDetails", {}).get("cweId", None) + finding = None + if result_type == "sast": + finding = self.get_results_sast(test, vulnerability) + elif result_type == "kics": + finding = self.get_results_kics(test, vulnerability) + elif result_type in ["sca", "sca-container"]: + finding = self.get_results_sca(test, vulnerability) + # Make sure we have a finding before continuing + if finding is not None: + # Add the type of vulnerability as a tag + finding.date = date + finding.cwe = cwe + finding.unsaved_tags = [result_type] + findings.append(finding) + return findings + + def get_results_sast( + self, + test: Test, + vulnerability: dict, + ) -> Finding: + description = vulnerability.get("description") + file_path = vulnerability.get("data").get("nodes")[0].get("fileName") + unique_id_from_tool = vulnerability.get("id", vulnerability.get("similarityId")) + return Finding( + description=description, + title=description, + file_path=file_path, + severity=vulnerability.get("severity").title(), + test=test, + static_finding=True, + unique_id_from_tool=unique_id_from_tool, + ) + + def get_results_kics( + self, + test: Test, + vulnerability: dict, + ) -> Finding: + description = vulnerability.get("description") + file_path = vulnerability.get("data").get("filename", vulnerability.get("data").get("fileName")) + unique_id_from_tool = vulnerability.get("id", vulnerability.get("similarityId")) + return Finding( + title=description, + description=description, + severity=vulnerability.get("severity").title(), + verified=vulnerability.get("state") != "TO_VERIFY", + file_path=file_path, + test=test, + static_finding=True, + unique_id_from_tool=unique_id_from_tool, + ) + + def get_results_sca( + self, + test: Test, + vulnerability: dict, + ) -> Finding: + description = vulnerability.get("description") + unique_id_from_tool = vulnerability.get("id", vulnerability.get("similarityId")) + finding = Finding( + title=description, + description=description, + severity=vulnerability.get("severity").title(), + verified=vulnerability.get("state") != "TO_VERIFY", + test=test, + static_finding=True, + unique_id_from_tool=unique_id_from_tool, + ) + if (cveId := vulnerability.get("cveId")) is not None: + finding.unsaved_vulnerability_ids = [cveId] + + return finding + + def get_findings(self, file, test): + data = json.load(file) + findings = [] + if any(vuln_type in data for vuln_type in ["scaScanResults", "iacScanResults", "scanResults"]): + findings = self.parse_vulnerabilities_from_scan_list(test, data) + if (results := data.get("vulnerabilities", None)) is not None: + findings = self.parse_vulnerabilities(test, results) + elif (results := data.get("results", None)) is not None: + findings = self.parse_results(test, results) return findings diff --git a/unittests/scans/checkmarx_one/vulnerabilities_from_scan_results.json b/unittests/scans/checkmarx_one/vulnerabilities_from_scan_results.json new file mode 100644 index 0000000000..8d97d5dadb --- /dev/null +++ b/unittests/scans/checkmarx_one/vulnerabilities_from_scan_results.json @@ -0,0 +1,10627 @@ +{ + "reportCreationDate": "2024-04-16T19:34:28.216323985Z", + "reportType": "Vulnerability Type", + "reportHeader": { + "projectName": "example-123/loiskjdye", + "projectCreationDate": "2023-07-17T18:36:54.880332Z", + "tenantId": "75dc3d05-ba3b-4eb9-a335-ed37f5d63eb7", + "scanDate": "2024-04-16T14:31:48.251029Z", + "severityDistribution": [ + { + "level": "High", + "value": 3 + }, + { + "level": "Medium", + "value": 47 + }, + { + "level": "Low", + "value": 85 + }, + { + "level": "Information", + "value": 11 + } + ], + "scannedBranchName": "main", + "scanners": [ + "SAST", + "SCA", + "IaC" + ], + "mainBranch": "main" + }, + "reportFilters": { + "filters": [ + { + "filterName": "Severity", + "included": [ + "High", + "Medium", + "Low", + "Information" + ], + "excluded": [] + }, + { + "filterName": "Result State", + "included": [ + "To Verify", + "Not Exploitable", + "Proposed Not Exploitable", + "Confirmed", + "Urgent" + ], + "excluded": [] + }, + { + "filterName": "Status", + "included": [ + "New", + "Recurrent" + ], + "excluded": [] + }, + { + "filterName": "Scanners", + "included": [ + "SAST", + "SCA", + "IaC" + ], + "excluded": [] + } + ], + "resultsLimit": "10000" + }, + "scanInformation": { + "scanId": "7c9b4b8e-6986-4e5f-a787-f7d2c93e622a", + "scanInitiator": "user@example123.com", + "scanDuration": 503881212000, + "preset": "All", + "totalScannedLoc": 62306, + "scannedLoc": 59718, + "iacScannedLoc": 2588, + "totalScannedFiles": 709, + "scannedFiles": 673, + "iacScannedFiles": 36, + "viewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast", + "sourceOrigin": "github", + "scanType": "Full Scan", + "branch": "main", + "totalDensity": 2.34, + "density": 2.28, + "iacDensity": 3.86, + "groups": null, + "scanners": [ + "SAST", + "SCA", + "IaC" + ], + "scannerStatus": [ + { + "name": "SCA", + "status": "Completed" + }, + { + "name": "IaC", + "status": "Completed" + }, + { + "name": "SAST", + "status": "Completed" + } + ] + }, + "projectAndScanTags": { + "scanTags": null, + "projectTags": null + }, + "densityGrade": { + "totalResults": 146, + "loc": 62306, + "density": 2.34 + }, + "scannerOverview": { + "totalResults": 146, + "sastResults": { + "engine": "SAST", + "value": 136, + "percentage": 93.15 + }, + "iacResults": { + "engine": "IaC", + "value": 10, + "percentage": 6.85 + }, + "scaResults": { + "engine": "SCA", + "value": 0, + "percentage": 0 + } + }, + "statusOverview": { + "totalResults": 146, + "newResultsOverview": { + "numberOfResults": 0, + "percentage": 0 + }, + "recurrentResultsOverview": { + "numberOfResults": 146, + "percentage": 100 + } + }, + "stateOverview": { + "totalResults": 146, + "stateDistribution": [ + { + "state": "To Verify", + "numberOfResults": 146, + "percentage": 100, + "density": { + "value": 2.34 + } + }, + { + "state": "Not Exploitable", + "numberOfResults": 0, + "percentage": 0, + "density": { + "value": 0 + } + }, + { + "state": "Proposed Not Exploitable", + "numberOfResults": 0, + "percentage": 0, + "density": { + "value": 0 + } + }, + { + "state": "Confirmed", + "numberOfResults": 0, + "percentage": 0, + "density": { + "value": 0 + } + }, + { + "state": "Urgent", + "numberOfResults": 0, + "percentage": 0, + "density": { + "value": 0 + } + } + ] + }, + "languageOverview": [ + { + "languageName": "java", + "totalResults": 68, + "density": { + "value": 1.14 + }, + "severityBreakdown": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 57 + }, + { + "level": "Information", + "value": 11 + } + ] + }, + { + "languageName": "kotlin", + "totalResults": 38, + "density": { + "value": 0.64 + }, + "severityBreakdown": [ + { + "level": "High", + "value": 3 + }, + { + "level": "Medium", + "value": 11 + }, + { + "level": "Low", + "value": 24 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "languageName": "go", + "totalResults": 28, + "density": { + "value": 0.47 + }, + "severityBreakdown": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 25 + }, + { + "level": "Low", + "value": 3 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "languageName": "python", + "totalResults": 2, + "density": { + "value": 0.03 + }, + "severityBreakdown": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 2 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + } + ], + "technologyOverview": [ + { + "technologyName": "CICD", + "totalResults": 5, + "density": { + "value": 1.93 + }, + "severityBreakdown": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 5 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "technologyName": "Kubernetes", + "totalResults": 4, + "density": { + "value": 1.55 + }, + "severityBreakdown": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 4 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "technologyName": "Dockerfile", + "totalResults": 1, + "density": { + "value": 0.39 + }, + "severityBreakdown": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 1 + }, + { + "level": "Information", + "value": 0 + } + ] + } + ], + "packageOverview": [], + "severityOverview": { + "totalResults": 146, + "severitiesBreakdown": [ + { + "level": "High", + "value": 3, + "percentage": 2.05, + "density": { + "value": 0.05 + } + }, + { + "level": "Medium", + "value": 47, + "percentage": 32.19, + "density": { + "value": 0.75 + } + }, + { + "level": "Low", + "value": 85, + "percentage": 58.22, + "density": { + "value": 1.36 + } + }, + { + "level": "Information", + "value": 11, + "percentage": 7.53, + "density": { + "value": 0.18 + } + } + ] + }, + "vulnerabilitiesTable": { + "totals": { + "detectedFiles": 51, + "resultsDistribution": [ + { + "level": "High", + "value": 3 + }, + { + "level": "Medium", + "value": 38 + }, + { + "level": "Low", + "value": 84 + }, + { + "level": "Information", + "value": 11 + } + ] + }, + "vulnerabilityTypes": [ + { + "vulnerabilityType": "Reflected_XSS", + "severity": "High", + "detectedFiles": 8, + "resultsDistribution": [ + { + "level": "High", + "value": 3 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "Denial_Of_Service_Resource_Exhaustion", + "severity": "Medium", + "detectedFiles": 4, + "resultsDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 12 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "Client_Side_Injection", + "severity": "Medium", + "detectedFiles": 18, + "resultsDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 10 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "Reflected_Absolute_Path_Traversal", + "severity": "Medium", + "detectedFiles": 4, + "resultsDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 4 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "Reflected_Relative_Path_Traversal", + "severity": "Medium", + "detectedFiles": 4, + "resultsDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 4 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "SSRF", + "severity": "Medium", + "detectedFiles": 2, + "resultsDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 4 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "Unchecked_Input_for_Loop_Condition", + "severity": "Medium", + "detectedFiles": 1, + "resultsDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 2 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "SSL_Verification_Bypass", + "severity": "Medium", + "detectedFiles": 1, + "resultsDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 1 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "Unchecked_Input_for_Loop_Condition", + "severity": "Medium", + "detectedFiles": 1, + "resultsDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 1 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "TruffleHog_HighEntropy_Strings", + "severity": "Low", + "detectedFiles": 15, + "resultsDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 56 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "Use_of_Non_Cryptographic_Random", + "severity": "Low", + "detectedFiles": 6, + "resultsDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 23 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "Improper_Error_Handling", + "severity": "Low", + "detectedFiles": 2, + "resultsDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 2 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "Deprecated_API", + "severity": "Low", + "detectedFiles": 1, + "resultsDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 1 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "Missing_Rooted_Device_Check", + "severity": "Low", + "detectedFiles": 1, + "resultsDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 1 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "TruffleHog_Regex_Matches", + "severity": "Low", + "detectedFiles": 1, + "resultsDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 1 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "Potentially_Serializable_Class_With_Sensitive_Data", + "severity": "Information", + "detectedFiles": 1, + "resultsDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 6 + } + ] + }, + { + "vulnerabilityType": "Incorrect_Block_Delimitation", + "severity": "Information", + "detectedFiles": 1, + "resultsDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 3 + } + ] + }, + { + "vulnerabilityType": "Incorrect_Conversion_between_Numeric_Types", + "severity": "Information", + "detectedFiles": 1, + "resultsDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 2 + } + ] + } + ] + }, + "topTenVulnerabilities": { + "vulnerableFiles": 51, + "totalVulnerabilities": 125, + "vulnerabilitiesList": [ + { + "vulnerabilityType": "TruffleHog_HighEntropy_Strings", + "total": 56, + "vulnerabilitySeverities": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 56 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "Use_of_Non_Cryptographic_Random", + "total": 23, + "vulnerabilitySeverities": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 23 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "Denial_Of_Service_Resource_Exhaustion", + "total": 12, + "vulnerabilitySeverities": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 12 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "Client_Side_Injection", + "total": 10, + "vulnerabilitySeverities": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 10 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "Potentially_Serializable_Class_With_Sensitive_Data", + "total": 6, + "vulnerabilitySeverities": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 6 + } + ] + }, + { + "vulnerabilityType": "Reflected_Absolute_Path_Traversal", + "total": 4, + "vulnerabilitySeverities": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 4 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "Reflected_Relative_Path_Traversal", + "total": 4, + "vulnerabilitySeverities": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 4 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "SSRF", + "total": 4, + "vulnerabilitySeverities": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 4 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "Reflected_XSS", + "total": 3, + "vulnerabilitySeverities": [ + { + "level": "High", + "value": 3 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "vulnerabilityType": "Incorrect_Block_Delimitation", + "total": 3, + "vulnerabilitySeverities": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 3 + } + ] + } + ] + }, + "topTenVulnerableFiles": { + "vulnerableFiles": 51, + "totalFiles": 673, + "vulnerableFilesList": [ + { + "fileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "total": 13, + "fileSeverities": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 13 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "total": 12, + "fileSeverities": [ + { + "level": "High", + "value": 3 + }, + { + "level": "Medium", + "value": 9 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "total": 11, + "fileSeverities": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 10 + }, + { + "level": "Low", + "value": 1 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "total": 11, + "fileSeverities": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 9 + }, + { + "level": "Low", + "value": 2 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/repository/CustomerRepository.kt", + "total": 8, + "fileSeverities": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 8 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/s.kt", + "total": 8, + "fileSeverities": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 8 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "fileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/ecommerce/c.kt", + "total": 7, + "fileSeverities": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 7 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "fileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/c.kt", + "total": 7, + "fileSeverities": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 7 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/c.kt", + "total": 6, + "fileSeverities": [ + { + "level": "High", + "value": 3 + }, + { + "level": "Medium", + "value": 3 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/c.kt", + "total": 6, + "fileSeverities": [ + { + "level": "High", + "value": 3 + }, + { + "level": "Medium", + "value": 3 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + } + ] + }, + "topFiveOldestBySeverity": [ + { + "level": "High", + "vulnerabilitiesDistribution": [ + { + "vulnerabilityType": "Reflected_XSS", + "age": 28 + } + ] + }, + { + "level": "Medium", + "vulnerabilitiesDistribution": [ + { + "vulnerabilityType": "Client_Side_Injection", + "age": 46 + }, + { + "vulnerabilityType": "Denial_Of_Service_Resource_Exhaustion", + "age": 46 + }, + { + "vulnerabilityType": "Reflected_Absolute_Path_Traversal", + "age": 46 + }, + { + "vulnerabilityType": "Reflected_Relative_Path_Traversal", + "age": 46 + }, + { + "vulnerabilityType": "SSL_Verification_Bypass", + "age": 46 + } + ] + }, + { + "level": "Low", + "vulnerabilitiesDistribution": [ + { + "vulnerabilityType": "Deprecated_API", + "age": 46 + }, + { + "vulnerabilityType": "Improper_Error_Handling", + "age": 46 + }, + { + "vulnerabilityType": "Missing_Rooted_Device_Check", + "age": 46 + }, + { + "vulnerabilityType": "TruffleHog_HighEntropy_Strings", + "age": 46 + }, + { + "vulnerabilityType": "TruffleHog_Regex_Matches", + "age": 46 + } + ] + }, + { + "level": "Information", + "vulnerabilitiesDistribution": [ + { + "vulnerabilityType": "Potentially_Serializable_Class_With_Sensitive_Data", + "age": 42 + }, + { + "vulnerabilityType": "Incorrect_Block_Delimitation", + "age": 23 + }, + { + "vulnerabilityType": "Incorrect_Conversion_between_Numeric_Types", + "age": 23 + } + ] + } + ], + "scanResults": { + "totalResults": 136, + "severitiesBreakdown": [ + { + "level": "High", + "value": 3 + }, + { + "level": "Medium", + "value": 38 + }, + { + "level": "Low", + "value": 84 + }, + { + "level": "Information", + "value": 11 + } + ], + "resultsList": [ + { + "queryName": "Reflected_XSS", + "queryDescriptionLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast/description/79/9349880549689768000", + "queryId": 9349880549689768000, + "description": "The method @DestinationMethod embeds untrusted data in generated output with @DestinationElement, at line @DestinationLine of @DestinationFile. This untrusted data is embedded into the output without proper sanitization or encoding, enabling an attacker to inject malicious code into the generated web-page.\n\nThe attacker would be able to alter the returned web page by simply providing modified data in the user input @SourceElement, which is read by the @SourceMethod method at line @SourceLine of @SourceFile. This input then flows through the code straight to the output web page, without sanitization. \r\n\r\nThis can enable a Reflected Cross-Site Scripting (XSS) attack.\n\n", + "vulnerabilitiesTotal": 3, + "queryPath": "Kotlin/Kotlin_High_Risk/Reflected_XSS", + "cweId": 79, + "categories": [ + { + "name": "SANS top 25", + "subCategories": [ + "SANS top 25" + ] + }, + { + "name": "CWE top 25", + "subCategories": [ + "CWE top 25" + ] + }, + { + "name": "MOIS(KISA) Secure Coding 2021", + "subCategories": [ + "MOIS(KISA) Verification and representation of input data" + ] + }, + { + "name": "OWASP ASVS", + "subCategories": [ + "V05 Validation, Sanitization and Encoding" + ] + }, + { + "name": "OWASP Top 10 2021", + "subCategories": [ + "A3-Injection" + ] + } + ], + "vulnerabilities": [ + { + "similarityId": 134962663, + "status": "Recurrent", + "state": "To Verify", + "severity": "High", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-18T20:51:25Z", + "sourceFileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "destinationFileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "sourceNode": "s", + "destinationNode": "set", + "sourceMethod": "putCustomer", + "destinationMethod": "Lambda", + "sourceLine": 69, + "sourceCode": "@RequestBody s: S", + "destinationLine": 484, + "destinationCode": "this.origins[it] = OriginPriority(cpf = originFromNewValue)", + "nodes": [ + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "method": "putCustomer", + "node": "s", + "line": 71, + "code": "val customer = customerService.createOrUpdateCustomer(s)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/CustomerService.kt", + "method": "createOrUpdateCustomer", + "node": "customerAccountCommand", + "line": 24, + "code": "fun createOrUpdateCustomer(customerAccountCommand: S): Customer? {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/CustomerService.kt", + "method": "createOrUpdateCustomer", + "node": "customerAccountCommand", + "line": 26, + "code": "return eventHandler.executeAccountEvent(customerAccountCommand)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "executeAccountEvent", + "node": "eventCommand", + "line": 56, + "code": "fun executeAccountEvent(eventCommand: EventCommand): Customer? =" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "executeAccountEvent", + "node": "eventCommand", + "line": 57, + "code": "createOrUpdateCustomerByEvent(eventCommand.toDomain())" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "toDomain", + "node": "buildAccountUpdated", + "line": 101, + "code": "buildAccountUpdated().also {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "buildAccountUpdated", + "node": "additionalInfo", + "line": 134, + "code": "additionalInfo = additionalInfo," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/event/base/D.kt", + "method": "D", + "node": "additionalInfo", + "line": 42, + "code": "val additionalInfo: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/event/base/D.kt", + "method": "D", + "node": "additionalInfo", + "line": 42, + "code": "val additionalInfo: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/event/base/D.kt", + "method": "D", + "node": "additionalInfo", + "line": 42, + "code": "val additionalInfo: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "buildAccountUpdated", + "node": "D", + "line": 112, + "code": "D(" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "toDomain", + "node": "buildAccountUpdated", + "line": 101, + "code": "buildAccountUpdated().also {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "toDomain", + "node": "also", + "line": 101, + "code": "buildAccountUpdated().also {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "executeAccountEvent", + "node": "toDomain", + "line": 57, + "code": "createOrUpdateCustomerByEvent(eventCommand.toDomain())" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "createOrUpdateCustomerByEvent", + "node": "iEvent", + "line": 63, + "code": "fun createOrUpdateCustomerByEvent(iEvent: IEvent): Customer? {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "createOrUpdateCustomerByEvent", + "node": "iEvent", + "line": 72, + "code": "customerFromEventService.update(customer, iEvent)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "update", + "node": "iEvent", + "line": 48, + "code": "fun update(customer: Customer, iEvent: IEvent): Customer? =" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "update", + "node": "iEvent", + "line": 53, + "code": "val customerUpdated = customer.updateCustomerBy(iEvent)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateCustomerBy", + "node": "iEvent", + "line": 268, + "code": "fun updateCustomerBy(iEvent: IEvent, registerEvent: Boolean = true): Customer {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateCustomerBy", + "node": "iEvent", + "line": 269, + "code": "updateIdentityKeys(iEvent.identityKeys(), iEvent.company, iEvent.origin)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateCustomerBy", + "node": "company", + "line": 269, + "code": "updateIdentityKeys(iEvent.identityKeys(), iEvent.company, iEvent.origin)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateIdentityKeys", + "node": "company", + "line": 514, + "code": "company: Company," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateIdentityKeys", + "node": "company", + "line": 519, + "code": "EmailBU.fromString(identityKey.email, company)," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/EmailBU.kt", + "method": "fromString", + "node": "company", + "line": 15, + "code": "fun fromString(email: String?, company: Company? = Company.CENTAURO): EmailBU? {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/EmailBU.kt", + "method": "fromString", + "node": "company", + "line": 19, + "code": "EmailBU(emailLowerCase, company)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/EmailBU.kt", + "method": "EmailBU", + "node": "company", + "line": 10, + "code": "val company: Company? = Company.CENTAURO" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/EmailBU.kt", + "method": "EmailBU", + "node": "company", + "line": 10, + "code": "val company: Company? = Company.CENTAURO" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/EmailBU.kt", + "method": "EmailBU", + "node": "company", + "line": 10, + "code": "val company: Company? = Company.CENTAURO" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/EmailBU.kt", + "method": "fromString", + "node": "EmailBU", + "line": 19, + "code": "EmailBU(emailLowerCase, company)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateIdentityKeys", + "node": "fromString", + "line": 519, + "code": "EmailBU.fromString(identityKey.email, company)," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateEmailByPriority", + "node": "newValue", + "line": 446, + "code": "private fun updateEmailByPriority(newValue: EmailBU?, originFromNewValue: Origin?) {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateEmailByPriority", + "node": "newValue", + "line": 448, + "code": "updateEmailAtCompany(newValue, originFromNewValue)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateEmailAtCompany", + "node": "newValue", + "line": 453, + "code": "newValue: EmailBU," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateEmailAtCompany", + "node": "newValue", + "line": 463, + "code": "this.origins[newValue.company] = OriginPriority(email = originFromNewValue)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateEmailAtCompany", + "node": "company", + "line": 463, + "code": "this.origins[newValue.company] = OriginPriority(email = originFromNewValue)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateEmailAtCompany", + "node": "set", + "line": 463, + "code": "this.origins[newValue.company] = OriginPriority(email = originFromNewValue)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateEmailAtCompany", + "node": "origins", + "line": 463, + "code": "this.origins[newValue.company] = OriginPriority(email = originFromNewValue)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateEmailByPriority", + "node": "updateEmailAtCompany", + "line": 448, + "code": "updateEmailAtCompany(newValue, originFromNewValue)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateIdentityKeys", + "node": "updateEmailByPriority", + "line": 518, + "code": "updateEmailByPriority(" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateIdentityKeys", + "node": "updateCPFByPriority", + "line": 522, + "code": "updateCPFByPriority(CPF.fromString(identityKey.cpf), origin, listOf(company))" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "Lambda", + "node": "Lambda", + "line": 482, + "code": "newCompanies.forEach {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "Lambda", + "node": "origins", + "line": 483, + "code": "if (this.origins[it] == null) {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "Lambda", + "node": "origins", + "line": 484, + "code": "this.origins[it] = OriginPriority(cpf = originFromNewValue)" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=3BDddUN89yPXUzjbQ%2FLSowTsplU%3D", + "firstScanID": "615ff822-f6ed-4e30-aeed-f5618ef09ca2", + "notes": [] + }, + { + "similarityId": 134962663, + "status": "Recurrent", + "state": "To Verify", + "severity": "High", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-18T20:51:25Z", + "sourceFileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "destinationFileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "sourceNode": "s", + "destinationNode": "set", + "sourceMethod": "putCustomer", + "destinationMethod": "Lambda", + "sourceLine": 69, + "sourceCode": "@RequestBody s: S", + "destinationLine": 504, + "destinationCode": "this.origins[it] = OriginPriority(cpf = originFromNewValue)", + "nodes": [ + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "method": "putCustomer", + "node": "s", + "line": 71, + "code": "val customer = customerService.createOrUpdateCustomer(s)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/CustomerService.kt", + "method": "createOrUpdateCustomer", + "node": "customerAccountCommand", + "line": 24, + "code": "fun createOrUpdateCustomer(customerAccountCommand: S): Customer? {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/CustomerService.kt", + "method": "createOrUpdateCustomer", + "node": "customerAccountCommand", + "line": 26, + "code": "return eventHandler.executeAccountEvent(customerAccountCommand)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "executeAccountEvent", + "node": "eventCommand", + "line": 56, + "code": "fun executeAccountEvent(eventCommand: EventCommand): Customer? =" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "executeAccountEvent", + "node": "eventCommand", + "line": 57, + "code": "createOrUpdateCustomerByEvent(eventCommand.toDomain())" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/c.kt", + "method": "toDomain", + "node": "buildAccountUpdated", + "line": 101, + "code": "buildAccountUpdated().also {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "buildAccountUpdated", + "node": "additionalInfo", + "line": 134, + "code": "additionalInfo = additionalInfo," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/event/base/D.kt", + "method": "D", + "node": "additionalInfo", + "line": 42, + "code": "val additionalInfo: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/event/base/D.kt", + "method": "D", + "node": "additionalInfo", + "line": 42, + "code": "val additionalInfo: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/event/base/D.kt", + "method": "D", + "node": "additionalInfo", + "line": 42, + "code": "val additionalInfo: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "buildAccountUpdated", + "node": "D", + "line": 112, + "code": "D(" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "toDomain", + "node": "buildAccountUpdated", + "line": 101, + "code": "buildAccountUpdated().also {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "toDomain", + "node": "also", + "line": 101, + "code": "buildAccountUpdated().also {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "executeAccountEvent", + "node": "toDomain", + "line": 57, + "code": "createOrUpdateCustomerByEvent(eventCommand.toDomain())" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "createOrUpdateCustomerByEvent", + "node": "iEvent", + "line": 63, + "code": "fun createOrUpdateCustomerByEvent(iEvent: IEvent): Customer? {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "createOrUpdateCustomerByEvent", + "node": "iEvent", + "line": 72, + "code": "customerFromEventService.update(customer, iEvent)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "update", + "node": "iEvent", + "line": 48, + "code": "fun update(customer: Customer, iEvent: IEvent): Customer? =" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "update", + "node": "iEvent", + "line": 53, + "code": "val customerUpdated = customer.updateCustomerBy(iEvent)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateCustomerBy", + "node": "iEvent", + "line": 268, + "code": "fun updateCustomerBy(iEvent: IEvent, registerEvent: Boolean = true): Customer {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateCustomerBy", + "node": "iEvent", + "line": 269, + "code": "updateIdentityKeys(iEvent.identityKeys(), iEvent.company, iEvent.origin)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateCustomerBy", + "node": "company", + "line": 269, + "code": "updateIdentityKeys(iEvent.identityKeys(), iEvent.company, iEvent.origin)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateIdentityKeys", + "node": "company", + "line": 514, + "code": "company: Company," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateIdentityKeys", + "node": "company", + "line": 519, + "code": "EmailBU.fromString(identityKey.email, company)," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/EmailBU.kt", + "method": "fromString", + "node": "company", + "line": 15, + "code": "fun fromString(email: String?, company: Company? = Company.CENTAURO): EmailBU? {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/EmailBU.kt", + "method": "fromString", + "node": "company", + "line": 19, + "code": "EmailBU(emailLowerCase, company)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/EmailBU.kt", + "method": "EmailBU", + "node": "company", + "line": 10, + "code": "val company: Company? = Company.CENTAURO" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/EmailBU.kt", + "method": "EmailBU", + "node": "company", + "line": 10, + "code": "val company: Company? = Company.CENTAURO" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/EmailBU.kt", + "method": "EmailBU", + "node": "company", + "line": 10, + "code": "val company: Company? = Company.CENTAURO" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/EmailBU.kt", + "method": "fromString", + "node": "EmailBU", + "line": 19, + "code": "EmailBU(emailLowerCase, company)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateIdentityKeys", + "node": "fromString", + "line": 519, + "code": "EmailBU.fromString(identityKey.email, company)," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateEmailByPriority", + "node": "newValue", + "line": 446, + "code": "private fun updateEmailByPriority(newValue: EmailBU?, originFromNewValue: Origin?) {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateEmailByPriority", + "node": "newValue", + "line": 448, + "code": "updateEmailAtCompany(newValue, originFromNewValue)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateEmailAtCompany", + "node": "newValue", + "line": 453, + "code": "newValue: EmailBU," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateEmailAtCompany", + "node": "newValue", + "line": 463, + "code": "this.origins[newValue.company] = OriginPriority(email = originFromNewValue)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateEmailAtCompany", + "node": "company", + "line": 463, + "code": "this.origins[newValue.company] = OriginPriority(email = originFromNewValue)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateEmailAtCompany", + "node": "set", + "line": 463, + "code": "this.origins[newValue.company] = OriginPriority(email = originFromNewValue)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateEmailAtCompany", + "node": "origins", + "line": 463, + "code": "this.origins[newValue.company] = OriginPriority(email = originFromNewValue)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateEmailByPriority", + "node": "updateEmailAtCompany", + "line": 448, + "code": "updateEmailAtCompany(newValue, originFromNewValue)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateIdentityKeys", + "node": "updateEmailByPriority", + "line": 518, + "code": "updateEmailByPriority(" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateIdentityKeys", + "node": "updateCNPJByPriority", + "line": 523, + "code": "updateCNPJByPriority(CNPJ.fromString(identityKey.cnpj), origin, listOf(company))" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "Lambda", + "node": "Lambda", + "line": 502, + "code": "newCompanies.forEach {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "Lambda", + "node": "origins", + "line": 503, + "code": "if (this.origins[it] == null) {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "Lambda", + "node": "origins", + "line": 504, + "code": "this.origins[it] = OriginPriority(cpf = originFromNewValue)" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=4hxOgYKZUJPRAlodgeAXgj4UMjI%3D", + "firstScanID": "615ff822-f6ed-4e30-aeed-f5618ef09ca2", + "notes": [] + }, + { + "similarityId": -1944555408, + "status": "Recurrent", + "state": "To Verify", + "severity": "High", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-18T20:51:25Z", + "sourceFileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "destinationFileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "sourceNode": "s", + "destinationNode": "set", + "sourceMethod": "putCustomer", + "destinationMethod": "updateVisitantId", + "sourceLine": 69, + "sourceCode": "@RequestBody s: S", + "destinationLine": 602, + "destinationCode": "this.visitantId[companyNewValue] = visitantIdNewValue", + "nodes": [ + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "method": "putCustomer", + "node": "s", + "line": 71, + "code": "val customer = customerService.createOrUpdateCustomer(s)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/CustomerService.kt", + "method": "createOrUpdateCustomer", + "node": "customerAccountCommand", + "line": 24, + "code": "fun createOrUpdateCustomer(customerAccountCommand: S): Customer? {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/CustomerService.kt", + "method": "createOrUpdateCustomer", + "node": "customerAccountCommand", + "line": 26, + "code": "return eventHandler.executeAccountEvent(customerAccountCommand)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "executeAccountEvent", + "node": "eventCommand", + "line": 56, + "code": "fun executeAccountEvent(eventCommand: EventCommand): Customer? =" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "executeAccountEvent", + "node": "eventCommand", + "line": 57, + "code": "createOrUpdateCustomerByEvent(eventCommand.toDomain())" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "toDomain", + "node": "buildAccountUpdated", + "line": 101, + "code": "buildAccountUpdated().also {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "buildAccountUpdated", + "node": "additionalInfo", + "line": 134, + "code": "additionalInfo = additionalInfo," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/event/base/D.kt", + "method": "D", + "node": "additionalInfo", + "line": 42, + "code": "val additionalInfo: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/event/base/D.kt", + "method": "D", + "node": "additionalInfo", + "line": 42, + "code": "val additionalInfo: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/event/base/D.kt", + "method": "D", + "node": "additionalInfo", + "line": 42, + "code": "val additionalInfo: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "buildAccountUpdated", + "node": "D", + "line": 112, + "code": "D(" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "toDomain", + "node": "buildAccountUpdated", + "line": 101, + "code": "buildAccountUpdated().also {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "toDomain", + "node": "also", + "line": 101, + "code": "buildAccountUpdated().also {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "executeAccountEvent", + "node": "toDomain", + "line": 57, + "code": "createOrUpdateCustomerByEvent(eventCommand.toDomain())" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "createOrUpdateCustomerByEvent", + "node": "iEvent", + "line": 63, + "code": "fun createOrUpdateCustomerByEvent(iEvent: IEvent): Customer? {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "createOrUpdateCustomerByEvent", + "node": "iEvent", + "line": 72, + "code": "customerFromEventService.update(customer, iEvent)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "update", + "node": "iEvent", + "line": 48, + "code": "fun update(customer: Customer, iEvent: IEvent): Customer? =" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "update", + "node": "iEvent", + "line": 53, + "code": "val customerUpdated = customer.updateCustomerBy(iEvent)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateCustomerBy", + "node": "iEvent", + "line": 268, + "code": "fun updateCustomerBy(iEvent: IEvent, registerEvent: Boolean = true): Customer {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateCustomerBy", + "node": "iEvent", + "line": 269, + "code": "updateIdentityKeys(iEvent.identityKeys(), iEvent.company, iEvent.origin)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateCustomerBy", + "node": "iEvent", + "line": 270, + "code": "updateAnonymousIds(iEvent.anonymousKeys())" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateCustomerBy", + "node": "iEvent", + "line": 275, + "code": "OriginIdentifyType.ACCOUNT, iEvent.customerOriginId()" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateCustomerBy", + "node": "iEvent", + "line": 274, + "code": "iEvent.company, iEvent.origin," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateCustomerBy", + "node": "company", + "line": 274, + "code": "iEvent.company, iEvent.origin," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateOriginCustomerIds", + "node": "company", + "line": 527, + "code": "company: Company," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateOriginCustomerIds", + "node": "company", + "line": 542, + "code": "Origin.SELLER -\u003e updateVisitantId(company, originId)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateVisitantId", + "node": "companyNewValue", + "line": 600, + "code": "private fun updateVisitantId(companyNewValue: Company, visitantIdNewValue: String?) {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/Customer.kt", + "method": "updateVisitantId", + "node": "companyNewValue", + "line": 602, + "code": "this.visitantId[companyNewValue] = visitantIdNewValue" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=PXy3jmxaCbAgjj2gcbAzatJ96Hs%3D", + "firstScanID": "35394c18-dd17-45cd-9667-56f631c879de", + "notes": [] + } + ] + }, + { + "queryName": "Client_Side_Injection", + "queryDescriptionLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast/description/89/3348175923312480217", + "queryId": 3348175923312480217, + "description": "The application's @DestinationMethod method executes an SQL query with @DestinationElement, at line @DestinationLine of @DestinationFile. The application constructs this SQL query by embedding an untrusted string into the query without proper sanitization. The concatenated string is submitted to the database, where it is parsed and executed accordingly.\n\n", + "vulnerabilitiesTotal": 10, + "queryPath": "Kotlin/Kotlin_Android/Client_Side_Injection", + "cweId": 89, + "categories": [], + "vulnerabilities": [ + { + "similarityId": 971992247, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-04-13T00:30:34Z", + "sourceFileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "destinationFileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/repository/CustomerRepository.kt", + "sourceNode": "businessUnit", + "destinationNode": "company", + "sourceMethod": "getCustomerByEcommerceCustomerId", + "destinationMethod": "findByEcommerceCustomerId", + "sourceLine": 116, + "sourceCode": "@RequestParam businessUnit: Company?,", + "destinationLine": 78, + "destinationCode": "@Param(\"company\") company: Company,", + "nodes": [ + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "method": "getCustomerByEcommerceCustomerId", + "node": "businessUnit", + "line": 120, + "code": "val company = businessUnit ?: Company.CENTAURO" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "method": "getCustomerByEcommerceCustomerId", + "node": "company", + "line": 120, + "code": "val company = businessUnit ?: Company.CENTAURO" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "method": "getCustomerByEcommerceCustomerId", + "node": "company", + "line": 121, + "code": "val person = personService.findByEcommerceId(company, ecommerceCustomerId)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findByEcommerceId", + "node": "businessUnit", + "line": 62, + "code": "fun findByEcommerceId(businessUnit: Company, ecommerceCustomerId: String): Person? {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findByEcommerceId", + "node": "businessUnit", + "line": 65, + "code": "company = businessUnit, origin = Origin.ECOMMERCE," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/PlatformCustomerId.kt", + "method": "PlatformCustomerId", + "node": "company", + "line": 9, + "code": "val company: Company = Company.CENTAURO," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/PlatformCustomerId.kt", + "method": "PlatformCustomerId", + "node": "company", + "line": 9, + "code": "val company: Company = Company.CENTAURO," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/PlatformCustomerId.kt", + "method": "PlatformCustomerId", + "node": "company", + "line": 9, + "code": "val company: Company = Company.CENTAURO," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findByEcommerceId", + "node": "PlatformCustomerId", + "line": 64, + "code": "PlatformCustomerId(" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByCustomerOriginId", + "node": "platformCustomerId", + "line": 99, + "code": "platformCustomerId: PlatformCustomerId" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "Lambda", + "node": "platformCustomerId", + "line": 103, + "code": ".ifEmpty { getCustomerByOriginIdInOldestKeys(platformCustomerId) }," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "getCustomerByOriginIdInOldestKeys", + "node": "platformCustomerId", + "line": 118, + "code": "platformCustomerId: PlatformCustomerId" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "getCustomerByOriginIdInOldestKeys", + "node": "platformCustomerId", + "line": 122, + "code": "platformCustomerId.company, platformCustomerId.value" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "getCustomerByOriginIdInOldestKeys", + "node": "company", + "line": 122, + "code": "platformCustomerId.company, platformCustomerId.value" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=XaGZsSNXXRRS917HcYQX%2BCamGkY%3D", + "firstScanID": "42f633e0-baee-4312-9283-7b189e76450f", + "notes": [] + }, + { + "similarityId": 1127975448, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-04-13T00:30:34Z", + "sourceFileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "destinationFileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/repository/CustomerRepository.kt", + "sourceNode": "businessUnit", + "destinationNode": "company", + "sourceMethod": "getCustomerByEcommerceCustomerId", + "destinationMethod": "findByStoreCustomerId", + "sourceLine": 116, + "sourceCode": "@RequestParam businessUnit: Company?,", + "destinationLine": 84, + "destinationCode": "@Param(\"company\") company: Company,", + "nodes": [ + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "method": "getCustomerByEcommerceCustomerId", + "node": "businessUnit", + "line": 120, + "code": "val company = businessUnit ?: Company.CENTAURO" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "method": "getCustomerByEcommerceCustomerId", + "node": "company", + "line": 120, + "code": "val company = businessUnit ?: Company.CENTAURO" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "method": "getCustomerByEcommerceCustomerId", + "node": "company", + "line": 121, + "code": "val person = personService.findByEcommerceId(company, ecommerceCustomerId)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findByEcommerceId", + "node": "businessUnit", + "line": 62, + "code": "fun findByEcommerceId(businessUnit: Company, ecommerceCustomerId: String): Person? {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findByEcommerceId", + "node": "businessUnit", + "line": 65, + "code": "company = businessUnit, origin = Origin.ECOMMERCE," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/PlatformCustomerId.kt", + "method": "PlatformCustomerId", + "node": "company", + "line": 9, + "code": "val company: Company = Company.CENTAURO," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/PlatformCustomerId.kt", + "method": "PlatformCustomerId", + "node": "company", + "line": 9, + "code": "val company: Company = Company.CENTAURO," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/PlatformCustomerId.kt", + "method": "PlatformCustomerId", + "node": "company", + "line": 9, + "code": "val company: Company = Company.CENTAURO," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findByEcommerceId", + "node": "PlatformCustomerId", + "line": 64, + "code": "PlatformCustomerId(" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByCustomerOriginId", + "node": "platformCustomerId", + "line": 99, + "code": "platformCustomerId: PlatformCustomerId" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "Lambda", + "node": "platformCustomerId", + "line": 103, + "code": ".ifEmpty { getCustomerByOriginIdInOldestKeys(platformCustomerId) }," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "getCustomerByOriginIdInOldestKeys", + "node": "platformCustomerId", + "line": 118, + "code": "platformCustomerId: PlatformCustomerId" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "getCustomerByOriginIdInOldestKeys", + "node": "platformCustomerId", + "line": 126, + "code": "platformCustomerId.company, platformCustomerId.value" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "getCustomerByOriginIdInOldestKeys", + "node": "company", + "line": 126, + "code": "platformCustomerId.company, platformCustomerId.value" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=wJNF%2FMS5geO7GQiOMH7q3B6fQII%3D", + "firstScanID": "42f633e0-baee-4312-9283-7b189e76450f", + "notes": [] + }, + { + "similarityId": 558570014, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-04-13T00:30:34Z", + "sourceFileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "destinationFileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/repository/CustomerRepository.kt", + "sourceNode": "businessUnit", + "destinationNode": "company", + "sourceMethod": "getCustomerByEcommerceCustomerId", + "destinationMethod": "findByPlatformCustomerId", + "sourceLine": 116, + "sourceCode": "@RequestParam businessUnit: Company?,", + "destinationLine": 70, + "destinationCode": "@Param(\"company\") company: Company,", + "nodes": [ + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "method": "getCustomerByEcommerceCustomerId", + "node": "businessUnit", + "line": 120, + "code": "val company = businessUnit ?: Company.CENTAURO" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "method": "getCustomerByEcommerceCustomerId", + "node": "company", + "line": 120, + "code": "val company = businessUnit ?: Company.CENTAURO" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "method": "getCustomerByEcommerceCustomerId", + "node": "company", + "line": 121, + "code": "val person = personService.findByEcommerceId(company, ecommerceCustomerId)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findByEcommerceId", + "node": "businessUnit", + "line": 62, + "code": "fun findByEcommerceId(businessUnit: Company, ecommerceCustomerId: String): Person? {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findByEcommerceId", + "node": "businessUnit", + "line": 65, + "code": "company = businessUnit, origin = Origin.ECOMMERCE," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/PlatformCustomerId.kt", + "method": "PlatformCustomerId", + "node": "company", + "line": 9, + "code": "val company: Company = Company.CENTAURO," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/PlatformCustomerId.kt", + "method": "PlatformCustomerId", + "node": "company", + "line": 9, + "code": "val company: Company = Company.CENTAURO," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/PlatformCustomerId.kt", + "method": "PlatformCustomerId", + "node": "company", + "line": 9, + "code": "val company: Company = Company.CENTAURO," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findByEcommerceId", + "node": "PlatformCustomerId", + "line": 64, + "code": "PlatformCustomerId(" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByCustomerOriginId", + "node": "platformCustomerId", + "line": 99, + "code": "platformCustomerId: PlatformCustomerId" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByCustomerOriginId", + "node": "platformCustomerId", + "line": 102, + "code": "findByPlatformCustomerId(platformCustomerId)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByPlatformCustomerId", + "node": "platformCustomerId", + "line": 108, + "code": "platformCustomerId: PlatformCustomerId" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByPlatformCustomerId", + "node": "platformCustomerId", + "line": 111, + "code": "platformCustomerId.company," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByPlatformCustomerId", + "node": "company", + "line": 111, + "code": "platformCustomerId.company," + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=fBI8BXCRIX9gfKGhGBCzwLZNiq0%3D", + "firstScanID": "42f633e0-baee-4312-9283-7b189e76450f", + "notes": [] + }, + { + "similarityId": -204318717, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-18T20:51:25Z", + "sourceFileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "destinationFileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/repository/CustomerRepository.kt", + "sourceNode": "s", + "destinationNode": "company", + "sourceMethod": "putCustomer", + "destinationMethod": "findByEcommerceCustomerId", + "sourceLine": 69, + "sourceCode": "@RequestBody s: S", + "destinationLine": 78, + "destinationCode": "@Param(\"company\") company: Company,", + "nodes": [ + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "method": "putCustomer", + "node": "s", + "line": 71, + "code": "val customer = customerService.createOrUpdateCustomer(s)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/CustomerService.kt", + "method": "createOrUpdateCustomer", + "node": "customerAccountCommand", + "line": 24, + "code": "fun createOrUpdateCustomer(customerAccountCommand: S): Customer? {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/CustomerService.kt", + "method": "createOrUpdateCustomer", + "node": "customerAccountCommand", + "line": 26, + "code": "return eventHandler.executeAccountEvent(customerAccountCommand)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "executeAccountEvent", + "node": "eventCommand", + "line": 56, + "code": "fun executeAccountEvent(eventCommand: EventCommand): Customer? =" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "executeAccountEvent", + "node": "eventCommand", + "line": 57, + "code": "createOrUpdateCustomerByEvent(eventCommand.toDomain())" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "toDomain", + "node": "buildAccountUpdated", + "line": 101, + "code": "buildAccountUpdated().also {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "buildAccountUpdated", + "node": "additionalInfo", + "line": 134, + "code": "additionalInfo = additionalInfo," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/event/base/D.kt", + "method": "D", + "node": "additionalInfo", + "line": 42, + "code": "val additionalInfo: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/event/base/D.kt", + "method": "D", + "node": "additionalInfo", + "line": 42, + "code": "val additionalInfo: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/event/base/D.kt", + "method": "D", + "node": "additionalInfo", + "line": 42, + "code": "val additionalInfo: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "buildAccountUpdated", + "node": "D", + "line": 112, + "code": "D(" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "toDomain", + "node": "buildAccountUpdated", + "line": 101, + "code": "buildAccountUpdated().also {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "toDomain", + "node": "also", + "line": 101, + "code": "buildAccountUpdated().also {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "executeAccountEvent", + "node": "toDomain", + "line": 57, + "code": "createOrUpdateCustomerByEvent(eventCommand.toDomain())" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "createOrUpdateCustomerByEvent", + "node": "iEvent", + "line": 63, + "code": "fun createOrUpdateCustomerByEvent(iEvent: IEvent): Customer? {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "createOrUpdateCustomerByEvent", + "node": "iEvent", + "line": 65, + "code": "val customer = customerFromEventService.findCustomer(iEvent)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomer", + "node": "iEvent", + "line": 65, + "code": "fun findCustomer(iEvent: IEvent): Customer? =" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomer", + "node": "iEvent", + "line": 67, + "code": "?: findCustomerByOriginId(iEvent)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomerByOriginId", + "node": "iEvent", + "line": 73, + "code": "private fun findCustomerByOriginId(iEvent: IEvent): Customer? =" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomerByOriginId", + "node": "iEvent", + "line": 74, + "code": "if (!iEvent.customerOriginId().isNullOrEmpty()) {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomerByOriginId", + "node": "iEvent", + "line": 80, + "code": "value = iEvent.customerOriginId()!!" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomerByOriginId", + "node": "iEvent", + "line": 77, + "code": "company = iEvent.company," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomerByOriginId", + "node": "company", + "line": 77, + "code": "company = iEvent.company," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/PlatformCustomerId.kt", + "method": "PlatformCustomerId", + "node": "company", + "line": 9, + "code": "val company: Company = Company.CENTAURO," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/PlatformCustomerId.kt", + "method": "PlatformCustomerId", + "node": "company", + "line": 9, + "code": "val company: Company = Company.CENTAURO," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/PlatformCustomerId.kt", + "method": "PlatformCustomerId", + "node": "company", + "line": 9, + "code": "val company: Company = Company.CENTAURO," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomerByOriginId", + "node": "PlatformCustomerId", + "line": 76, + "code": "PlatformCustomerId(" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByCustomerOriginId", + "node": "platformCustomerId", + "line": 99, + "code": "platformCustomerId: PlatformCustomerId" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "Lambda", + "node": "platformCustomerId", + "line": 103, + "code": ".ifEmpty { getCustomerByOriginIdInOldestKeys(platformCustomerId) }," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "getCustomerByOriginIdInOldestKeys", + "node": "platformCustomerId", + "line": 118, + "code": "platformCustomerId: PlatformCustomerId" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "getCustomerByOriginIdInOldestKeys", + "node": "platformCustomerId", + "line": 122, + "code": "platformCustomerId.company, platformCustomerId.value" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "getCustomerByOriginIdInOldestKeys", + "node": "company", + "line": 122, + "code": "platformCustomerId.company, platformCustomerId.value" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=Xyn5EqekUMnMFVXfahJ4Td7s7HI%3D", + "firstScanID": "42f633e0-baee-4312-9283-7b189e76450f", + "notes": [] + }, + { + "similarityId": -1970275484, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-18T20:51:25Z", + "sourceFileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "destinationFileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/repository/CustomerRepository.kt", + "sourceNode": "s", + "destinationNode": "company", + "sourceMethod": "putCustomer", + "destinationMethod": "findByStoreCustomerId", + "sourceLine": 69, + "sourceCode": "@RequestBody s: S", + "destinationLine": 84, + "destinationCode": "@Param(\"company\") company: Company,", + "nodes": [ + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "method": "putCustomer", + "node": "s", + "line": 71, + "code": "val customer = customerService.createOrUpdateCustomer(s)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/CustomerService.kt", + "method": "createOrUpdateCustomer", + "node": "customerAccountCommand", + "line": 24, + "code": "fun createOrUpdateCustomer(customerAccountCommand: S): Customer? {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/CustomerService.kt", + "method": "createOrUpdateCustomer", + "node": "customerAccountCommand", + "line": 26, + "code": "return eventHandler.executeAccountEvent(customerAccountCommand)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "executeAccountEvent", + "node": "eventCommand", + "line": 56, + "code": "fun executeAccountEvent(eventCommand: EventCommand): Customer? =" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "executeAccountEvent", + "node": "eventCommand", + "line": 57, + "code": "createOrUpdateCustomerByEvent(eventCommand.toDomain())" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "toDomain", + "node": "buildAccountUpdated", + "line": 101, + "code": "buildAccountUpdated().also {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "buildAccountUpdated", + "node": "additionalInfo", + "line": 134, + "code": "additionalInfo = additionalInfo," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/event/base/D.kt", + "method": "D", + "node": "additionalInfo", + "line": 42, + "code": "val additionalInfo: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/event/base/D.kt", + "method": "D", + "node": "additionalInfo", + "line": 42, + "code": "val additionalInfo: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/event/base/D.kt", + "method": "D", + "node": "additionalInfo", + "line": 42, + "code": "val additionalInfo: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "buildAccountUpdated", + "node": "D", + "line": 112, + "code": "D(" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "toDomain", + "node": "buildAccountUpdated", + "line": 101, + "code": "buildAccountUpdated().also {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "toDomain", + "node": "also", + "line": 101, + "code": "buildAccountUpdated().also {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "executeAccountEvent", + "node": "toDomain", + "line": 57, + "code": "createOrUpdateCustomerByEvent(eventCommand.toDomain())" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "createOrUpdateCustomerByEvent", + "node": "iEvent", + "line": 63, + "code": "fun createOrUpdateCustomerByEvent(iEvent: IEvent): Customer? {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "createOrUpdateCustomerByEvent", + "node": "iEvent", + "line": 65, + "code": "val customer = customerFromEventService.findCustomer(iEvent)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomer", + "node": "iEvent", + "line": 65, + "code": "fun findCustomer(iEvent: IEvent): Customer? =" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomer", + "node": "iEvent", + "line": 67, + "code": "?: findCustomerByOriginId(iEvent)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomerByOriginId", + "node": "iEvent", + "line": 73, + "code": "private fun findCustomerByOriginId(iEvent: IEvent): Customer? =" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomerByOriginId", + "node": "iEvent", + "line": 74, + "code": "if (!iEvent.customerOriginId().isNullOrEmpty()) {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomerByOriginId", + "node": "iEvent", + "line": 80, + "code": "value = iEvent.customerOriginId()!!" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomerByOriginId", + "node": "iEvent", + "line": 77, + "code": "company = iEvent.company," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomerByOriginId", + "node": "company", + "line": 77, + "code": "company = iEvent.company," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/PlatformCustomerId.kt", + "method": "PlatformCustomerId", + "node": "company", + "line": 9, + "code": "val company: Company = Company.CENTAURO," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/PlatformCustomerId.kt", + "method": "PlatformCustomerId", + "node": "company", + "line": 9, + "code": "val company: Company = Company.CENTAURO," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/PlatformCustomerId.kt", + "method": "PlatformCustomerId", + "node": "company", + "line": 9, + "code": "val company: Company = Company.CENTAURO," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomerByOriginId", + "node": "PlatformCustomerId", + "line": 76, + "code": "PlatformCustomerId(" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByCustomerOriginId", + "node": "platformCustomerId", + "line": 99, + "code": "platformCustomerId: PlatformCustomerId" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "Lambda", + "node": "platformCustomerId", + "line": 103, + "code": ".ifEmpty { getCustomerByOriginIdInOldestKeys(platformCustomerId) }," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "getCustomerByOriginIdInOldestKeys", + "node": "platformCustomerId", + "line": 118, + "code": "platformCustomerId: PlatformCustomerId" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "getCustomerByOriginIdInOldestKeys", + "node": "platformCustomerId", + "line": 126, + "code": "platformCustomerId.company, platformCustomerId.value" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "getCustomerByOriginIdInOldestKeys", + "node": "company", + "line": 126, + "code": "platformCustomerId.company, platformCustomerId.value" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=gvMWazFHfbxwhf8NWBbt3GAnlf8%3D", + "firstScanID": "42f633e0-baee-4312-9283-7b189e76450f", + "notes": [] + }, + { + "similarityId": -587754158, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-18T20:51:25Z", + "sourceFileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "destinationFileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/repository/CustomerRepository.kt", + "sourceNode": "s", + "destinationNode": "company", + "sourceMethod": "putCustomer", + "destinationMethod": "findByPlatformCustomerId", + "sourceLine": 69, + "sourceCode": "@RequestBody s: S", + "destinationLine": 70, + "destinationCode": "@Param(\"company\") company: Company,", + "nodes": [ + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "method": "putCustomer", + "node": "s", + "line": 71, + "code": "val customer = customerService.createOrUpdateCustomer(s)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/CustomerService.kt", + "method": "createOrUpdateCustomer", + "node": "customerAccountCommand", + "line": 24, + "code": "fun createOrUpdateCustomer(customerAccountCommand: S): Customer? {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/CustomerService.kt", + "method": "createOrUpdateCustomer", + "node": "customerAccountCommand", + "line": 26, + "code": "return eventHandler.executeAccountEvent(customerAccountCommand)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "executeAccountEvent", + "node": "eventCommand", + "line": 56, + "code": "fun executeAccountEvent(eventCommand: EventCommand): Customer? =" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "executeAccountEvent", + "node": "eventCommand", + "line": 57, + "code": "createOrUpdateCustomerByEvent(eventCommand.toDomain())" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "toDomain", + "node": "buildAccountUpdated", + "line": 101, + "code": "buildAccountUpdated().also {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "buildAccountUpdated", + "node": "additionalInfo", + "line": 134, + "code": "additionalInfo = additionalInfo," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/event/base/D.kt", + "method": "D", + "node": "additionalInfo", + "line": 42, + "code": "val additionalInfo: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/event/base/D.kt", + "method": "D", + "node": "additionalInfo", + "line": 42, + "code": "val additionalInfo: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/event/base/D.kt", + "method": "D", + "node": "additionalInfo", + "line": 42, + "code": "val additionalInfo: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "buildAccountUpdated", + "node": "D", + "line": 112, + "code": "D(" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "toDomain", + "node": "buildAccountUpdated", + "line": 101, + "code": "buildAccountUpdated().also {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/command/S.kt", + "method": "toDomain", + "node": "also", + "line": 101, + "code": "buildAccountUpdated().also {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "executeAccountEvent", + "node": "toDomain", + "line": 57, + "code": "createOrUpdateCustomerByEvent(eventCommand.toDomain())" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "createOrUpdateCustomerByEvent", + "node": "iEvent", + "line": 63, + "code": "fun createOrUpdateCustomerByEvent(iEvent: IEvent): Customer? {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/handler/base/EventHandler.kt", + "method": "createOrUpdateCustomerByEvent", + "node": "iEvent", + "line": 65, + "code": "val customer = customerFromEventService.findCustomer(iEvent)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomer", + "node": "iEvent", + "line": 65, + "code": "fun findCustomer(iEvent: IEvent): Customer? =" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomer", + "node": "iEvent", + "line": 67, + "code": "?: findCustomerByOriginId(iEvent)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomerByOriginId", + "node": "iEvent", + "line": 73, + "code": "private fun findCustomerByOriginId(iEvent: IEvent): Customer? =" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomerByOriginId", + "node": "iEvent", + "line": 74, + "code": "if (!iEvent.customerOriginId().isNullOrEmpty()) {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomerByOriginId", + "node": "iEvent", + "line": 80, + "code": "value = iEvent.customerOriginId()!!" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomerByOriginId", + "node": "iEvent", + "line": 77, + "code": "company = iEvent.company," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomerByOriginId", + "node": "company", + "line": 77, + "code": "company = iEvent.company," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/PlatformCustomerId.kt", + "method": "PlatformCustomerId", + "node": "company", + "line": 9, + "code": "val company: Company = Company.CENTAURO," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/PlatformCustomerId.kt", + "method": "PlatformCustomerId", + "node": "company", + "line": 9, + "code": "val company: Company = Company.CENTAURO," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/entity/valueobject/PlatformCustomerId.kt", + "method": "PlatformCustomerId", + "node": "company", + "line": 9, + "code": "val company: Company = Company.CENTAURO," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventService.kt", + "method": "findCustomerByOriginId", + "node": "PlatformCustomerId", + "line": 76, + "code": "PlatformCustomerId(" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByCustomerOriginId", + "node": "platformCustomerId", + "line": 99, + "code": "platformCustomerId: PlatformCustomerId" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByCustomerOriginId", + "node": "platformCustomerId", + "line": 102, + "code": "findByPlatformCustomerId(platformCustomerId)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByPlatformCustomerId", + "node": "platformCustomerId", + "line": 108, + "code": "platformCustomerId: PlatformCustomerId" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByPlatformCustomerId", + "node": "platformCustomerId", + "line": 111, + "code": "platformCustomerId.company," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByPlatformCustomerId", + "node": "company", + "line": 111, + "code": "platformCustomerId.company," + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=oFJmykQBYbyN0n1g1XsQWCNIHZk%3D", + "firstScanID": "42f633e0-baee-4312-9283-7b189e76450f", + "notes": [] + }, + { + "similarityId": 640885851, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "destinationFileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/repository/CustomerRepository.kt", + "sourceNode": "cpf", + "destinationNode": "cpf", + "sourceMethod": "getCustomersByFilters", + "destinationMethod": "findByDocumentNumber", + "sourceLine": 90, + "sourceCode": "@Parameter(required = false, description = CPF_DESCRIPTION) @RequestParam cpf: String?,", + "destinationLine": 23, + "destinationCode": "@Param(\"cpf\") cpf: String?,", + "nodes": [ + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "method": "getCustomersByFilters", + "node": "cpf", + "line": 94, + "code": "val identityKeys = IdentityKeys(cpf, cnpj, email)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/IdentityKeys.kt", + "method": "IdentityKeys", + "node": "cpf", + "line": 6, + "code": "var cpf: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/IdentityKeys.kt", + "method": "IdentityKeys", + "node": "cpf", + "line": 6, + "code": "var cpf: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/IdentityKeys.kt", + "method": "IdentityKeys", + "node": "cpf", + "line": 6, + "code": "var cpf: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "method": "getCustomersByFilters", + "node": "IdentityKeys", + "line": 94, + "code": "val identityKeys = IdentityKeys(cpf, cnpj, email)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "method": "getCustomersByFilters", + "node": "identityKeys", + "line": 94, + "code": "val identityKeys = IdentityKeys(cpf, cnpj, email)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "method": "getCustomersByFilters", + "node": "identityKeys", + "line": 98, + "code": "val persons = personService.findBy(company, id, identityKeys).filterNotNull()" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findBy", + "node": "identityKey", + "line": 26, + "code": "identityKey: IdentityKeys" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findBy", + "node": "identityKey", + "line": 27, + "code": ") = findByCustomer(businessUnit, id, identityKey).map {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findByCustomer", + "node": "identityKey", + "line": 34, + "code": "identityKey: IdentityKeys" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findByCustomer", + "node": "identityKey", + "line": 38, + "code": "findByIdentityKey(businessUnit, identityKey)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findByIdentityKey", + "node": "identityKeys", + "line": 53, + "code": "identityKeys: IdentityKeys" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findByIdentityKey", + "node": "identityKeys", + "line": 55, + "code": "if (!identityKeys.existValidKey()) {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findByIdentityKey", + "node": "identityKeys", + "line": 58, + "code": "return customerFinder.findByIdentityKeys(identityKeys)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByIdentityKeys", + "node": "identityKeys", + "line": 29, + "code": "identityKeys: IdentityKeys," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByIdentityKeys", + "node": "identityKeys", + "line": 32, + "code": "val customers = findByDocumentNumber(identityKeys.cpf, identityKeys.cnpj)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByIdentityKeys", + "node": "cpf", + "line": 32, + "code": "val customers = findByDocumentNumber(identityKeys.cpf, identityKeys.cnpj)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByDocumentNumber", + "node": "cpf", + "line": 68, + "code": "cpf: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByDocumentNumber", + "node": "cpf", + "line": 72, + "code": "customerRepository.findByDocumentNumber(cpf, cnpj)" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=hq2oVIS4LrGF8CFA0OPJ4Z9%2BrNY%3D", + "firstScanID": "42f633e0-baee-4312-9283-7b189e76450f", + "notes": [] + }, + { + "similarityId": 536979830, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "destinationFileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/repository/EventRepository.kt", + "sourceNode": "customerId", + "destinationNode": "customerId", + "sourceMethod": "getOrders", + "destinationMethod": "findByCustomerIdAndCompanyAndType", + "sourceLine": 141, + "sourceCode": "@Parameter(description = CUSTOMER_ID_DESCRIPTION) @PathVariable customerId: String,", + "destinationLine": 75, + "destinationCode": "@Param(\"customerId\") customerId: String,", + "nodes": [ + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "method": "getOrders", + "node": "customerId", + "line": 144, + "code": "val orderResponses = orderService.findEventsBy(customerId, pageable).map { OrderResponse.from(it) }" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/OrderService.kt", + "method": "findEventsBy", + "node": "id", + "line": 32, + "code": "fun findEventsBy(id: String, pageable: Pageable): List\u003cEvent\u003e {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/OrderService.kt", + "method": "findEventsBy", + "node": "id", + "line": 40, + "code": "customerId = id," + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=5Su3U7sQr%2BmQmRgPJR8PPDJYuug%3D", + "firstScanID": "13c58a3f-78d2-4e58-a900-cf7c95ebd96c", + "notes": [] + }, + { + "similarityId": 495143190, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "destinationFileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/repository/EventRepository.kt", + "sourceNode": "customerId", + "destinationNode": "customerId", + "sourceMethod": "deletePerson", + "destinationMethod": "findByCustomerIdAndCompany", + "sourceLine": 170, + "sourceCode": "@PathVariable customerId: String,", + "destinationLine": 17, + "destinationCode": "@Param(\"customerId\") customerId: String,", + "nodes": [ + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/CustomerController.kt", + "method": "deletePerson", + "node": "customerId", + "line": 174, + "code": "if (deletePersonService.deletePerson(customerId, businessUnit)) {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/DeletePersonService.kt", + "method": "deletePerson", + "node": "customerId", + "line": 22, + "code": "fun deletePerson(customerId: String, company: Company): Boolean {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/DeletePersonService.kt", + "method": "deletePerson", + "node": "customerId", + "line": 23, + "code": "val eventCount = eventService.deleteByCustomerIdAndCompany(customerId, company)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/EventService.kt", + "method": "deleteByCustomerIdAndCompany", + "node": "customerId", + "line": 36, + "code": "fun deleteByCustomerIdAndCompany(customerId: String, company: Company): Int {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/EventService.kt", + "method": "deleteByCustomerIdAndCompany", + "node": "customerId", + "line": 37, + "code": "val events = eventRepository.findByCustomerIdAndCompany(customerId, company)" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=m8FLfznhv%2B2hH9in9MfJ6Ek%2FD0Q%3D", + "firstScanID": "13c58a3f-78d2-4e58-a900-cf7c95ebd96c", + "notes": [] + }, + { + "similarityId": 604123299, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/main/kotlin/br/com/123/loiskjdye/api/ClipboardController.kt", + "destinationFileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/repository/CustomerRepository.kt", + "sourceNode": "cpf", + "destinationNode": "cpf", + "sourceMethod": "getCustomers", + "destinationMethod": "findByDocumentNumber", + "sourceLine": 58, + "sourceCode": "@Parameter(required = false, description = CPF_DESCRIPTION) @RequestParam cpf: String?,", + "destinationLine": 23, + "destinationCode": "@Param(\"cpf\") cpf: String?,", + "nodes": [ + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/ClipboardController.kt", + "method": "getCustomers", + "node": "cpf", + "line": 61, + "code": "val identityKeys = IdentityKeys(cpf = cpf, email = email)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/IdentityKeys.kt", + "method": "IdentityKeys", + "node": "cpf", + "line": 6, + "code": "var cpf: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/IdentityKeys.kt", + "method": "IdentityKeys", + "node": "cpf", + "line": 6, + "code": "var cpf: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/valueobject/IdentityKeys.kt", + "method": "IdentityKeys", + "node": "cpf", + "line": 6, + "code": "var cpf: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/ClipboardController.kt", + "method": "getCustomers", + "node": "IdentityKeys", + "line": 61, + "code": "val identityKeys = IdentityKeys(cpf = cpf, email = email)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/ClipboardController.kt", + "method": "getCustomers", + "node": "identityKeys", + "line": 61, + "code": "val identityKeys = IdentityKeys(cpf = cpf, email = email)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/ClipboardController.kt", + "method": "getCustomers", + "node": "identityKeys", + "line": 64, + "code": "identityKeys = identityKeys," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/dtos/ClipboardQueryDTO.kt", + "method": "ClipboardQueryDTO", + "node": "identityKeys", + "line": 8, + "code": "val identityKeys: IdentityKeys," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/dtos/ClipboardQueryDTO.kt", + "method": "ClipboardQueryDTO", + "node": "identityKeys", + "line": 8, + "code": "val identityKeys: IdentityKeys," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/dtos/ClipboardQueryDTO.kt", + "method": "ClipboardQueryDTO", + "node": "identityKeys", + "line": 8, + "code": "val identityKeys: IdentityKeys," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/ClipboardController.kt", + "method": "getCustomers", + "node": "ClipboardQueryDTO", + "line": 62, + "code": "val clipboardQueryDTO = ClipboardQueryDTO(" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/ClipboardController.kt", + "method": "getCustomers", + "node": "clipboardQueryDTO", + "line": 62, + "code": "val clipboardQueryDTO = ClipboardQueryDTO(" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/api/ClipboardController.kt", + "method": "getCustomers", + "node": "clipboardQueryDTO", + "line": 68, + "code": "val clipboard = clipboardService.getClipboard(clipboardQueryDTO)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/ClipboardService.kt", + "method": "getClipboard", + "node": "clipboardQueryDTO", + "line": 22, + "code": "fun getClipboard(clipboardQueryDTO: ClipboardQueryDTO): Clipboard? =" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/ClipboardService.kt", + "method": "getClipboard", + "node": "clipboardQueryDTO", + "line": 24, + "code": "createClipboard(clipboardQueryDTO)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/ClipboardService.kt", + "method": "createClipboard", + "node": "clipboardQueryDTO", + "line": 29, + "code": "private fun createClipboard(clipboardQueryDTO: ClipboardQueryDTO): Clipboard? {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/ClipboardService.kt", + "method": "createClipboard", + "node": "clipboardQueryDTO", + "line": 30, + "code": "val person = getPerson(clipboardQueryDTO) ?: return null" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/ClipboardService.kt", + "method": "getPerson", + "node": "clipboardQueryDTO", + "line": 48, + "code": "private fun getPerson(clipboardQueryDTO: ClipboardQueryDTO): Person? =" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/ClipboardService.kt", + "method": "getPerson", + "node": "clipboardQueryDTO", + "line": 51, + "code": "id = null, identityKey = clipboardQueryDTO.identityKeys" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/ClipboardService.kt", + "method": "getPerson", + "node": "identityKeys", + "line": 51, + "code": "id = null, identityKey = clipboardQueryDTO.identityKeys" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findBy", + "node": "identityKey", + "line": 26, + "code": "identityKey: IdentityKeys" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findBy", + "node": "identityKey", + "line": 27, + "code": ") = findByCustomer(businessUnit, id, identityKey).map {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findByCustomer", + "node": "identityKey", + "line": 34, + "code": "identityKey: IdentityKeys" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findByCustomer", + "node": "identityKey", + "line": 38, + "code": "findByIdentityKey(businessUnit, identityKey)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findByIdentityKey", + "node": "identityKeys", + "line": 53, + "code": "identityKeys: IdentityKeys" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findByIdentityKey", + "node": "identityKeys", + "line": 55, + "code": "if (!identityKeys.existValidKey()) {" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/application/services/PersonService.kt", + "method": "findByIdentityKey", + "node": "identityKeys", + "line": 58, + "code": "return customerFinder.findByIdentityKeys(identityKeys)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByIdentityKeys", + "node": "identityKeys", + "line": 29, + "code": "identityKeys: IdentityKeys," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByIdentityKeys", + "node": "identityKeys", + "line": 32, + "code": "val customers = findByDocumentNumber(identityKeys.cpf, identityKeys.cnpj)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByIdentityKeys", + "node": "cpf", + "line": 32, + "code": "val customers = findByDocumentNumber(identityKeys.cpf, identityKeys.cnpj)" + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByDocumentNumber", + "node": "cpf", + "line": 68, + "code": "cpf: String? = null," + }, + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/domain/service/CustomerFinder.kt", + "method": "findByDocumentNumber", + "node": "cpf", + "line": 72, + "code": "customerRepository.findByDocumentNumber(cpf, cnpj)" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=UPJUQffX3uK2PAgHCjskVvLuyKY%3D", + "firstScanID": "42f633e0-baee-4312-9283-7b189e76450f", + "notes": [] + } + ] + }, + { + "queryName": "Unchecked_Input_for_Loop_Condition", + "queryDescriptionLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast/description/606/7308467749988344824", + "queryId": 7308467749988344824, + "description": "Method @SourceMethod at line @SourceLine of @SourceFile gets user input from element @SourceElement . This element’s value flows through the code without being validated, and is eventually used in a loop condition in @DestinationMethod at line @DestinationLine of @DestinationFile. This constitutes an Unchecked Input for Loop Condition.\n\n", + "vulnerabilitiesTotal": 1, + "queryPath": "Kotlin/Kotlin_Medium_Threat/Unchecked_Input_for_Loop_Condition", + "cweId": 606, + "categories": [ + { + "name": "OWASP Top 10 2021", + "subCategories": [ + "A4-Insecure Design" + ] + } + ], + "vulnerabilities": [ + { + "similarityId": -1047631551, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-04-01T23:57:07Z", + "sourceFileName": "/src/main/kotlin/br/com/123/loiskjdye/configuration/XSSSanitizationInterceptor.kt", + "destinationFileName": "/src/main/kotlin/br/com/123/loiskjdye/configuration/XSSSanitizationInterceptor.kt", + "sourceNode": "parameterMap", + "destinationNode": "parameterMap", + "sourceMethod": "sanitizeParameterMap", + "destinationMethod": "sanitizeParameterMap", + "sourceLine": 23, + "sourceCode": "val parameterMap = request.parameterMap", + "destinationLine": 25, + "destinationCode": "for ((_, values) in parameterMap) {", + "nodes": [ + { + "fileName": "/src/main/kotlin/br/com/123/loiskjdye/configuration/XSSSanitizationInterceptor.kt", + "method": "sanitizeParameterMap", + "node": "parameterMap", + "line": 23, + "code": "val parameterMap = request.parameterMap" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=Nw4DvTqaqFHqWcuuvf05%2BOwCvUE%3D", + "firstScanID": "3d859bfc-e7c7-435d-862e-e50c0c257c23", + "notes": [] + } + ] + }, + { + "queryName": "Unchecked_Input_for_Loop_Condition", + "queryDescriptionLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast/description/606/12513885999564608658", + "queryId": 12513885999564608658, + "description": "Method @SourceMethod at line @SourceLine of @SourceFile gets user input from element @SourceElement . This element’s value flows through the code without being validated, and is eventually used in a loop condition in @DestinationMethod at line @DestinationLine of @DestinationFile. This constitutes an Unchecked Input for Loop Condition.\n\n", + "vulnerabilitiesTotal": 2, + "queryPath": "Python/Python_Medium_Threat/Unchecked_Input_for_Loop_Condition", + "cweId": 606, + "categories": [ + { + "name": "OWASP Top 10 2021", + "subCategories": [ + "A4-Insecure Design" + ] + } + ], + "vulnerabilities": [ + { + "similarityId": -1697321860, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/kafka-tombstone.py", + "destinationFileName": "/scripts/kafka-tombstone.py", + "sourceNode": "environ", + "destinationNode": "Not", + "sourceMethod": "_create_producer_connected_to_kafka", + "destinationMethod": "_create_producer_connected_to_kafka", + "sourceLine": 22, + "sourceCode": "sasl_plain_password=os.environ['KAFKA_PASSWORD'])", + "destinationLine": 24, + "destinationCode": "while not producer.bootstrap_connected():", + "nodes": [ + { + "fileName": "/scripts/kafka-tombstone.py", + "method": "_create_producer_connected_to_kafka", + "node": "KafkaProducer", + "line": 17, + "code": "producer = KafkaProducer(bootstrap_servers=bootstrap_servers," + }, + { + "fileName": "/scripts/kafka-tombstone.py", + "method": "_create_producer_connected_to_kafka", + "node": "producer", + "line": 17, + "code": "producer = KafkaProducer(bootstrap_servers=bootstrap_servers," + }, + { + "fileName": "/scripts/kafka-tombstone.py", + "method": "_create_producer_connected_to_kafka", + "node": "producer", + "line": 24, + "code": "while not producer.bootstrap_connected():" + }, + { + "fileName": "/scripts/kafka-tombstone.py", + "method": "_create_producer_connected_to_kafka", + "node": "bootstrap_connected", + "line": 24, + "code": "while not producer.bootstrap_connected():" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=vIT%2BynoenV7jhBmTKHEGnwhdZn0%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 815362143, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/kafka-tombstone.py", + "destinationFileName": "/scripts/kafka-tombstone.py", + "sourceNode": "environ", + "destinationNode": "Not", + "sourceMethod": "_create_producer_connected_to_kafka", + "destinationMethod": "_create_producer_connected_to_kafka", + "sourceLine": 21, + "sourceCode": "sasl_plain_username=os.environ['KAFKA_USERNAME'],", + "destinationLine": 24, + "destinationCode": "while not producer.bootstrap_connected():", + "nodes": [ + { + "fileName": "/scripts/kafka-tombstone.py", + "method": "_create_producer_connected_to_kafka", + "node": "KafkaProducer", + "line": 17, + "code": "producer = KafkaProducer(bootstrap_servers=bootstrap_servers," + }, + { + "fileName": "/scripts/kafka-tombstone.py", + "method": "_create_producer_connected_to_kafka", + "node": "producer", + "line": 17, + "code": "producer = KafkaProducer(bootstrap_servers=bootstrap_servers," + }, + { + "fileName": "/scripts/kafka-tombstone.py", + "method": "_create_producer_connected_to_kafka", + "node": "producer", + "line": 24, + "code": "while not producer.bootstrap_connected():" + }, + { + "fileName": "/scripts/kafka-tombstone.py", + "method": "_create_producer_connected_to_kafka", + "node": "bootstrap_connected", + "line": 24, + "code": "while not producer.bootstrap_connected():" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=dwkc9QNXDY6nyxLmILK9%2FNz26H8%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + } + ] + }, + { + "queryName": "SSRF", + "queryDescriptionLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast/description/918/5815271517533586646", + "queryId": 5815271517533586646, + "description": "The application sends a request to a remote server, for some resource, using @DestinationElement in @DestinationFile:@DestinationLine. However, an attacker can control the target of the request, by sending a URL or other data in @SourceElement at @SourceFile:@SourceLine.\n\n", + "vulnerabilitiesTotal": 4, + "queryPath": "Go/Go_Medium_Threat/SSRF", + "cweId": 918, + "categories": [ + { + "name": "CWE top 25", + "subCategories": [ + "CWE top 25" + ] + }, + { + "name": "MOIS(KISA) Secure Coding 2021", + "subCategories": [ + "MOIS(KISA) Verification and representation of input data" + ] + }, + { + "name": "OWASP ASVS", + "subCategories": [ + "V05 Validation, Sanitization and Encoding" + ] + }, + { + "name": "OWASP Top 10 2017", + "subCategories": [ + "A5-Broken Access Control" + ] + }, + { + "name": "OWASP Top 10 2021", + "subCategories": [ + "A10-Server-Side Request Forgery" + ] + } + ], + "vulnerabilities": [ + { + "similarityId": 1884777923, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/extract_orders.go", + "destinationFileName": "/scripts/export-csv-full-base/e.go", + "sourceNode": "Text", + "destinationNode": "Do", + "sourceMethod": "main", + "destinationMethod": "Lambda", + "sourceLine": 129, + "sourceCode": "line := scanner.Text()", + "destinationLine": 88, + "destinationCode": "resp, err := httpClient.Do(req)", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "line", + "line": 129, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "line", + "line": 130, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "Split", + "line": 130, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "parts", + "line": 130, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "parts", + "line": 131, + "code": "customer_id := parts[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "customer_id", + "line": 131, + "code": "customer_id := parts[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "customer_id", + "line": 133, + "code": "inputs = append(inputs, input{customer_id, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "input", + "node": "customer_id", + "line": 48, + "code": "customer_id string" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "input", + "node": "customer_id", + "line": 48, + "code": "customer_id string" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "input", + "node": "customer_id", + "line": 48, + "code": "customer_id string" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "input", + "line": 133, + "code": "inputs = append(inputs, input{customer_id, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "append", + "line": 133, + "code": "inputs = append(inputs, input{customer_id, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "inputs", + "line": 133, + "code": "inputs = append(inputs, input{customer_id, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "inputs", + "line": 139, + "code": "results := boundedParallelGet(inputs, concurrency)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "boundedParallelGet", + "node": "inputs", + "line": 62, + "code": "func boundedParallelGet(inputs []input, concurrencyLimit int) []bool {" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "boundedParallelGet", + "node": "inputs", + "line": 72, + "code": "for i, inp := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "boundedParallelGet", + "node": "inputs", + "line": 72, + "code": "for i, inp := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "boundedParallelGet", + "node": "inp", + "line": 72, + "code": "for i, inp := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "boundedParallelGet", + "node": "inp", + "line": 120, + "code": "}(i, inp)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "Lambda", + "node": "inp", + "line": 74, + "code": "go func(i int, inp input) {" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "Lambda", + "node": "inp", + "line": 78, + "code": "req, err := http.NewRequest(\"GET\", inp.url, nil)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "Lambda", + "node": "url", + "line": 78, + "code": "req, err := http.NewRequest(\"GET\", inp.url, nil)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "Lambda", + "node": "NewRequest", + "line": 78, + "code": "req, err := http.NewRequest(\"GET\", inp.url, nil)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "Lambda", + "node": "req", + "line": 78, + "code": "req, err := http.NewRequest(\"GET\", inp.url, nil)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "Lambda", + "node": "req", + "line": 85, + "code": "req.Header.Add(\"Accept\", \"application/vnd.example123.v1+json\")" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "Lambda", + "node": "req", + "line": 86, + "code": "req.Header.Add(\"Accept-Charset\", \"UTF-8\")" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "Lambda", + "node": "req", + "line": 88, + "code": "resp, err := httpClient.Do(req)" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=tA56eqAtnN%2Bjd%2BsB1ayL0tlLBD8%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -1912671113, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/e.go", + "destinationFileName": "/scripts/export-csv-full-base/e.go", + "sourceNode": "Text", + "destinationNode": "Do", + "sourceMethod": "main", + "destinationMethod": "Lambda", + "sourceLine": 151, + "sourceCode": "line := scanner.Text()", + "destinationLine": 88, + "destinationCode": "resp, err := httpClient.Do(req)", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "line", + "line": 151, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "line", + "line": 152, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "Split", + "line": 152, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "parts", + "line": 152, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "parts", + "line": 153, + "code": "field := parts[0]" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "field", + "line": 153, + "code": "field := parts[0]" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "field", + "line": 166, + "code": "inputs = append(inputs, input{field, value, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "input", + "line": 166, + "code": "inputs = append(inputs, input{field, value, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "append", + "line": 166, + "code": "inputs = append(inputs, input{field, value, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "inputs", + "line": 166, + "code": "inputs = append(inputs, input{field, value, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "inputs", + "line": 172, + "code": "results := boundedParallelGet(inputs, concurrency)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "boundedParallelGet", + "node": "inputs", + "line": 62, + "code": "func boundedParallelGet(inputs []input, concurrencyLimit int) []bool {" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "boundedParallelGet", + "node": "inputs", + "line": 72, + "code": "for i, inp := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "boundedParallelGet", + "node": "inputs", + "line": 72, + "code": "for i, inp := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "boundedParallelGet", + "node": "inp", + "line": 72, + "code": "for i, inp := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "boundedParallelGet", + "node": "inp", + "line": 120, + "code": "}(i, inp)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "Lambda", + "node": "inp", + "line": 74, + "code": "go func(i int, inp input) {" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "Lambda", + "node": "inp", + "line": 78, + "code": "req, err := http.NewRequest(\"GET\", inp.url, nil)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "Lambda", + "node": "url", + "line": 78, + "code": "req, err := http.NewRequest(\"GET\", inp.url, nil)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "Lambda", + "node": "NewRequest", + "line": 78, + "code": "req, err := http.NewRequest(\"GET\", inp.url, nil)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "Lambda", + "node": "req", + "line": 78, + "code": "req, err := http.NewRequest(\"GET\", inp.url, nil)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "Lambda", + "node": "req", + "line": 85, + "code": "req.Header.Add(\"Accept\", \"application/vnd.example123.v1+json\")" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "Lambda", + "node": "req", + "line": 86, + "code": "req.Header.Add(\"Accept-Charset\", \"UTF-8\")" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "Lambda", + "node": "req", + "line": 88, + "code": "resp, err := httpClient.Do(req)" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=LZtZQkrDjUuHkkCLdvQu%2BDKdraE%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -2058055515, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/extract_orders.go", + "destinationFileName": "/scripts/export-csv-full-base/extract_orders.go", + "sourceNode": "Text", + "destinationNode": "Do", + "sourceMethod": "main", + "destinationMethod": "Lambda", + "sourceLine": 129, + "sourceCode": "line := scanner.Text()", + "destinationLine": 78, + "destinationCode": "resp, err := httpClient.Do(req)", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "line", + "line": 129, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "line", + "line": 130, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "Split", + "line": 130, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "parts", + "line": 130, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "parts", + "line": 131, + "code": "customer_id := parts[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "customer_id", + "line": 131, + "code": "customer_id := parts[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "customer_id", + "line": 133, + "code": "inputs = append(inputs, input{customer_id, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "input", + "node": "customer_id", + "line": 48, + "code": "customer_id string" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "input", + "node": "customer_id", + "line": 48, + "code": "customer_id string" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "input", + "node": "customer_id", + "line": 48, + "code": "customer_id string" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "input", + "line": 133, + "code": "inputs = append(inputs, input{customer_id, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "append", + "line": 133, + "code": "inputs = append(inputs, input{customer_id, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "inputs", + "line": 133, + "code": "inputs = append(inputs, input{customer_id, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "inputs", + "line": 139, + "code": "results := boundedParallelGet(inputs, concurrency)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "boundedParallelGet", + "node": "inputs", + "line": 52, + "code": "func boundedParallelGet(inputs []input, concurrencyLimit int) []bool {" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "boundedParallelGet", + "node": "inputs", + "line": 62, + "code": "for i, inp := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "boundedParallelGet", + "node": "inputs", + "line": 62, + "code": "for i, inp := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "boundedParallelGet", + "node": "inp", + "line": 62, + "code": "for i, inp := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "boundedParallelGet", + "node": "inp", + "line": 98, + "code": "}(i, inp)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "Lambda", + "node": "inp", + "line": 64, + "code": "go func(i int, inp input) {" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "Lambda", + "node": "inp", + "line": 68, + "code": "req, err := http.NewRequest(\"GET\", inp.url, nil)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "Lambda", + "node": "url", + "line": 68, + "code": "req, err := http.NewRequest(\"GET\", inp.url, nil)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "Lambda", + "node": "NewRequest", + "line": 68, + "code": "req, err := http.NewRequest(\"GET\", inp.url, nil)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "Lambda", + "node": "req", + "line": 68, + "code": "req, err := http.NewRequest(\"GET\", inp.url, nil)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "Lambda", + "node": "req", + "line": 75, + "code": "req.Header.Add(\"Accept\", \"application/vnd.example123.v1+json\")" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "Lambda", + "node": "req", + "line": 76, + "code": "req.Header.Add(\"Accept-Charset\", \"UTF-8\")" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "Lambda", + "node": "req", + "line": 78, + "code": "resp, err := httpClient.Do(req)" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=RuLcgBI47lTYtQAwY3NhPdXs6Jw%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 569747057, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/e.go", + "destinationFileName": "/scripts/export-csv-full-base/extract_orders.go", + "sourceNode": "Text", + "destinationNode": "Do", + "sourceMethod": "main", + "destinationMethod": "Lambda", + "sourceLine": 151, + "sourceCode": "line := scanner.Text()", + "destinationLine": 78, + "destinationCode": "resp, err := httpClient.Do(req)", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "line", + "line": 151, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "line", + "line": 152, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "Split", + "line": 152, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "parts", + "line": 152, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "parts", + "line": 153, + "code": "field := parts[0]" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "field", + "line": 153, + "code": "field := parts[0]" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "field", + "line": 166, + "code": "inputs = append(inputs, input{field, value, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "input", + "line": 166, + "code": "inputs = append(inputs, input{field, value, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "append", + "line": 166, + "code": "inputs = append(inputs, input{field, value, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "inputs", + "line": 166, + "code": "inputs = append(inputs, input{field, value, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "inputs", + "line": 172, + "code": "results := boundedParallelGet(inputs, concurrency)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "boundedParallelGet", + "node": "inputs", + "line": 52, + "code": "func boundedParallelGet(inputs []input, concurrencyLimit int) []bool {" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "boundedParallelGet", + "node": "inputs", + "line": 62, + "code": "for i, inp := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "boundedParallelGet", + "node": "inputs", + "line": 62, + "code": "for i, inp := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "boundedParallelGet", + "node": "inp", + "line": 62, + "code": "for i, inp := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "boundedParallelGet", + "node": "inp", + "line": 98, + "code": "}(i, inp)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "Lambda", + "node": "inp", + "line": 64, + "code": "go func(i int, inp input) {" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "Lambda", + "node": "inp", + "line": 68, + "code": "req, err := http.NewRequest(\"GET\", inp.url, nil)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "Lambda", + "node": "url", + "line": 68, + "code": "req, err := http.NewRequest(\"GET\", inp.url, nil)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "Lambda", + "node": "NewRequest", + "line": 68, + "code": "req, err := http.NewRequest(\"GET\", inp.url, nil)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "Lambda", + "node": "req", + "line": 68, + "code": "req, err := http.NewRequest(\"GET\", inp.url, nil)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "Lambda", + "node": "req", + "line": 75, + "code": "req.Header.Add(\"Accept\", \"application/vnd.example123.v1+json\")" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "Lambda", + "node": "req", + "line": 76, + "code": "req.Header.Add(\"Accept-Charset\", \"UTF-8\")" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "Lambda", + "node": "req", + "line": 78, + "code": "resp, err := httpClient.Do(req)" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=xHwepY1uRJ0CUKw1%2FCWCdjqvku4%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + } + ] + }, + { + "queryName": "SSL_Verification_Bypass", + "queryDescriptionLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast/description/599/1229368380051640880", + "queryId": 1229368380051640880, + "description": "@DestinationFile relies HTTPS requests, in @DestinationMethod. The @DestinationElement parameter, at line @DestinationLine, effectively disables verification of the SSL certificate trust chain.\n\n", + "vulnerabilitiesTotal": 1, + "queryPath": "Go/Go_Medium_Threat/SSL_Verification_Bypass", + "cweId": 599, + "categories": [ + { + "name": "OWASP ASVS", + "subCategories": [ + "V09 Communication" + ] + }, + { + "name": "OWASP Top 10 2021", + "subCategories": [ + "A2-Cryptographic Failures" + ] + }, + { + "name": "SANS top 25", + "subCategories": [ + "SANS top 25" + ] + }, + { + "name": "MOIS(KISA) Secure Coding 2021", + "subCategories": [ + "MOIS(KISA) Security Functions" + ] + } + ], + "vulnerabilities": [ + { + "similarityId": -1862729044, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/extract_orders.go", + "destinationFileName": "/scripts/export-csv-full-base/extract_orders.go", + "sourceNode": "true", + "destinationNode": "true", + "sourceLine": 28, + "sourceCode": "TLSClientConfig: \u0026tls.Config{InsecureSkipVerify: true},", + "destinationLine": 28, + "destinationCode": "TLSClientConfig: \u0026tls.Config{InsecureSkipVerify: true},", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=dwQ%2B5L%2FprM3S7VRgll%2FPfo1NVcE%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + } + ] + }, + { + "queryName": "Reflected_Relative_Path_Traversal", + "queryDescriptionLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast/description/23/13335880433012882564", + "queryId": 13335880433012882564, + "description": "Method @SourceMethod at line @SourceLine of @SourceFile gets dynamic data from the @SourceElement element. This element’s value then flows through the code and is eventually used in a file path for local disk access in @DestinationMethod at line @DestinationLine of @DestinationFile. This may cause a Path Traversal vulnerability.\n\n", + "vulnerabilitiesTotal": 4, + "queryPath": "Go/Go_Medium_Threat/Reflected_Relative_Path_Traversal", + "cweId": 23, + "categories": [ + { + "name": "OWASP Top 10 2021", + "subCategories": [ + "A1-Broken Access Control" + ] + }, + { + "name": "SANS top 25", + "subCategories": [ + "SANS top 25" + ] + }, + { + "name": "CWE top 25", + "subCategories": [ + "CWE top 25" + ] + }, + { + "name": "MOIS(KISA) Secure Coding 2021", + "subCategories": [ + "MOIS(KISA) Verification and representation of input data" + ] + }, + { + "name": "OWASP ASVS", + "subCategories": [ + "V12 Files and Resources" + ] + } + ], + "vulnerabilities": [ + { + "similarityId": 395802728, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "destinationFileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "sourceNode": "Args", + "destinationNode": "filename", + "sourceMethod": "main", + "destinationMethod": "main", + "sourceLine": 191, + "sourceCode": "filename := os.Args[1]", + "destinationLine": 193, + "destinationCode": "file, err := os.Open(filename)", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "filename", + "line": 191, + "code": "filename := os.Args[1]" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=bLd8WKxjj37KomVyg26Kd52H%2FVE%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -1961783156, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "destinationFileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "sourceNode": "Args", + "destinationNode": "filename", + "sourceMethod": "main", + "destinationMethod": "main", + "sourceLine": 159, + "sourceCode": "filename := os.Args[1]", + "destinationLine": 161, + "destinationCode": "file, err := os.Open(filename)", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "filename", + "line": 159, + "code": "filename := os.Args[1]" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=6UQvxQarG8caXzRN9m8ZsUdqwAI%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 287938150, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/e.go", + "destinationFileName": "/scripts/export-csv-full-base/e.go", + "sourceNode": "Args", + "destinationNode": "filename", + "sourceMethod": "main", + "destinationMethod": "main", + "sourceLine": 140, + "sourceCode": "filename := os.Args[1]", + "destinationLine": 142, + "destinationCode": "file, err := os.Open(filename)", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "filename", + "line": 140, + "code": "filename := os.Args[1]" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=lMnAZUJkfs826uXTlQj9NqoevwE%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 1536663916, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/extract_orders.go", + "destinationFileName": "/scripts/export-csv-full-base/extract_orders.go", + "sourceNode": "Args", + "destinationNode": "filename", + "sourceMethod": "main", + "destinationMethod": "main", + "sourceLine": 118, + "sourceCode": "filename := os.Args[1]", + "destinationLine": 120, + "destinationCode": "file, err := os.Open(filename)", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "filename", + "line": 118, + "code": "filename := os.Args[1]" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=ZBmrTjbTFrelRalQkJt4lP7%2BLgU%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + } + ] + }, + { + "queryName": "Reflected_Absolute_Path_Traversal", + "queryDescriptionLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast/description/36/2543264030649380806", + "queryId": 2543264030649380806, + "description": "Method @SourceMethod at line @SourceLine of @SourceFile gets dynamic data from the @SourceElement element. This element’s value then flows through the code and is eventually used in a file path for local disk access in @DestinationMethod at line @DestinationLine of @DestinationFile. This may cause a Path Traversal vulnerability.\n\n", + "vulnerabilitiesTotal": 4, + "queryPath": "Go/Go_Medium_Threat/Reflected_Absolute_Path_Traversal", + "cweId": 36, + "categories": [ + { + "name": "FISMA 2014", + "subCategories": [ + "System And Information Integrity" + ] + }, + { + "name": "MOIS(KISA) Secure Coding 2021", + "subCategories": [ + "MOIS(KISA) Verification and representation of input data" + ] + }, + { + "name": "NIST SP 800-53", + "subCategories": [ + "SI-10 Information Input Validation (P1)" + ] + }, + { + "name": "OWASP ASVS", + "subCategories": [ + "V12 Files and Resources" + ] + }, + { + "name": "OWASP Top 10 2021", + "subCategories": [ + "A1-Broken Access Control" + ] + }, + { + "name": "SANS top 25", + "subCategories": [ + "SANS top 25" + ] + }, + { + "name": "CWE top 25", + "subCategories": [ + "CWE top 25" + ] + } + ], + "vulnerabilities": [ + { + "similarityId": 913471081, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "destinationFileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "sourceNode": "Args", + "destinationNode": "filename", + "sourceMethod": "main", + "destinationMethod": "main", + "sourceLine": 191, + "sourceCode": "filename := os.Args[1]", + "destinationLine": 193, + "destinationCode": "file, err := os.Open(filename)", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "filename", + "line": 191, + "code": "filename := os.Args[1]" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=strTNgzsaxq%2BnXzpP%2F1tF3eaj3Q%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -1794979387, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "destinationFileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "sourceNode": "Args", + "destinationNode": "filename", + "sourceMethod": "main", + "destinationMethod": "main", + "sourceLine": 159, + "sourceCode": "filename := os.Args[1]", + "destinationLine": 161, + "destinationCode": "file, err := os.Open(filename)", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "filename", + "line": 159, + "code": "filename := os.Args[1]" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=VXQ3i6GPJDHiBkMZLc5FNxA%2F5C0%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 1464180907, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/e.go", + "destinationFileName": "/scripts/export-csv-full-base/e.go", + "sourceNode": "Args", + "destinationNode": "filename", + "sourceMethod": "main", + "destinationMethod": "main", + "sourceLine": 140, + "sourceCode": "filename := os.Args[1]", + "destinationLine": 142, + "destinationCode": "file, err := os.Open(filename)", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "filename", + "line": 140, + "code": "filename := os.Args[1]" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=Tt57l%2FfVa2%2BwJDmZhg8Yiu09GHY%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -989389595, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/extract_orders.go", + "destinationFileName": "/scripts/export-csv-full-base/extract_orders.go", + "sourceNode": "Args", + "destinationNode": "filename", + "sourceMethod": "main", + "destinationMethod": "main", + "sourceLine": 118, + "sourceCode": "filename := os.Args[1]", + "destinationLine": 120, + "destinationCode": "file, err := os.Open(filename)", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "filename", + "line": 118, + "code": "filename := os.Args[1]" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=MMOOUcm1bpbOIdhY9t%2B6EyBle%2FY%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + } + ] + }, + { + "queryName": "Denial_Of_Service_Resource_Exhaustion", + "queryDescriptionLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast/description/400/13696509829871502452", + "queryId": 13696509829871502452, + "description": "The resource @SourceElement allocated by @SourceMethod in the file @SourceFile at line @SourceLine is prone to resource exhaustion when used by @DestinationMethod in the file @DestinationFile at line @DestinationLine.\n\n", + "vulnerabilitiesTotal": 12, + "queryPath": "Go/Go_Medium_Threat/Denial_Of_Service_Resource_Exhaustion", + "cweId": 400, + "categories": [ + { + "name": "OWASP Top 10 2021", + "subCategories": [ + "A4-Insecure Design" + ] + }, + { + "name": "SANS top 25", + "subCategories": [ + "SANS top 25" + ] + }, + { + "name": "CWE top 25", + "subCategories": [ + "CWE top 25" + ] + }, + { + "name": "MOIS(KISA) Secure Coding 2021", + "subCategories": [ + "MOIS(KISA) Verification and representation of input data" + ] + }, + { + "name": "OWASP ASVS", + "subCategories": [ + "V12 Files and Resources" + ] + } + ], + "vulnerabilities": [ + { + "similarityId": 1854218705, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "destinationFileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "sourceNode": "Args", + "destinationNode": "\u003c", + "sourceMethod": "main", + "destinationMethod": "print", + "sourceLine": 191, + "sourceCode": "filename := os.Args[1]", + "destinationLine": 119, + "destinationCode": "for _, item := range *order.Items {", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "filename", + "line": 191, + "code": "filename := os.Args[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "filename", + "line": 193, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "Open", + "line": 193, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "file", + "line": 193, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "file", + "line": 198, + "code": "defer file.Close()" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "file", + "line": 202, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "NewScanner", + "line": 202, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "scanner", + "line": 202, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "scanner", + "line": 206, + "code": "scanner.Buffer(buf, maxCapacity)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "scanner", + "line": 208, + "code": "for scanner.Scan() {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "scanner", + "line": 209, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "Text", + "line": 209, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "line", + "line": 209, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "line", + "line": 210, + "code": "inputs = append(inputs, line)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "append", + "line": 210, + "code": "inputs = append(inputs, line)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "inputs", + "line": 210, + "code": "inputs = append(inputs, line)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "inputs", + "line": 223, + "code": "processOrders(inputs, concurrency)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "processOrders", + "node": "inputs", + "line": 145, + "code": "func processOrders(inputs []string, concurrencyLimit int) []bool {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "processOrders", + "node": "inputs", + "line": 155, + "code": "for i, line := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "processOrders", + "node": "inputs", + "line": 155, + "code": "for i, line := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "processOrders", + "node": "line", + "line": 155, + "code": "for i, line := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "processOrders", + "node": "line", + "line": 173, + "code": "}(i, line)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "Lambda", + "node": "line", + "line": 157, + "code": "go func(i int, line string) {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "Lambda", + "node": "line", + "line": 162, + "code": "err := json.Unmarshal([]byte(line), \u0026record)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "Lambda", + "node": "Unmarshal", + "line": 162, + "code": "err := json.Unmarshal([]byte(line), \u0026record)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "Lambda", + "node": "encoding/json", + "line": 162, + "code": "err := json.Unmarshal([]byte(line), \u0026record)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "Lambda", + "node": "Address", + "line": 162, + "code": "err := json.Unmarshal([]byte(line), \u0026record)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "Lambda", + "node": "record", + "line": 162, + "code": "err := json.Unmarshal([]byte(line), \u0026record)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "Lambda", + "node": "record", + "line": 167, + "code": "print(record)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "print", + "node": "record", + "line": 97, + "code": "func print(record Record) {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "print", + "node": "record", + "line": 98, + "code": "for _, order := range record.Orders {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "print", + "node": "Orders", + "line": 98, + "code": "for _, order := range record.Orders {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "print", + "node": "order", + "line": 98, + "code": "for _, order := range record.Orders {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "print", + "node": "order", + "line": 119, + "code": "for _, item := range *order.Items {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "print", + "node": "Items", + "line": 119, + "code": "for _, item := range *order.Items {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "print", + "node": "Pointer", + "line": 119, + "code": "for _, item := range *order.Items {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "print", + "node": "len", + "line": 119, + "code": "for _, item := range *order.Items {" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=cgInUQs0zqZy7%2Bi34V0h7rDHBq4%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -1135908474, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "destinationFileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "sourceNode": "Args", + "destinationNode": "\u003c", + "sourceMethod": "main", + "destinationMethod": "print", + "sourceLine": 191, + "sourceCode": "filename := os.Args[1]", + "destinationLine": 98, + "destinationCode": "for _, order := range record.Orders {", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "filename", + "line": 191, + "code": "filename := os.Args[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "filename", + "line": 193, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "Open", + "line": 193, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "file", + "line": 193, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "file", + "line": 198, + "code": "defer file.Close()" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "file", + "line": 202, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "NewScanner", + "line": 202, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "scanner", + "line": 202, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "scanner", + "line": 206, + "code": "scanner.Buffer(buf, maxCapacity)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "scanner", + "line": 208, + "code": "for scanner.Scan() {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "scanner", + "line": 209, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "Text", + "line": 209, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "line", + "line": 209, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "line", + "line": 210, + "code": "inputs = append(inputs, line)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "append", + "line": 210, + "code": "inputs = append(inputs, line)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "inputs", + "line": 210, + "code": "inputs = append(inputs, line)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "inputs", + "line": 223, + "code": "processOrders(inputs, concurrency)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "processOrders", + "node": "inputs", + "line": 145, + "code": "func processOrders(inputs []string, concurrencyLimit int) []bool {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "processOrders", + "node": "inputs", + "line": 155, + "code": "for i, line := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "processOrders", + "node": "inputs", + "line": 155, + "code": "for i, line := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "processOrders", + "node": "line", + "line": 155, + "code": "for i, line := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "processOrders", + "node": "line", + "line": 173, + "code": "}(i, line)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "Lambda", + "node": "line", + "line": 157, + "code": "go func(i int, line string) {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "Lambda", + "node": "line", + "line": 162, + "code": "err := json.Unmarshal([]byte(line), \u0026record)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "Lambda", + "node": "Unmarshal", + "line": 162, + "code": "err := json.Unmarshal([]byte(line), \u0026record)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "Lambda", + "node": "encoding/json", + "line": 162, + "code": "err := json.Unmarshal([]byte(line), \u0026record)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "Lambda", + "node": "Address", + "line": 162, + "code": "err := json.Unmarshal([]byte(line), \u0026record)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "Lambda", + "node": "record", + "line": 162, + "code": "err := json.Unmarshal([]byte(line), \u0026record)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "Lambda", + "node": "record", + "line": 167, + "code": "print(record)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "print", + "node": "record", + "line": 97, + "code": "func print(record Record) {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "print", + "node": "record", + "line": 98, + "code": "for _, order := range record.Orders {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "print", + "node": "Orders", + "line": 98, + "code": "for _, order := range record.Orders {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "print", + "node": "len", + "line": 98, + "code": "for _, order := range record.Orders {" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=%2FdG9mOc3VLYUM3saeMFd88WrV6A%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 32673949, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "destinationFileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "sourceNode": "Args", + "destinationNode": "\u003c", + "sourceMethod": "main", + "destinationMethod": "processOrders", + "sourceLine": 191, + "sourceCode": "filename := os.Args[1]", + "destinationLine": 155, + "destinationCode": "for i, line := range inputs {", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "filename", + "line": 191, + "code": "filename := os.Args[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "filename", + "line": 193, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "Open", + "line": 193, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "file", + "line": 193, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "file", + "line": 198, + "code": "defer file.Close()" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "file", + "line": 202, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "NewScanner", + "line": 202, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "scanner", + "line": 202, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "scanner", + "line": 206, + "code": "scanner.Buffer(buf, maxCapacity)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "scanner", + "line": 208, + "code": "for scanner.Scan() {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "scanner", + "line": 209, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "Text", + "line": 209, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "line", + "line": 209, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "line", + "line": 210, + "code": "inputs = append(inputs, line)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "append", + "line": 210, + "code": "inputs = append(inputs, line)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "inputs", + "line": 210, + "code": "inputs = append(inputs, line)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "inputs", + "line": 223, + "code": "processOrders(inputs, concurrency)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "processOrders", + "node": "inputs", + "line": 145, + "code": "func processOrders(inputs []string, concurrencyLimit int) []bool {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "processOrders", + "node": "inputs", + "line": 155, + "code": "for i, line := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "processOrders", + "node": "len", + "line": 155, + "code": "for i, line := range inputs {" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=R7Rt153i51oEwwbyLc6nApneueQ%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 1091072045, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "destinationFileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "sourceNode": "Args", + "destinationNode": "Scan", + "sourceMethod": "main", + "destinationMethod": "main", + "sourceLine": 191, + "sourceCode": "filename := os.Args[1]", + "destinationLine": 208, + "destinationCode": "for scanner.Scan() {", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "filename", + "line": 191, + "code": "filename := os.Args[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "filename", + "line": 193, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "Open", + "line": 193, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "file", + "line": 193, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "file", + "line": 198, + "code": "defer file.Close()" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "file", + "line": 202, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "NewScanner", + "line": 202, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "scanner", + "line": 202, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "scanner", + "line": 206, + "code": "scanner.Buffer(buf, maxCapacity)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_orders_csv.go", + "method": "main", + "node": "scanner", + "line": 208, + "code": "for scanner.Scan() {" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=%2BXVe1rco%2BeIXZo6ihh7OMabLLYA%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 2103498812, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "destinationFileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "sourceNode": "Args", + "destinationNode": "\u003c", + "sourceMethod": "main", + "destinationMethod": "process", + "sourceLine": 159, + "sourceCode": "filename := os.Args[1]", + "destinationLine": 122, + "destinationCode": "for i, line := range inputs {", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "filename", + "line": 159, + "code": "filename := os.Args[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "filename", + "line": 161, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "Open", + "line": 161, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "file", + "line": 161, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "file", + "line": 166, + "code": "defer file.Close()" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "file", + "line": 170, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "NewScanner", + "line": 170, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "scanner", + "line": 170, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "scanner", + "line": 171, + "code": "for scanner.Scan() {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "scanner", + "line": 172, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "Text", + "line": 172, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "line", + "line": 172, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "line", + "line": 173, + "code": "inputs = append(inputs, line)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "append", + "line": 173, + "code": "inputs = append(inputs, line)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "inputs", + "line": 173, + "code": "inputs = append(inputs, line)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "inputs", + "line": 180, + "code": "process(inputs, concurrency)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "process", + "node": "inputs", + "line": 112, + "code": "func process(inputs []string, concurrencyLimit int) []bool {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "process", + "node": "inputs", + "line": 122, + "code": "for i, line := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "process", + "node": "len", + "line": 122, + "code": "for i, line := range inputs {" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=1xy1UlEUgF4WbuyO49WvU0w56bM%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 840410449, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "destinationFileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "sourceNode": "Args", + "destinationNode": "Scan", + "sourceMethod": "main", + "destinationMethod": "main", + "sourceLine": 159, + "sourceCode": "filename := os.Args[1]", + "destinationLine": 171, + "destinationCode": "for scanner.Scan() {", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "filename", + "line": 159, + "code": "filename := os.Args[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "filename", + "line": 161, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "Open", + "line": 161, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "file", + "line": 161, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "file", + "line": 166, + "code": "defer file.Close()" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "file", + "line": 170, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "NewScanner", + "line": 170, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "scanner", + "line": 170, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/generate_customers_csv.go", + "method": "main", + "node": "scanner", + "line": 171, + "code": "for scanner.Scan() {" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=Tkvsc9AX2%2BFHObW0NaurE%2BwxVz0%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 401019633, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/e.go", + "destinationFileName": "/scripts/export-csv-full-base/e.go", + "sourceNode": "Args", + "destinationNode": "\u003c", + "sourceMethod": "main", + "destinationMethod": "boundedParallelGet", + "sourceLine": 140, + "sourceCode": "filename := os.Args[1]", + "destinationLine": 72, + "destinationCode": "for i, inp := range inputs {", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "filename", + "line": 140, + "code": "filename := os.Args[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "filename", + "line": 142, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "Open", + "line": 142, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "file", + "line": 142, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "file", + "line": 147, + "code": "defer file.Close()" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "file", + "line": 149, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "NewScanner", + "line": 149, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "scanner", + "line": 149, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "scanner", + "line": 150, + "code": "for scanner.Scan() {" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "scanner", + "line": 151, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "Text", + "line": 151, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "line", + "line": 151, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "line", + "line": 152, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "Split", + "line": 152, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "parts", + "line": 152, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "parts", + "line": 154, + "code": "value := parts[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "value", + "line": 154, + "code": "value := parts[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "value", + "line": 166, + "code": "inputs = append(inputs, input{field, value, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "input", + "line": 166, + "code": "inputs = append(inputs, input{field, value, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "append", + "line": 166, + "code": "inputs = append(inputs, input{field, value, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "inputs", + "line": 166, + "code": "inputs = append(inputs, input{field, value, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "inputs", + "line": 172, + "code": "results := boundedParallelGet(inputs, concurrency)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "boundedParallelGet", + "node": "inputs", + "line": 62, + "code": "func boundedParallelGet(inputs []input, concurrencyLimit int) []bool {" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "boundedParallelGet", + "node": "inputs", + "line": 72, + "code": "for i, inp := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "boundedParallelGet", + "node": "len", + "line": 72, + "code": "for i, inp := range inputs {" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=jMOa2QJfnCz7LRuqTdMMTt5ijrU%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -1798981385, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/e.go", + "destinationFileName": "/scripts/export-csv-full-base/extract_orders.go", + "sourceNode": "Args", + "destinationNode": "\u003c", + "sourceMethod": "main", + "destinationMethod": "boundedParallelGet", + "sourceLine": 140, + "sourceCode": "filename := os.Args[1]", + "destinationLine": 62, + "destinationCode": "for i, inp := range inputs {", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "filename", + "line": 140, + "code": "filename := os.Args[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "filename", + "line": 142, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "Open", + "line": 142, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "file", + "line": 142, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "file", + "line": 147, + "code": "defer file.Close()" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "file", + "line": 149, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "NewScanner", + "line": 149, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "scanner", + "line": 149, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "scanner", + "line": 150, + "code": "for scanner.Scan() {" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "scanner", + "line": 151, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "Text", + "line": 151, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "line", + "line": 151, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "line", + "line": 152, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "Split", + "line": 152, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "parts", + "line": 152, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "parts", + "line": 154, + "code": "value := parts[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "value", + "line": 154, + "code": "value := parts[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "value", + "line": 166, + "code": "inputs = append(inputs, input{field, value, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "input", + "line": 166, + "code": "inputs = append(inputs, input{field, value, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "append", + "line": 166, + "code": "inputs = append(inputs, input{field, value, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "inputs", + "line": 166, + "code": "inputs = append(inputs, input{field, value, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "inputs", + "line": 172, + "code": "results := boundedParallelGet(inputs, concurrency)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "boundedParallelGet", + "node": "inputs", + "line": 52, + "code": "func boundedParallelGet(inputs []input, concurrencyLimit int) []bool {" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "boundedParallelGet", + "node": "inputs", + "line": 62, + "code": "for i, inp := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "boundedParallelGet", + "node": "len", + "line": 62, + "code": "for i, inp := range inputs {" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=wo%2FDo2dEMZ4VTgq08e%2BuZR3oIMM%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 617239467, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/e.go", + "destinationFileName": "/scripts/export-csv-full-base/e.go", + "sourceNode": "Args", + "destinationNode": "Scan", + "sourceMethod": "main", + "destinationMethod": "main", + "sourceLine": 140, + "sourceCode": "filename := os.Args[1]", + "destinationLine": 150, + "destinationCode": "for scanner.Scan() {", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "filename", + "line": 140, + "code": "filename := os.Args[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "filename", + "line": 142, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "Open", + "line": 142, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "file", + "line": 142, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "file", + "line": 147, + "code": "defer file.Close()" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "file", + "line": 149, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "NewScanner", + "line": 149, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "scanner", + "line": 149, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "main", + "node": "scanner", + "line": 150, + "code": "for scanner.Scan() {" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=XcaYLeJKppg9dYSs6SgDMGQPqgI%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -687221187, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/extract_orders.go", + "destinationFileName": "/scripts/export-csv-full-base/e.go", + "sourceNode": "Args", + "destinationNode": "\u003c", + "sourceMethod": "main", + "destinationMethod": "boundedParallelGet", + "sourceLine": 118, + "sourceCode": "filename := os.Args[1]", + "destinationLine": 72, + "destinationCode": "for i, inp := range inputs {", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "filename", + "line": 118, + "code": "filename := os.Args[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "filename", + "line": 120, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "Open", + "line": 120, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "file", + "line": 120, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "file", + "line": 125, + "code": "defer file.Close()" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "file", + "line": 127, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "NewScanner", + "line": 127, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "scanner", + "line": 127, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "scanner", + "line": 128, + "code": "for scanner.Scan() {" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "scanner", + "line": 129, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "Text", + "line": 129, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "line", + "line": 129, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "line", + "line": 130, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "Split", + "line": 130, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "parts", + "line": 130, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "parts", + "line": 131, + "code": "customer_id := parts[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "customer_id", + "line": 131, + "code": "customer_id := parts[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "customer_id", + "line": 133, + "code": "inputs = append(inputs, input{customer_id, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "input", + "node": "customer_id", + "line": 48, + "code": "customer_id string" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "input", + "node": "customer_id", + "line": 48, + "code": "customer_id string" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "input", + "node": "customer_id", + "line": 48, + "code": "customer_id string" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "input", + "line": 133, + "code": "inputs = append(inputs, input{customer_id, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "append", + "line": 133, + "code": "inputs = append(inputs, input{customer_id, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "inputs", + "line": 133, + "code": "inputs = append(inputs, input{customer_id, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "inputs", + "line": 139, + "code": "results := boundedParallelGet(inputs, concurrency)" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "boundedParallelGet", + "node": "inputs", + "line": 62, + "code": "func boundedParallelGet(inputs []input, concurrencyLimit int) []bool {" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "boundedParallelGet", + "node": "inputs", + "line": 72, + "code": "for i, inp := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/e.go", + "method": "boundedParallelGet", + "node": "len", + "line": 72, + "code": "for i, inp := range inputs {" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=UlC%2FQ%2BFuFtk2Km%2FQwNC%2Bhz6unac%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -2037475029, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/extract_orders.go", + "destinationFileName": "/scripts/export-csv-full-base/extract_orders.go", + "sourceNode": "Args", + "destinationNode": "\u003c", + "sourceMethod": "main", + "destinationMethod": "boundedParallelGet", + "sourceLine": 118, + "sourceCode": "filename := os.Args[1]", + "destinationLine": 62, + "destinationCode": "for i, inp := range inputs {", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "filename", + "line": 118, + "code": "filename := os.Args[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "filename", + "line": 120, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "Open", + "line": 120, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "file", + "line": 120, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "file", + "line": 125, + "code": "defer file.Close()" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "file", + "line": 127, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "NewScanner", + "line": 127, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "scanner", + "line": 127, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "scanner", + "line": 128, + "code": "for scanner.Scan() {" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "scanner", + "line": 129, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "Text", + "line": 129, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "line", + "line": 129, + "code": "line := scanner.Text()" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "line", + "line": 130, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "Split", + "line": 130, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "parts", + "line": 130, + "code": "parts := strings.Split(line, \"@\")" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "parts", + "line": 131, + "code": "customer_id := parts[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "customer_id", + "line": 131, + "code": "customer_id := parts[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "customer_id", + "line": 133, + "code": "inputs = append(inputs, input{customer_id, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "input", + "node": "customer_id", + "line": 48, + "code": "customer_id string" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "input", + "node": "customer_id", + "line": 48, + "code": "customer_id string" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "input", + "node": "customer_id", + "line": 48, + "code": "customer_id string" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "input", + "line": 133, + "code": "inputs = append(inputs, input{customer_id, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "append", + "line": 133, + "code": "inputs = append(inputs, input{customer_id, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "inputs", + "line": 133, + "code": "inputs = append(inputs, input{customer_id, url})" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "inputs", + "line": 139, + "code": "results := boundedParallelGet(inputs, concurrency)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "boundedParallelGet", + "node": "inputs", + "line": 52, + "code": "func boundedParallelGet(inputs []input, concurrencyLimit int) []bool {" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "boundedParallelGet", + "node": "inputs", + "line": 62, + "code": "for i, inp := range inputs {" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "boundedParallelGet", + "node": "len", + "line": 62, + "code": "for i, inp := range inputs {" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=yI9rwIgdTYRg5Uv6klXjsscLNHo%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -1158459855, + "status": "Recurrent", + "state": "To Verify", + "severity": "Medium", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/extract_orders.go", + "destinationFileName": "/scripts/export-csv-full-base/extract_orders.go", + "sourceNode": "Args", + "destinationNode": "Scan", + "sourceMethod": "main", + "destinationMethod": "main", + "sourceLine": 118, + "sourceCode": "filename := os.Args[1]", + "destinationLine": 128, + "destinationCode": "for scanner.Scan() {", + "nodes": [ + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "filename", + "line": 118, + "code": "filename := os.Args[1]" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "filename", + "line": 120, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "Open", + "line": 120, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "file", + "line": 120, + "code": "file, err := os.Open(filename)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "file", + "line": 125, + "code": "defer file.Close()" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "file", + "line": 127, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "NewScanner", + "line": 127, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "scanner", + "line": 127, + "code": "scanner := bufio.NewScanner(file)" + }, + { + "fileName": "/scripts/export-csv-full-base/extract_orders.go", + "method": "main", + "node": "scanner", + "line": 128, + "code": "for scanner.Scan() {" + } + ], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=oFBUJSl5ZaU2n508T8beHzxwdKg%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + } + ] + }, + { + "queryName": "TruffleHog_HighEntropy_Strings", + "queryDescriptionLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast/description/798/2386285962878890935", + "queryId": 2386285962878890935, + "description": "The application uses the hard-coded password @SourceElement for authentication purposes, either using it to verify users' identities, or to access another remote system. This password at line @SourceLine of @SourceFile appears in the code, implying it is accessible to anyone with source code access, and cannot be changed without rebuilding the application.", + "vulnerabilitiesTotal": 56, + "queryPath": "Java/Java_Low_Visibility/TruffleHog_HighEntropy_Strings", + "cweId": 798, + "categories": [ + { + "name": "OWASP ASVS", + "subCategories": [ + "V06 Stored Cryptography" + ] + }, + { + "name": "OWASP Top 10 2021", + "subCategories": [ + "A7-Identification and Authentication Failures" + ] + }, + { + "name": "SANS top 25", + "subCategories": [ + "SANS top 25" + ] + }, + { + "name": "CWE top 25", + "subCategories": [ + "CWE top 25" + ] + }, + { + "name": "MOIS(KISA) Secure Coding 2021", + "subCategories": [ + "MOIS(KISA) Security Functions" + ] + } + ], + "vulnerabilities": [ + { + "similarityId": -199619872, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-04-11T04:43:00Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/jobs/SplitWrongCustomerJobIntegrationTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/jobs/SplitWrongCustomerJobIntegrationTest.kt", + "sourceNode": "a24dd2f3-e7bd-4f35-9530-28c023a6ff00", + "destinationNode": "a24dd2f3-e7bd-4f35-9530-28c023a6ff00", + "sourceLine": 330, + "sourceCode": "originId = \"a24dd2f3-e7bd-4f35-9530-28c023a6ff00\",", + "destinationLine": 330, + "destinationCode": "originId = \"a24dd2f3-e7bd-4f35-9530-28c023a6ff00\",", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=O9dg9o7XYmx6BcTGcu03wyKMpGM%3D", + "firstScanID": "12f6a247-2e80-497c-a975-20699ef3a6be", + "notes": [] + }, + { + "similarityId": -1700918878, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-04-11T04:43:00Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/jobs/SplitWrongCustomerJobIntegrationTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/jobs/SplitWrongCustomerJobIntegrationTest.kt", + "sourceNode": "a24dd2f3-e7bd-4f35-9530-28c023a6ff00", + "destinationNode": "a24dd2f3-e7bd-4f35-9530-28c023a6ff00", + "sourceLine": 367, + "sourceCode": "originId = \"a24dd2f3-e7bd-4f35-9530-28c023a6ff00\"", + "destinationLine": 367, + "destinationCode": "originId = \"a24dd2f3-e7bd-4f35-9530-28c023a6ff00\"", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=aeXsqhk0uGM2ZYa1Q8syZB0DZGY%3D", + "firstScanID": "12f6a247-2e80-497c-a975-20699ef3a6be", + "notes": [] + }, + { + "similarityId": 1147546504, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-04-11T04:43:00Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/jobs/SplitWrongCustomerJobIntegrationTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/jobs/SplitWrongCustomerJobIntegrationTest.kt", + "sourceNode": "a24dd2f3-e7bd-4f35-9530-28c023a6ff00", + "destinationNode": "a24dd2f3-e7bd-4f35-9530-28c023a6ff00", + "sourceLine": 247, + "sourceCode": "value = \"a24dd2f3-e7bd-4f35-9530-28c023a6ff00\"", + "destinationLine": 247, + "destinationCode": "value = \"a24dd2f3-e7bd-4f35-9530-28c023a6ff00\"", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=4IhwFXitst3KXs6jQ2dvZGlfbrU%3D", + "firstScanID": "12f6a247-2e80-497c-a975-20699ef3a6be", + "notes": [] + }, + { + "similarityId": 1147546504, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-04-11T04:43:00Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/jobs/SplitWrongCustomerJobIntegrationTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/jobs/SplitWrongCustomerJobIntegrationTest.kt", + "sourceNode": "a24dd2f3-e7bd-4f35-9530-28c023a6ff00", + "destinationNode": "a24dd2f3-e7bd-4f35-9530-28c023a6ff00", + "sourceLine": 278, + "sourceCode": "value = \"a24dd2f3-e7bd-4f35-9530-28c023a6ff00\"", + "destinationLine": 278, + "destinationCode": "value = \"a24dd2f3-e7bd-4f35-9530-28c023a6ff00\"", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=JdU3IsDJGqFDUpSuUAHQ6I%2F6jyY%3D", + "firstScanID": "12f6a247-2e80-497c-a975-20699ef3a6be", + "notes": [] + }, + { + "similarityId": 1086961550, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-27T18:15:41Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/DefaultValues.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/DefaultValues.kt", + "sourceNode": "b256f34f-71b3-42b0-9c2b-9699cb1c9a46", + "destinationNode": "b256f34f-71b3-42b0-9c2b-9699cb1c9a46", + "sourceLine": 56, + "sourceCode": "const val OTHER_CUSTOMER_ID = \"b256f34f-71b3-42b0-9c2b-9699cb1c9a46\"", + "destinationLine": 56, + "destinationCode": "const val OTHER_CUSTOMER_ID = \"b256f34f-71b3-42b0-9c2b-9699cb1c9a46\"", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=W5EkYqK4r1wsIgjmRl4i2gbRfew%3D", + "firstScanID": "674aaaba-7622-4773-bf5c-c69b46724e05", + "notes": [] + }, + { + "similarityId": 1085937290, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-26T17:55:36Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/WebUserCommandBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/WebUserCommandBuilder.kt", + "sourceNode": "f5eab4ab-d5bf-4183-aa1b-4f8154df3411", + "destinationNode": "f5eab4ab-d5bf-4183-aa1b-4f8154df3411", + "sourceLine": 124, + "sourceCode": "\"mp_deviceid\":\"f5eab4ab-d5bf-4183-aa1b-4f8154df3411\",", + "destinationLine": 124, + "destinationCode": "\"mp_deviceid\":\"f5eab4ab-d5bf-4183-aa1b-4f8154df3411\",", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=dmB1Dwrh4xKejo%2ByPNnBebfWReU%3D", + "firstScanID": "29a41414-4452-4a67-9f08-ac7d6556e427", + "notes": [] + }, + { + "similarityId": -534264276, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-26T17:55:36Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/WebUserCommandBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/WebUserCommandBuilder.kt", + "sourceNode": "e6c8ddc3-b12c-4a82-9c26-ecf4f637c65b", + "destinationNode": "e6c8ddc3-b12c-4a82-9c26-ecf4f637c65b", + "sourceLine": 102, + "sourceCode": "\"source_request_id\":\"e6c8ddc3-b12c-4a82-9c26-ecf4f637c65b\",", + "destinationLine": 102, + "destinationCode": "\"source_request_id\":\"e6c8ddc3-b12c-4a82-9c26-ecf4f637c65b\",", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=VfFFt2NzonsfBRUx71ImKfd4qL4%3D", + "firstScanID": "29a41414-4452-4a67-9f08-ac7d6556e427", + "notes": [] + }, + { + "similarityId": -1634429672, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-26T17:55:36Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/WebUserCommandBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/WebUserCommandBuilder.kt", + "sourceNode": "eef028aa-e884-43e4-8a1e-13fea8107fee", + "destinationNode": "eef028aa-e884-43e4-8a1e-13fea8107fee", + "sourceLine": 101, + "sourceCode": "\"message_id\":\"eef028aa-e884-43e4-8a1e-13fea8107fee\",", + "destinationLine": 101, + "destinationCode": "\"message_id\":\"eef028aa-e884-43e4-8a1e-13fea8107fee\",", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=KDxwztm2HjXSkwoX809shw%2Fjuy8%3D", + "firstScanID": "29a41414-4452-4a67-9f08-ac7d6556e427", + "notes": [] + }, + { + "similarityId": 1271592864, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-26T17:55:36Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/WebUserCommandBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/WebUserCommandBuilder.kt", + "sourceNode": "3C9ACCAC-4E75-40BC-A50E-D5D549F4580B", + "destinationNode": "3C9ACCAC-4E75-40BC-A50E-D5D549F4580B", + "sourceLine": 88, + "sourceCode": "\"session_uuid\":\"3C9ACCAC-4E75-40BC-A50E-D5D549F4580B\",", + "destinationLine": 88, + "destinationCode": "\"session_uuid\":\"3C9ACCAC-4E75-40BC-A50E-D5D549F4580B\",", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=NrAj7Kl84SAdUFx%2Biljj8FS0kFU%3D", + "firstScanID": "29a41414-4452-4a67-9f08-ac7d6556e427", + "notes": [] + }, + { + "similarityId": -1005063728, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-26T17:55:36Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/WebUserCommandBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/WebUserCommandBuilder.kt", + "sourceNode": "-2418825570255719384", + "destinationNode": "-2418825570255719384", + "sourceLine": 87, + "sourceCode": "\"session_id\":\"-2418825570255719384\",", + "destinationLine": 87, + "destinationCode": "\"session_id\":\"-2418825570255719384\",", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=B67HUxR1L%2BZWYzBwaWqFpM1G6ZU%3D", + "firstScanID": "29a41414-4452-4a67-9f08-ac7d6556e427", + "notes": [] + }, + { + "similarityId": -951075168, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-26T17:55:36Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/WebUserCommandBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/WebUserCommandBuilder.kt", + "sourceNode": "36f88d79-7597-4097-7380-a06ed98aac7a", + "destinationNode": "36f88d79-7597-4097-7380-a06ed98aac7a", + "sourceLine": 86, + "sourceCode": "\"source_message_id\":\"36f88d79-7597-4097-7380-a06ed98aac7a\",", + "destinationLine": 86, + "destinationCode": "\"source_message_id\":\"36f88d79-7597-4097-7380-a06ed98aac7a\",", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=2W72khTVyVCrpA6piW2gYfWWq%2BM%3D", + "firstScanID": "29a41414-4452-4a67-9f08-ac7d6556e427", + "notes": [] + }, + { + "similarityId": 607023392, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/resources/wiremock/order/order.json", + "destinationFileName": "/src/test/resources/wiremock/order/order.json", + "sourceNode": "80430281-970E-4027-AC68-2131D1D77DC8", + "destinationNode": "80430281-970E-4027-AC68-2131D1D77DC8", + "sourceLine": 357, + "sourceCode": "\"grouper\": \"80430281-970E-4027-AC68-2131D1D77DC8\",", + "destinationLine": 357, + "destinationCode": "\"grouper\": \"80430281-970E-4027-AC68-2131D1D77DC8\",", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=yzFRItG%2Fl39MdZUOEgH0ers6V%2FY%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -282363872, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/resources/wiremock/order/order.json", + "destinationFileName": "/src/test/resources/wiremock/order/order.json", + "sourceNode": "2D023F2A-FD9F-4282-B36C-280CC0C2FD72", + "destinationNode": "2D023F2A-FD9F-4282-B36C-280CC0C2FD72", + "sourceLine": 223, + "sourceCode": "\"grouper\": \"2D023F2A-FD9F-4282-B36C-280CC0C2FD72\",", + "destinationLine": 223, + "destinationCode": "\"grouper\": \"2D023F2A-FD9F-4282-B36C-280CC0C2FD72\",", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=6pYCwEjzMfg8QUD5gi%2FbLsahHBg%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -1674015712, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/resources/wiremock/order/order.json", + "destinationFileName": "/src/test/resources/wiremock/order/order.json", + "sourceNode": "D12378CD-0FFA-401A-9EC9-6F01312746FA", + "destinationNode": "D12378CD-0FFA-401A-9EC9-6F01312746FA", + "sourceLine": 4, + "sourceCode": "\"code\": \"D12378CD-0FFA-401A-9EC9-6F01312746FA\",", + "destinationLine": 4, + "destinationCode": "\"code\": \"D12378CD-0FFA-401A-9EC9-6F01312746FA\",", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=xdtersnfgXprNY%2BQT%2BgZ0CdRCOM%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 2062432160, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/kafka/listener/ecommerce/OrderStatusDeliveryGroupConsumerTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/kafka/listener/ecommerce/OrderStatusDeliveryGroupConsumerTest.kt", + "sourceNode": "880CCCB5-2267-4A04-A963-24DEA02F1A14", + "destinationNode": "880CCCB5-2267-4A04-A963-24DEA02F1A14", + "sourceLine": 150, + "sourceCode": "\" \\\"token\\\": \\\"880CCCB5-2267-4A04-A963-24DEA02F1A14\\\"\" +", + "destinationLine": 150, + "destinationCode": "\" \\\"token\\\": \\\"880CCCB5-2267-4A04-A963-24DEA02F1A14\\\"\" +", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=IMbyW5EDThudp5ULJW%2FTvQDjc3E%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 2062432160, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/kafka/listener/ecommerce/OrderStatusDeliveryGroupConsumerTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/kafka/listener/ecommerce/OrderStatusDeliveryGroupConsumerTest.kt", + "sourceNode": "880CCCB5-2267-4A04-A963-24DEA02F1A14", + "destinationNode": "880CCCB5-2267-4A04-A963-24DEA02F1A14", + "sourceLine": 42, + "sourceCode": "\" \\\"token\\\": \\\"880CCCB5-2267-4A04-A963-24DEA02F1A14\\\"\" +", + "destinationLine": 42, + "destinationCode": "\" \\\"token\\\": \\\"880CCCB5-2267-4A04-A963-24DEA02F1A14\\\"\" +", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=WreWxISEHGAGFChGwK2%2FE%2FRhEyg%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -641287918, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/kafka/listener/ecommerce/OrderStatusDeliveryGroupConsumerIntegrationTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/kafka/listener/ecommerce/OrderStatusDeliveryGroupConsumerIntegrationTest.kt", + "sourceNode": "71B00656-5B39-4625-BDA4-B066171652B6", + "destinationNode": "71B00656-5B39-4625-BDA4-B066171652B6", + "sourceLine": 42, + "sourceCode": "\" \\\"token\\\": \\\"71B00656-5B39-4625-BDA4-B066171652B6\\\"\" +", + "destinationLine": 42, + "destinationCode": "\" \\\"token\\\": \\\"71B00656-5B39-4625-BDA4-B066171652B6\\\"\" +", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=2rFxRpTHIeetsR%2FLOJOQp%2BOFkZ0%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -437932192, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/kafka/listener/ecommerce/CustomerTermsAcceptConsumerTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/kafka/listener/ecommerce/CustomerTermsAcceptConsumerTest.kt", + "sourceNode": "cd6ce515-29b4-4d1b-a415-da10d3d0bcd0", + "destinationNode": "cd6ce515-29b4-4d1b-a415-da10d3d0bcd0", + "sourceLine": 159, + "sourceCode": "\" \\\"id\\\": \\\"cd6ce515-29b4-4d1b-a415-da10d3d0bcd0\\\",\" +", + "destinationLine": 159, + "destinationCode": "\" \\\"id\\\": \\\"cd6ce515-29b4-4d1b-a415-da10d3d0bcd0\\\",\" +", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=6AcES%2FE6OYSEVZoS%2BZBSMYUNd8g%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -1615769098, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/kafka/listener/ecommerce/CustomerTermsAcceptConsumerTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/kafka/listener/ecommerce/CustomerTermsAcceptConsumerTest.kt", + "sourceNode": "cd6ce515-29b4-4d1b-a415-da10d3d0bcd0", + "destinationNode": "cd6ce515-29b4-4d1b-a415-da10d3d0bcd0", + "sourceLine": 116, + "sourceCode": "id shouldBeEqualTo \"cd6ce515-29b4-4d1b-a415-da10d3d0bcd0\"", + "destinationLine": 116, + "destinationCode": "id shouldBeEqualTo \"cd6ce515-29b4-4d1b-a415-da10d3d0bcd0\"", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=q4Yn90GH9JVTqHSWrD9UHun%2F1xM%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -437932192, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/kafka/listener/ecommerce/CustomerTermsAcceptConsumerTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/kafka/listener/ecommerce/CustomerTermsAcceptConsumerTest.kt", + "sourceNode": "cd6ce515-29b4-4d1b-a415-da10d3d0bcd0", + "destinationNode": "cd6ce515-29b4-4d1b-a415-da10d3d0bcd0", + "sourceLine": 29, + "sourceCode": "\" \\\"id\\\": \\\"cd6ce515-29b4-4d1b-a415-da10d3d0bcd0\\\",\" +", + "destinationLine": 29, + "destinationCode": "\" \\\"id\\\": \\\"cd6ce515-29b4-4d1b-a415-da10d3d0bcd0\\\",\" +", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=bHzhOK9ZN76yub1vNK2JGbF4xm0%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 1276498382, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/domain/service/NotifyPersonServiceTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/domain/service/NotifyPersonServiceTest.kt", + "sourceNode": "ce79829a-6aa1-4a21-8753-f97a76b8153b", + "destinationNode": "ce79829a-6aa1-4a21-8753-f97a76b8153b", + "sourceLine": 59, + "sourceCode": "val customerId = \"ce79829a-6aa1-4a21-8753-f97a76b8153b\"", + "destinationLine": 59, + "destinationCode": "val customerId = \"ce79829a-6aa1-4a21-8753-f97a76b8153b\"", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=pCC0g4QtmZaeOErmOYZo4Cg%2B%2Fmk%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 1276498382, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/domain/service/NotifyPersonServiceTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/domain/service/NotifyPersonServiceTest.kt", + "sourceNode": "ce79829a-6aa1-4a21-8753-f97a76b8153b", + "destinationNode": "ce79829a-6aa1-4a21-8753-f97a76b8153b", + "sourceLine": 42, + "sourceCode": "val customerId = \"ce79829a-6aa1-4a21-8753-f97a76b8153b\"", + "destinationLine": 42, + "destinationCode": "val customerId = \"ce79829a-6aa1-4a21-8753-f97a76b8153b\"", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=kVFdQhfKQRtzBC7%2B1Tfu%2BFpHbaY%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 1276498382, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/domain/service/NotifyPersonServiceTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/domain/service/NotifyPersonServiceTest.kt", + "sourceNode": "ce79829a-6aa1-4a21-8753-f97a76b8153b", + "destinationNode": "ce79829a-6aa1-4a21-8753-f97a76b8153b", + "sourceLine": 23, + "sourceCode": "val customerId = \"ce79829a-6aa1-4a21-8753-f97a76b8153b\"", + "destinationLine": 23, + "destinationCode": "val customerId = \"ce79829a-6aa1-4a21-8753-f97a76b8153b\"", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=%2BDP7T9e1aysYpAFo9ChlKIW2u2U%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -800650046, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventServiceIntegrationTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/domain/service/CustomerFromEventServiceIntegrationTest.kt", + "sourceNode": "1699b89c-6b60-4419-a4a0-02ea6004a06c", + "destinationNode": "1699b89c-6b60-4419-a4a0-02ea6004a06c", + "sourceLine": 45, + "sourceCode": "val mParticleDAS = \"1699b89c-6b60-4419-a4a0-02ea6004a06c\"", + "destinationLine": 45, + "destinationCode": "val mParticleDAS = \"1699b89c-6b60-4419-a4a0-02ea6004a06c\"", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=JCsJ2sy36Q2ICnD7%2FhtKEM9pOFw%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -722925024, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/infrastructure/mParticle/DataPlanVersionBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/infrastructure/mParticle/DataPlanVersionBuilder.kt", + "sourceNode": "RxZztwf8SoT05MGmvonOcIseIT8LA48C", + "destinationNode": "RxZztwf8SoT05MGmvonOcIseIT8LA48C", + "sourceLine": 16, + "sourceCode": "createdBy = \"client_id:RxZztwf8SoT05MGmvonOcIseIT8LA48C\",", + "destinationLine": 16, + "destinationCode": "createdBy = \"client_id:RxZztwf8SoT05MGmvonOcIseIT8LA48C\",", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=hjXPGjUR60BXLoFCeM6IUJxNOEE%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -1230730176, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/infrastructure/mParticle/DataPlanBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/infrastructure/mParticle/DataPlanBuilder.kt", + "sourceNode": "Rxbrs8SoT05MGmvonOcIs346LA48C", + "destinationNode": "Rxbrs8SoT05MGmvonOcIs346LA48C", + "sourceLine": 17, + "sourceCode": "createdBy = \"client_id:Rxbrs8SoT05MGmvonOcIs346LA48C\",", + "destinationLine": 17, + "destinationCode": "createdBy = \"client_id:Rxbrs8SoT05MGmvonOcIs346LA48C\",", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=qv2Qr904TfevDwaX0wnTMvJPBZI%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 2120657286, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/DefaultValues.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/DefaultValues.kt", + "sourceNode": "a83142bd-022d-4d5b-849d-cc2dec0b9ae4", + "destinationNode": "a83142bd-022d-4d5b-849d-cc2dec0b9ae4", + "sourceLine": 30, + "sourceCode": "const val MPARTICLE_DAS = \"a83142bd-022d-4d5b-849d-cc2dec0b9ae4\"", + "destinationLine": 30, + "destinationCode": "const val MPARTICLE_DAS = \"a83142bd-022d-4d5b-849d-cc2dec0b9ae4\"", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=%2Fd1okGTQdJMUtrOjd%2BOYn5ybxmY%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 2105735882, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/DefaultValues.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/DefaultValues.kt", + "sourceNode": "a256f34f-71b3-42b0-9c2b-9699cb1c9a22", + "destinationNode": "a256f34f-71b3-42b0-9c2b-9699cb1c9a22", + "sourceLine": 28, + "sourceCode": "const val CUSTOMER_ID = \"a256f34f-71b3-42b0-9c2b-9699cb1c9a22\"", + "destinationLine": 28, + "destinationCode": "const val CUSTOMER_ID = \"a256f34f-71b3-42b0-9c2b-9699cb1c9a22\"", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=dliYfOKmJG8rWRB8vKjEl1%2BQs8c%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -1649761718, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/DefaultValues.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/DefaultValues.kt", + "sourceNode": "69971bc1-c624-461b-a669-7f8d407f4debR", + "destinationNode": "69971bc1-c624-461b-a669-7f8d407f4debR", + "sourceLine": 19, + "sourceCode": "const val AMPLITUDE_DEVICE_ID = \"69971bc1-c624-461b-a669-7f8d407f4debR\"", + "destinationLine": 19, + "destinationCode": "const val AMPLITUDE_DEVICE_ID = \"69971bc1-c624-461b-a669-7f8d407f4debR\"", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=voxh55OeaUAE7QwEUzHga24oNAE%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 858642912, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/application/services/EventServiceTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/application/services/EventServiceTest.kt", + "sourceNode": "6ead3404-c36b-46b0-b042-885b9f0065c2", + "destinationNode": "6ead3404-c36b-46b0-b042-885b9f0065c2", + "sourceLine": 128, + "sourceCode": "val customerId = \"6ead3404-c36b-46b0-b042-885b9f0065c2\"", + "destinationLine": 128, + "destinationCode": "val customerId = \"6ead3404-c36b-46b0-b042-885b9f0065c2\"", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=PDa0jezCLGesOMK5zn2VENVseGU%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 1091204880, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/application/services/EventServiceTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/application/services/EventServiceTest.kt", + "sourceNode": "d2c129a3-4e92-4268-b10a-33db5fdf99b6", + "destinationNode": "d2c129a3-4e92-4268-b10a-33db5fdf99b6", + "sourceLine": 110, + "sourceCode": "val customerId = \"d2c129a3-4e92-4268-b10a-33db5fdf99b6\"", + "destinationLine": 110, + "destinationCode": "val customerId = \"d2c129a3-4e92-4268-b10a-33db5fdf99b6\"", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=4SLZZMava4rpd5rR0N%2FXP42tNf8%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -1552080448, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/application/services/EventServiceTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/application/services/EventServiceTest.kt", + "sourceNode": "9a8af21b-10ac-41c1-badc-eed75dc7cb34", + "destinationNode": "9a8af21b-10ac-41c1-badc-eed75dc7cb34", + "sourceLine": 87, + "sourceCode": "val customerId = \"9a8af21b-10ac-41c1-badc-eed75dc7cb34\"", + "destinationLine": 87, + "destinationCode": "val customerId = \"9a8af21b-10ac-41c1-badc-eed75dc7cb34\"", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=ogFx3gwKSEarScGYrHPAbk0A1Yg%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 807313472, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "sourceNode": "e097e8cb-b2c8-4eb6-9b2b", + "destinationNode": "e097e8cb-b2c8-4eb6-9b2b", + "sourceLine": 99, + "sourceCode": "response.body shouldBeEqualTo \"Mó paia o customer e097e8cb-b2c8-4eb6-9b2b\"", + "destinationLine": 99, + "destinationCode": "response.body shouldBeEqualTo \"Mó paia o customer e097e8cb-b2c8-4eb6-9b2b\"", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=%2FxuLNPuXzWjnf%2FIV5acCOCOogwQ%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -325339936, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "sourceNode": "e097e8cb-b2c8-4eb6-9b2b", + "destinationNode": "e097e8cb-b2c8-4eb6-9b2b", + "sourceLine": 96, + "sourceCode": "val response = customerController.deletePerson(\"e097e8cb-b2c8-4eb6-9b2b\", Company.FISIA)", + "destinationLine": 96, + "destinationCode": "val response = customerController.deletePerson(\"e097e8cb-b2c8-4eb6-9b2b\", Company.FISIA)", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=VnpF2w6sXi4LhzOEduXu5h0ZsMQ%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 354270058, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "sourceNode": "e097e8cb-b2c8-4eb6-9b2b", + "destinationNode": "e097e8cb-b2c8-4eb6-9b2b", + "sourceLine": 94, + "sourceCode": "} throws Exception(\"Mó paia o customer e097e8cb-b2c8-4eb6-9b2b\")", + "destinationLine": 94, + "destinationCode": "} throws Exception(\"Mó paia o customer e097e8cb-b2c8-4eb6-9b2b\")", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=MVdBvIi1P%2FnQXmbdz3R52GesfQ0%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -677940736, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "sourceNode": "e097e8cb-b2c8-4eb6-9b2b", + "destinationNode": "e097e8cb-b2c8-4eb6-9b2b", + "sourceLine": 93, + "sourceCode": "deletePersonService.deletePerson(\"e097e8cb-b2c8-4eb6-9b2b\", Company.FISIA)", + "destinationLine": 93, + "destinationCode": "deletePersonService.deletePerson(\"e097e8cb-b2c8-4eb6-9b2b\", Company.FISIA)", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=MjUS6x4bsdtcxWVYx2SXY7mEpkY%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -930739680, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "sourceNode": "e097e8cb-b2c8-4eb6-9b2b", + "destinationNode": "e097e8cb-b2c8-4eb6-9b2b", + "sourceLine": 86, + "sourceCode": "verify { deletePersonService.deletePerson(\"e097e8cb-b2c8-4eb6-9b2b\", Company.FISIA) }", + "destinationLine": 86, + "destinationCode": "verify { deletePersonService.deletePerson(\"e097e8cb-b2c8-4eb6-9b2b\", Company.FISIA) }", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=4AZQoMXuMO8rJJtdSvwxN5Qv1rI%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -325339936, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "sourceNode": "e097e8cb-b2c8-4eb6-9b2b", + "destinationNode": "e097e8cb-b2c8-4eb6-9b2b", + "sourceLine": 84, + "sourceCode": "val response = customerController.deletePerson(\"e097e8cb-b2c8-4eb6-9b2b\", Company.FISIA)", + "destinationLine": 84, + "destinationCode": "val response = customerController.deletePerson(\"e097e8cb-b2c8-4eb6-9b2b\", Company.FISIA)", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=d%2Fscmqd4YuD6yAHZxJVWGiE3dVo%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -677940736, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "sourceNode": "e097e8cb-b2c8-4eb6-9b2b", + "destinationNode": "e097e8cb-b2c8-4eb6-9b2b", + "sourceLine": 81, + "sourceCode": "deletePersonService.deletePerson(\"e097e8cb-b2c8-4eb6-9b2b\", Company.FISIA)", + "destinationLine": 81, + "destinationCode": "deletePersonService.deletePerson(\"e097e8cb-b2c8-4eb6-9b2b\", Company.FISIA)", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=2V6J6ZgTXix8CSjYWr5LRNOGX8E%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -930739680, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "sourceNode": "e097e8cb-b2c8-4eb6-9b2b", + "destinationNode": "e097e8cb-b2c8-4eb6-9b2b", + "sourceLine": 74, + "sourceCode": "verify { deletePersonService.deletePerson(\"e097e8cb-b2c8-4eb6-9b2b\", Company.FISIA) }", + "destinationLine": 74, + "destinationCode": "verify { deletePersonService.deletePerson(\"e097e8cb-b2c8-4eb6-9b2b\", Company.FISIA) }", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=8P2DBkqYp4tjSXi%2FporlNwjTRTI%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -325339936, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "sourceNode": "e097e8cb-b2c8-4eb6-9b2b", + "destinationNode": "e097e8cb-b2c8-4eb6-9b2b", + "sourceLine": 72, + "sourceCode": "val response = customerController.deletePerson(\"e097e8cb-b2c8-4eb6-9b2b\", Company.FISIA)", + "destinationLine": 72, + "destinationCode": "val response = customerController.deletePerson(\"e097e8cb-b2c8-4eb6-9b2b\", Company.FISIA)", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=Z4uYa203KvYQafd166scZcCGoRk%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -677940736, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "sourceNode": "e097e8cb-b2c8-4eb6-9b2b", + "destinationNode": "e097e8cb-b2c8-4eb6-9b2b", + "sourceLine": 69, + "sourceCode": "deletePersonService.deletePerson(\"e097e8cb-b2c8-4eb6-9b2b\", Company.FISIA)", + "destinationLine": 69, + "destinationCode": "deletePersonService.deletePerson(\"e097e8cb-b2c8-4eb6-9b2b\", Company.FISIA)", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=31%2FU0p%2BSNFn4m6RWkdui724%2BI7g%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -533248960, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "sourceNode": "62bda6f6-7934-4bbc-a9a5-76fd48596dd9", + "destinationNode": "62bda6f6-7934-4bbc-a9a5-76fd48596dd9", + "sourceLine": 51, + "sourceCode": "val customerId = \"62bda6f6-7934-4bbc-a9a5-76fd48596dd9\"", + "destinationLine": 51, + "destinationCode": "val customerId = \"62bda6f6-7934-4bbc-a9a5-76fd48596dd9\"", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=DEQAxnJ8DprxBP5wJA%2F%2FAO1jxFM%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -533248960, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "sourceNode": "62bda6f6-7934-4bbc-a9a5-76fd48596dd9", + "destinationNode": "62bda6f6-7934-4bbc-a9a5-76fd48596dd9", + "sourceLine": 40, + "sourceCode": "val customerId = \"62bda6f6-7934-4bbc-a9a5-76fd48596dd9\"", + "destinationLine": 40, + "destinationCode": "val customerId = \"62bda6f6-7934-4bbc-a9a5-76fd48596dd9\"", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=QGxVhyAAbN8ULtkgSp1RBVHMkhs%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -533248960, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/api/CustomerControllerTest.kt", + "sourceNode": "62bda6f6-7934-4bbc-a9a5-76fd48596dd9", + "destinationNode": "62bda6f6-7934-4bbc-a9a5-76fd48596dd9", + "sourceLine": 29, + "sourceCode": "val customerId = \"62bda6f6-7934-4bbc-a9a5-76fd48596dd9\"", + "destinationLine": 29, + "destinationCode": "val customerId = \"62bda6f6-7934-4bbc-a9a5-76fd48596dd9\"", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=h3JqYH0DrmkQKi1U7RBGNGo4dgc%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 1776136322, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/docs/architecture/architecture-cdp.drawio.xml", + "destinationFileName": "/docs/architecture/architecture-cdp.drawio.xml", + "sourceNode": "/9j/4AAQS", + "destinationNode": "/9j/4AAQS", + "sourceLine": 160, + "sourceCode": "no source available", + "destinationLine": 160, + "destinationCode": "no source available", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=kZJZf%2BMif3ZrqvaUZiW6JYfpP2I%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -1672947992, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/docs/architecture/architecture-cdp.drawio.xml", + "destinationFileName": "/docs/architecture/architecture-cdp.drawio.xml", + "sourceNode": "app/images/bf02ff9e-bfe2-4b7e-8863-b73bff19b87b/content", + "destinationNode": "app/images/bf02ff9e-bfe2-4b7e-8863-b73bff19b87b/content", + "sourceLine": 141, + "sourceCode": "\u003cmxCell style=\"html=1;overflow=block;blockSpacing=1;whiteSpace=wrap;shape=image;fontSize=13;spacing=3.8;strokeColor=none;strokeOpacity=100;strokeWidth=0;image=https://images.lucid.app/images/bf02ff9e-bfe2-4b7e-8863-b73bff19b87b/content;imageAspect=0;\" parent=\"1\" vertex=\"1\"\u003e", + "destinationLine": 141, + "destinationCode": "\u003cmxCell style=\"html=1;overflow=block;blockSpacing=1;whiteSpace=wrap;shape=image;fontSize=13;spacing=3.8;strokeColor=none;strokeOpacity=100;strokeWidth=0;image=https://images.lucid.app/images/bf02ff9e-bfe2-4b7e-8863-b73bff19b87b/content;imageAspect=0;\" parent=\"1\" vertex=\"1\"\u003e", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=x2cdi1xr5YKy7woEGg9mLmOT7dU%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -1672947992, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/docs/architecture/architecture-cdp.drawio.xml", + "destinationFileName": "/docs/architecture/architecture-cdp.drawio.xml", + "sourceNode": "app/images/bf02ff9e-bfe2-4b7e-8863-b73bff19b87b/content", + "destinationNode": "app/images/bf02ff9e-bfe2-4b7e-8863-b73bff19b87b/content", + "sourceLine": 133, + "sourceCode": "\u003cmxCell style=\"html=1;overflow=block;blockSpacing=1;whiteSpace=wrap;shape=image;fontSize=13;spacing=3.8;strokeColor=none;strokeOpacity=100;strokeWidth=0;image=https://images.lucid.app/images/bf02ff9e-bfe2-4b7e-8863-b73bff19b87b/content;imageAspect=0;\" parent=\"1\" vertex=\"1\"\u003e", + "destinationLine": 133, + "destinationCode": "\u003cmxCell style=\"html=1;overflow=block;blockSpacing=1;whiteSpace=wrap;shape=image;fontSize=13;spacing=3.8;strokeColor=none;strokeOpacity=100;strokeWidth=0;image=https://images.lucid.app/images/bf02ff9e-bfe2-4b7e-8863-b73bff19b87b/content;imageAspect=0;\" parent=\"1\" vertex=\"1\"\u003e", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=ySM7f4waLmLAp90gvACz1077Mew%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -694807218, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/docs/architecture/architecture-cdp.drawio.xml", + "destinationFileName": "/docs/architecture/architecture-cdp.drawio.xml", + "sourceNode": "iVBOR", + "destinationNode": "iVBOR", + "sourceLine": 33, + "sourceCode": "n/a", + "destinationLine": 33, + "destinationCode": "n/a", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=evZA8r4B3kmI3hP49kdPuWOnM14%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -1346482252, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/BeginCheckoutCommandBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/BeginCheckoutCommandBuilder.kt", + "sourceNode": "-1337061051639281024", + "destinationNode": "-1337061051639281024", + "sourceLine": 227, + "sourceCode": "\"results_batch_id\": \"-1337061051639281024\",", + "destinationLine": 227, + "destinationCode": "\"results_batch_id\": \"-1337061051639281024\",", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=ZWmBAnVlNPufGeOVWQRlztCFQlU%3D", + "firstScanID": "147ab44a-cd9d-455f-a23f-ba74f51365d5", + "notes": [] + }, + { + "similarityId": 1434722978, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/BeginCheckoutCommandBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/BeginCheckoutCommandBuilder.kt", + "sourceNode": "b13df545-8fd6-462a-85bb-00a0a640013c", + "destinationNode": "b13df545-8fd6-462a-85bb-00a0a640013c", + "sourceLine": 218, + "sourceCode": "\"mp_deviceid\": \"b13df545-8fd6-462a-85bb-00a0a640013c\",", + "destinationLine": 218, + "destinationCode": "\"mp_deviceid\": \"b13df545-8fd6-462a-85bb-00a0a640013c\",", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=1D3NqHi%2FNj7%2FdoCWjHJ3eRAsvQA%3D", + "firstScanID": "147ab44a-cd9d-455f-a23f-ba74f51365d5", + "notes": [] + }, + { + "similarityId": 1515757216, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/BeginCheckoutCommandBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/BeginCheckoutCommandBuilder.kt", + "sourceNode": "983aaa66-716d-41f7-f2e1-45539420b730", + "destinationNode": "983aaa66-716d-41f7-f2e1-45539420b730", + "sourceLine": 163, + "sourceCode": "\"source_message_id\": \"983aaa66-716d-41f7-f2e1-45539420b730\",", + "destinationLine": 163, + "destinationCode": "\"source_message_id\": \"983aaa66-716d-41f7-f2e1-45539420b730\",", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=V6b1GEv3aVwLhZSr4U5al9doOsY%3D", + "firstScanID": "147ab44a-cd9d-455f-a23f-ba74f51365d5", + "notes": [] + }, + { + "similarityId": 1627688480, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/BeginCheckoutCommandBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/BeginCheckoutCommandBuilder.kt", + "sourceNode": "71AC6982-629F-4A6B-9568-37D3A56E37E3", + "destinationNode": "71AC6982-629F-4A6B-9568-37D3A56E37E3", + "sourceLine": 165, + "sourceCode": "\"session_uuid\": \"71AC6982-629F-4A6B-9568-37D3A56E37E3\",", + "destinationLine": 165, + "destinationCode": "\"session_uuid\": \"71AC6982-629F-4A6B-9568-37D3A56E37E3\",", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=6FfywHoYStqJjNAJ3h2F0WxsYno%3D", + "firstScanID": "147ab44a-cd9d-455f-a23f-ba74f51365d5", + "notes": [] + }, + { + "similarityId": 1193212346, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/BeginCheckoutCommandBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/BeginCheckoutCommandBuilder.kt", + "sourceNode": "-8245949395527182239", + "destinationNode": "-8245949395527182239", + "sourceLine": 189, + "sourceCode": "\"batch_id\": \"-8245949395527182239\",", + "destinationLine": 189, + "destinationCode": "\"batch_id\": \"-8245949395527182239\",", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=BNCm0w9jELq6L47ZrkxjYZ0qD%2Fg%3D", + "firstScanID": "147ab44a-cd9d-455f-a23f-ba74f51365d5", + "notes": [] + }, + { + "similarityId": -1712539798, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/BeginCheckoutCommandBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/BeginCheckoutCommandBuilder.kt", + "sourceNode": "a286dd30-319b-49a8-95ca-933ce6b85b6c", + "destinationNode": "a286dd30-319b-49a8-95ca-933ce6b85b6c", + "sourceLine": 190, + "sourceCode": "\"message_id\": \"a286dd30-319b-49a8-95ca-933ce6b85b6c\",", + "destinationLine": 190, + "destinationCode": "\"message_id\": \"a286dd30-319b-49a8-95ca-933ce6b85b6c\",", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=MHzt%2Bn0qVYSBeVaBhP%2FYN1glOJE%3D", + "firstScanID": "147ab44a-cd9d-455f-a23f-ba74f51365d5", + "notes": [] + }, + { + "similarityId": 1665652064, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/BeginCheckoutCommandBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/mParticle/BeginCheckoutCommandBuilder.kt", + "sourceNode": "339fe3e3-bb75-4c0d-2af4-685117e55999", + "destinationNode": "339fe3e3-bb75-4c0d-2af4-685117e55999", + "sourceLine": 191, + "sourceCode": "\"source_request_id\": \"339fe3e3-bb75-4c0d-2af4-685117e55999\",", + "destinationLine": 191, + "destinationCode": "\"source_request_id\": \"339fe3e3-bb75-4c0d-2af4-685117e55999\",", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=HYYl5pIzrao3bMT9RypYWCTPsxQ%3D", + "firstScanID": "147ab44a-cd9d-455f-a23f-ba74f51365d5", + "notes": [] + } + ] + }, + { + "queryName": "Use_of_Non_Cryptographic_Random", + "queryDescriptionLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast/description/330/6951891211749769081", + "queryId": 6951891211749769081, + "description": "Method @SourceMethod at line @SourceLine of @SourceFile uses a weak method @SourceElement to produce random values. These values might be used as personal identifiers, session tokens or cryptographic input; however, due to their insufficient randomness, an attacker may be able to derive their value.\n\n", + "vulnerabilitiesTotal": 23, + "queryPath": "Kotlin/Kotlin_Low_Visibility/Use_of_Non_Cryptographic_Random", + "cweId": 330, + "categories": [ + { + "name": "MOIS(KISA) Secure Coding 2021", + "subCategories": [ + "MOIS(KISA) Security Functions" + ] + }, + { + "name": "OWASP ASVS", + "subCategories": [ + "V02 Authentication" + ] + }, + { + "name": "OWASP Top 10 2021", + "subCategories": [ + "A2-Cryptographic Failures" + ] + } + ], + "vulnerabilities": [ + { + "similarityId": 516481930, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-26T17:55:36Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/jobs/DataRenotifyJobTest.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/infrastructure/jobs/DataRenotifyJobTest.kt", + "sourceNode": "nextLong", + "destinationNode": "nextLong", + "sourceMethod": "`always returns false`", + "destinationMethod": "`always returns false`", + "sourceLine": 66, + "sourceCode": "val timeLimitMinutes = ThreadLocalRandom.current().nextLong(Long.MAX_VALUE)", + "destinationLine": 66, + "destinationCode": "val timeLimitMinutes = ThreadLocalRandom.current().nextLong(Long.MAX_VALUE)", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=mVhNoC50rp9E9poSpsuzQ6ogY%2Bc%3D", + "firstScanID": "29a41414-4452-4a67-9f08-ac7d6556e427", + "notes": [] + }, + { + "similarityId": -1716307846, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/RandomUtils.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/RandomUtils.kt", + "sourceNode": "nextBoolean", + "destinationNode": "nextBoolean", + "sourceMethod": "boolean", + "destinationMethod": "boolean", + "sourceLine": 13, + "sourceCode": "fun boolean() = ThreadLocalRandom.current().nextBoolean()", + "destinationLine": 13, + "destinationCode": "fun boolean() = ThreadLocalRandom.current().nextBoolean()", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=c1FH%2F4N7nAqJ9yJrJiWo07%2B5T7c%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 309425226, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/RandomUtils.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/RandomUtils.kt", + "sourceNode": "nextInt", + "destinationNode": "nextInt", + "sourceMethod": "int", + "destinationMethod": "int", + "sourceLine": 9, + "sourceCode": "fun int(min: Int = 0, bound: Int = Int.MAX_VALUE) = ThreadLocalRandom.current().nextInt(min, bound)", + "destinationLine": 9, + "destinationCode": "fun int(min: Int = 0, bound: Int = Int.MAX_VALUE) = ThreadLocalRandom.current().nextInt(min, bound)", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=eIiBjlkpFeEnPooRjmyetS1%2F7cs%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -716467614, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/RandomUtils.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/RandomUtils.kt", + "sourceNode": "nextLong", + "destinationNode": "nextLong", + "sourceMethod": "long", + "destinationMethod": "long", + "sourceLine": 7, + "sourceCode": "fun long(min: Long = 0, bound: Long = Long.MAX_VALUE) = ThreadLocalRandom.current().nextLong(min, bound)", + "destinationLine": 7, + "destinationCode": "fun long(min: Long = 0, bound: Long = Long.MAX_VALUE) = ThreadLocalRandom.current().nextLong(min, bound)", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=mjnOele2Pk7LJLHFfnkZDmIe9A8%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 651102282, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/OrderBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/OrderBuilder.kt", + "sourceNode": "nextDouble", + "destinationNode": "nextDouble", + "sourceMethod": "moneyValue", + "destinationMethod": "moneyValue", + "sourceLine": 43, + "sourceCode": "BigDecimal(ThreadLocalRandom.current().nextDouble(0.01, maxValue))", + "destinationLine": 43, + "destinationCode": "BigDecimal(ThreadLocalRandom.current().nextDouble(0.01, maxValue))", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=P%2BHK8yhO6QSkRGoZKq8QTgA6KHE%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -576370902, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/OrderBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/OrderBuilder.kt", + "sourceNode": "nextInt", + "destinationNode": "nextInt", + "sourceMethod": "Lambda", + "destinationMethod": "Lambda", + "sourceLine": 34, + "sourceCode": "id = ThreadLocalRandom.current().nextInt(),", + "destinationLine": 34, + "destinationCode": "id = ThreadLocalRandom.current().nextInt(),", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=88kKofdYjzWDPPfUtiBvu2pwiUA%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -532904118, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/OrderBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/OrderBuilder.kt", + "sourceNode": "nextInt", + "destinationNode": "nextInt", + "sourceMethod": "build", + "destinationMethod": "build", + "sourceLine": 29, + "sourceCode": "id = ThreadLocalRandom.current().nextInt(),", + "destinationLine": 29, + "destinationCode": "id = ThreadLocalRandom.current().nextInt(),", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=3BbVbnAb4Eu42ZTYcJ%2FWY0gVO%2F0%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -1405866082, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/OrderBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/OrderBuilder.kt", + "sourceNode": "nextLong", + "destinationNode": "nextLong", + "sourceMethod": "build", + "destinationMethod": "build", + "sourceLine": 19, + "sourceCode": "statusId = ThreadLocalRandom.current().nextLong(),", + "destinationLine": 19, + "destinationCode": "statusId = ThreadLocalRandom.current().nextLong(),", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=bOk0Mah9iB6bUyWZEJGC18Sk%2BPE%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -1341375190, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/OrderBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/OrderBuilder.kt", + "sourceNode": "nextLong", + "destinationNode": "nextLong", + "sourceMethod": "build", + "destinationMethod": "build", + "sourceLine": 14, + "sourceCode": "customerId: Long = ThreadLocalRandom.current().nextLong(1, Long.MAX_VALUE),", + "destinationLine": 14, + "destinationCode": "customerId: Long = ThreadLocalRandom.current().nextLong(1, Long.MAX_VALUE),", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=rXkgdtC3paV1jVJQZjd2yCxPH%2Bo%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 181695044, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/OrderBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/OrderBuilder.kt", + "sourceNode": "nextLong", + "destinationNode": "nextLong", + "sourceMethod": "build", + "destinationMethod": "build", + "sourceLine": 10, + "sourceCode": "id: Long = ThreadLocalRandom.current().nextLong(),", + "destinationLine": 10, + "destinationCode": "id: Long = ThreadLocalRandom.current().nextLong(),", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=fSUw4dmnDN0x0Rn1hnzgRdm26U8%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 455442882, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/ItemBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/ItemBuilder.kt", + "sourceNode": "nextDouble", + "destinationNode": "nextDouble", + "sourceMethod": "moneyValue", + "destinationMethod": "moneyValue", + "sourceLine": 20, + "sourceCode": "BigDecimal(ThreadLocalRandom.current().nextDouble(0.01, maxValue))", + "destinationLine": 20, + "destinationCode": "BigDecimal(ThreadLocalRandom.current().nextDouble(0.01, maxValue))", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=RC73iDeh59PUDm%2FYX2AmWXLOpBk%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 1712631370, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/ItemBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/ItemBuilder.kt", + "sourceNode": "nextInt", + "destinationNode": "nextInt", + "sourceMethod": "build", + "destinationMethod": "build", + "sourceLine": 11, + "sourceCode": "quantity = ThreadLocalRandom.current().nextInt(1, Int.MAX_VALUE),", + "destinationLine": 11, + "destinationCode": "quantity = ThreadLocalRandom.current().nextInt(1, Int.MAX_VALUE),", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=fXsYQWm%2BQyH8yclh9EpILxPOeTQ%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 1346155068, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/DeliveryBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/DeliveryBuilder.kt", + "sourceNode": "nextLong", + "destinationNode": "nextLong", + "sourceMethod": "build", + "destinationMethod": "build", + "sourceLine": 21, + "sourceCode": "id = ThreadLocalRandom.current().nextLong(),", + "destinationLine": 21, + "destinationCode": "id = ThreadLocalRandom.current().nextLong(),", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=YivjCXC7JkglixKl0KmOqsj9CK0%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -1864063286, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/DeliveryBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/DeliveryBuilder.kt", + "sourceNode": "nextInt", + "destinationNode": "nextInt", + "sourceMethod": "build", + "destinationMethod": "build", + "sourceLine": 19, + "sourceCode": "statusId = ThreadLocalRandom.current().nextInt(),", + "destinationLine": 19, + "destinationCode": "statusId = ThreadLocalRandom.current().nextInt(),", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=eODXBYatmua%2Bdvdp8xf95dST750%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 1346155068, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/DeliveryBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/DeliveryBuilder.kt", + "sourceNode": "nextLong", + "destinationNode": "nextLong", + "sourceMethod": "build", + "destinationMethod": "build", + "sourceLine": 13, + "sourceCode": "id = ThreadLocalRandom.current().nextLong(),", + "destinationLine": 13, + "destinationCode": "id = ThreadLocalRandom.current().nextLong(),", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=vDruUtf7XcDH%2B7w9Puq9l7f7W7U%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -1864063286, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/DeliveryBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/domain/canonicalorder/DeliveryBuilder.kt", + "sourceNode": "nextInt", + "destinationNode": "nextInt", + "sourceMethod": "build", + "destinationMethod": "build", + "sourceLine": 11, + "sourceCode": "statusId = ThreadLocalRandom.current().nextInt(),", + "destinationLine": 11, + "destinationCode": "statusId = ThreadLocalRandom.current().nextInt(),", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=ZPHyCvrkFKKf7Tc3fxs%2FXbI%2BY4M%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 86747414, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/ecommerce/OrderStatusDeliveryGroupCommandBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/ecommerce/OrderStatusDeliveryGroupCommandBuilder.kt", + "sourceNode": "nextLong", + "destinationNode": "nextLong", + "sourceMethod": "build", + "destinationMethod": "build", + "sourceLine": 37, + "sourceCode": "id = ThreadLocalRandom.current().nextLong(),", + "destinationLine": 37, + "destinationCode": "id = ThreadLocalRandom.current().nextLong(),", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=zMPSctoPEZuHO8mwStL6OJdR%2FZY%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 301992676, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/ecommerce/OrderStatusDeliveryGroupCommandBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/ecommerce/OrderStatusDeliveryGroupCommandBuilder.kt", + "sourceNode": "nextLong", + "destinationNode": "nextLong", + "sourceMethod": "build", + "destinationMethod": "build", + "sourceLine": 34, + "sourceCode": "cancellationId = ThreadLocalRandom.current().nextLong(),", + "destinationLine": 34, + "destinationCode": "cancellationId = ThreadLocalRandom.current().nextLong(),", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=UN7123YjZmkP%2F5CAIkw2e5194TE%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -584626590, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/ecommerce/OrderStatusDeliveryGroupCommandBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/ecommerce/OrderStatusDeliveryGroupCommandBuilder.kt", + "sourceNode": "nextInt", + "destinationNode": "nextInt", + "sourceMethod": "build", + "destinationMethod": "build", + "sourceLine": 31, + "sourceCode": "quantity = ThreadLocalRandom.current().nextInt(1, Int.MAX_VALUE)", + "destinationLine": 31, + "destinationCode": "quantity = ThreadLocalRandom.current().nextInt(1, Int.MAX_VALUE)", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=vRByia%2Fpy5aOBu6gqvxMRJpozaM%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -584626590, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/ecommerce/OrderStatusDeliveryGroupCommandBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/ecommerce/OrderStatusDeliveryGroupCommandBuilder.kt", + "sourceNode": "nextInt", + "destinationNode": "nextInt", + "sourceMethod": "build", + "destinationMethod": "build", + "sourceLine": 26, + "sourceCode": "quantity = ThreadLocalRandom.current().nextInt(1, Int.MAX_VALUE)", + "destinationLine": 26, + "destinationCode": "quantity = ThreadLocalRandom.current().nextInt(1, Int.MAX_VALUE)", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=ytwabDjrAAnouWK4k8YiPSKyNPc%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -1042315702, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/ecommerce/OrderStatusDeliveryGroupCommandBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/ecommerce/OrderStatusDeliveryGroupCommandBuilder.kt", + "sourceNode": "nextLong", + "destinationNode": "nextLong", + "sourceMethod": "build", + "destinationMethod": "build", + "sourceLine": 20, + "sourceCode": "storeId = ThreadLocalRandom.current().nextLong(),", + "destinationLine": 20, + "destinationCode": "storeId = ThreadLocalRandom.current().nextLong(),", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=4eZkDJOS05v4su1Z2aqCgcyuf1g%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -1927886198, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/ecommerce/OrderStatusDeliveryGroupCommandBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/ecommerce/OrderStatusDeliveryGroupCommandBuilder.kt", + "sourceNode": "nextLong", + "destinationNode": "nextLong", + "sourceMethod": "build", + "destinationMethod": "build", + "sourceLine": 17, + "sourceCode": "deliveryGroupId = ThreadLocalRandom.current().nextLong(),", + "destinationLine": 17, + "destinationCode": "deliveryGroupId = ThreadLocalRandom.current().nextLong(),", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=gKFMZ6ERY%2BpBuJNABJcVID%2FEypU%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": -2015071542, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/ecommerce/OrderStatusDeliveryGroupCommandBuilder.kt", + "destinationFileName": "/src/test/kotlin/br/com/123/loiskjdye/builder/application/ecommerce/OrderStatusDeliveryGroupCommandBuilder.kt", + "sourceNode": "nextLong", + "destinationNode": "nextLong", + "sourceMethod": "build", + "destinationMethod": "build", + "sourceLine": 10, + "sourceCode": "originOrderId: Long = ThreadLocalRandom.current().nextLong(),", + "destinationLine": 10, + "destinationCode": "originOrderId: Long = ThreadLocalRandom.current().nextLong(),", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=2pl1cS%2FhollDiD09oVRgu5eEvmo%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + } + ] + }, + { + "queryName": "TruffleHog_Regex_Matches", + "queryDescriptionLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast/description/798/17363913395740017241", + "queryId": 17363913395740017241, + "description": "The application uses the hard-coded password @SourceElement for authentication purposes, either using it to verify users' identities, or to access another remote system. This password at line @SourceLine of @SourceFile appears in the code, implying it is accessible to anyone with source code access, and cannot be changed without rebuilding the application.", + "vulnerabilitiesTotal": 1, + "queryPath": "Java/Java_Low_Visibility/TruffleHog_Regex_Matches", + "cweId": 798, + "categories": [ + { + "name": "CWE top 25", + "subCategories": [ + "CWE top 25" + ] + }, + { + "name": "MOIS(KISA) Secure Coding 2021", + "subCategories": [ + "MOIS(KISA) Security Functions" + ] + }, + { + "name": "OWASP ASVS", + "subCategories": [ + "V06 Stored Cryptography" + ] + }, + { + "name": "OWASP Top 10 2021", + "subCategories": [ + "A7-Identification and Authentication Failures" + ] + }, + { + "name": "SANS top 25", + "subCategories": [ + "SANS top 25" + ] + } + ], + "vulnerabilities": [ + { + "similarityId": -1425229424, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/main/resources/application.yaml", + "destinationFileName": "/src/main/resources/application.yaml", + "sourceNode": "redis://${REDIS_AUTH:SUPER_SECRET_PASSWORD}@${REDIS_HOST", + "destinationNode": "redis://${REDIS_AUTH:SUPER_SECRET_PASSWORD}@${REDIS_HOST", + "sourceLine": 19, + "sourceCode": "url: redis://${REDIS_AUTH:SUPER_SECRET_PASSWORD}@${REDIS_HOST:localhost}:6379/0", + "destinationLine": 19, + "destinationCode": "url: redis://${REDIS_AUTH:SUPER_SECRET_PASSWORD}@${REDIS_HOST:localhost}:6379/0", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=7nrl5xTLhV8dMsl5lRJtL84TPTM%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + } + ] + }, + { + "queryName": "Missing_Rooted_Device_Check", + "queryDescriptionLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast/description/693/5904646516379822605", + "queryId": 5904646516379822605, + "description": "No checks to identify whether the device has been rooted were found.\n\n", + "vulnerabilitiesTotal": 1, + "queryPath": "Kotlin/Kotlin_Android/Missing_Rooted_Device_Check", + "cweId": 693, + "categories": [], + "vulnerabilities": [ + { + "similarityId": -330126304, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/src/main/kotlin/br/com/123/loiskjdye/LoiskjdyeApplication.kt", + "destinationFileName": "/src/main/kotlin/br/com/123/loiskjdye/LoiskjdyeApplication.kt", + "sourceNode": "main", + "destinationNode": "main", + "sourceMethod": "main", + "destinationMethod": "main", + "sourceLine": 36, + "sourceCode": "fun main() {", + "destinationLine": 36, + "destinationCode": "fun main() {", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=%2BLfKM9Vre35vP%2BBPA7cJtIVdF2Q%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + } + ] + }, + { + "queryName": "Improper_Error_Handling", + "queryDescriptionLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast/description/248/11966797339944458227", + "queryId": 11966797339944458227, + "description": "An error generated by @SourceElement at @SourceFile in line @SourceLine is not properly handled by subsequent application code.\n\n", + "vulnerabilitiesTotal": 2, + "queryPath": "Go/Go_Low_Visibility/Improper_Error_Handling", + "cweId": 248, + "categories": [ + { + "name": "MOIS(KISA) Secure Coding 2021", + "subCategories": [ + "MOIS(KISA) Error processing" + ] + }, + { + "name": "OWASP ASVS", + "subCategories": [ + "V14 Configuration" + ] + }, + { + "name": "OWASP Top 10 2021", + "subCategories": [ + "A4-Insecure Design" + ] + } + ], + "vulnerabilities": [ + { + "similarityId": 1767608375, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/extract_orders.go", + "destinationFileName": "/scripts/export-csv-full-base/extract_orders.go", + "sourceNode": "_", + "destinationNode": "_", + "sourceMethod": "main", + "destinationMethod": "main", + "sourceLine": 136, + "sourceCode": "concurrency, _ := strconv.Atoi(os.Args[2])", + "destinationLine": 136, + "destinationCode": "concurrency, _ := strconv.Atoi(os.Args[2])", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=07cLMZjOUZzKjS5CD77oKmqGqH8%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + }, + { + "similarityId": 923287423, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/e.go", + "destinationFileName": "/scripts/export-csv-full-base/e.go", + "sourceNode": "_", + "destinationNode": "_", + "sourceMethod": "main", + "destinationMethod": "main", + "sourceLine": 169, + "sourceCode": "concurrency, _ := strconv.Atoi(os.Args[2])", + "destinationLine": 169, + "destinationCode": "concurrency, _ := strconv.Atoi(os.Args[2])", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=7pXYFlqxb265uzmYRG3TA427xjk%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + } + ] + }, + { + "queryName": "Deprecated_API", + "queryDescriptionLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast/description/477/6232347621420708893", + "queryId": 6232347621420708893, + "description": "Method @DestinationMethod in @DestinationFile, at line @DestinationLine, calls an obsolete API, @DestinationElement. This has been deprecated, and should not be used in a modern codebase.\n\n", + "vulnerabilitiesTotal": 1, + "queryPath": "Go/Go_Low_Visibility/Deprecated_API", + "cweId": 477, + "categories": [ + { + "name": "OWASP ASVS", + "subCategories": [ + "V01 Architecture, Design and Threat Modeling" + ] + }, + { + "name": "OWASP Top 10 2021", + "subCategories": [ + "A6-Vulnerable and Outdated Components" + ] + } + ], + "vulnerabilities": [ + { + "similarityId": -904203947, + "status": "Recurrent", + "state": "To Verify", + "severity": "Low", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-01T15:19:17Z", + "sourceFileName": "/scripts/export-csv-full-base/e.go", + "destinationFileName": "/scripts/export-csv-full-base/e.go", + "sourceNode": "\"io/ioutil\"", + "destinationNode": "\"io/ioutil\"", + "sourceLine": 9, + "sourceCode": "\"io/ioutil\"", + "destinationLine": 9, + "destinationCode": "\"io/ioutil\"", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=DgyPxJl8MV6PUXK0loybcOIXHaQ%3D", + "firstScanID": "4438e7f8-9b94-4211-9314-ca7986448c3d", + "notes": [] + } + ] + }, + { + "queryName": "Incorrect_Conversion_between_Numeric_Types", + "queryDescriptionLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast/description/681/7919413771692923175", + "queryId": 7919413771692923175, + "description": "No query description available", + "vulnerabilitiesTotal": 2, + "queryPath": "Java/Java_Best_Coding_Practice/Incorrect_Conversion_between_Numeric_Types", + "cweId": 681, + "categories": [], + "vulnerabilities": [ + { + "similarityId": -592931585, + "status": "Recurrent", + "state": "To Verify", + "severity": "Information", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-24T14:21:13Z", + "sourceFileName": "/src/main/java/example123/single_customer_view/EventWithItemsKeyV1.java", + "destinationFileName": "/src/main/java/example123/single_customer_view/EventWithItemsKeyV1.java", + "sourceNode": "size0", + "destinationNode": "size0", + "sourceMethod": "customDecode", + "destinationMethod": "customDecode", + "sourceLine": 509, + "sourceCode": "a0 = new SpecificData.Array\u003cjava.lang.CharSequence\u003e((int)size0, SCHEMA$.getField(\"items\").schema());", + "destinationLine": 509, + "destinationCode": "a0 = new SpecificData.Array\u003cjava.lang.CharSequence\u003e((int)size0, SCHEMA$.getField(\"items\").schema());", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=wxekq3kf5x4oVy49lzjckgPYXkE%3D", + "firstScanID": "b005d91e-45f0-4c1b-a4b7-45efe8aa08b4", + "notes": [] + }, + { + "similarityId": -1084469121, + "status": "Recurrent", + "state": "To Verify", + "severity": "Information", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-24T14:21:13Z", + "sourceFileName": "/src/main/java/example123/single_customer_view/EventWithItemsKeyV1.java", + "destinationFileName": "/src/main/java/example123/single_customer_view/EventWithItemsKeyV1.java", + "sourceNode": "size0", + "destinationNode": "size0", + "sourceMethod": "customDecode", + "destinationMethod": "customDecode", + "sourceLine": 482, + "sourceCode": "a0 = new SpecificData.Array\u003cjava.lang.CharSequence\u003e((int)size0, SCHEMA$.getField(\"items\").schema());", + "destinationLine": 482, + "destinationCode": "a0 = new SpecificData.Array\u003cjava.lang.CharSequence\u003e((int)size0, SCHEMA$.getField(\"items\").schema());", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=zPyWjFi2GesVk40ANwqvNL8fcSQ%3D", + "firstScanID": "b005d91e-45f0-4c1b-a4b7-45efe8aa08b4", + "notes": [] + } + ] + }, + { + "queryName": "Incorrect_Block_Delimitation", + "queryDescriptionLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast/description/483/12135915305422528707", + "queryId": 12135915305422528707, + "description": "The application's @SourceMethod method (line @SourceLine) does not delimit a block using braces. This can create a logical error, and therefore, security implications that can be exploited by an attacker. ", + "vulnerabilitiesTotal": 3, + "queryPath": "Java/Java_Best_Coding_Practice/Incorrect_Block_Delimitation", + "cweId": 483, + "categories": [], + "vulnerabilities": [ + { + "similarityId": -801798977, + "status": "Recurrent", + "state": "To Verify", + "severity": "Information", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-24T14:21:13Z", + "sourceFileName": "/src/main/java/example123/single_customer_view/EventWithItemsKeyV1.java", + "destinationFileName": "/src/main/java/example123/single_customer_view/EventWithItemsKeyV1.java", + "sourceNode": "a0", + "destinationNode": "a0", + "sourceMethod": "customDecode", + "destinationMethod": "customDecode", + "sourceLine": 511, + "sourceCode": "} else a0.clear();", + "destinationLine": 511, + "destinationCode": "} else a0.clear();", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=DPhu8UYnCVextysP%2FsHH%2BtwlQ5I%3D", + "firstScanID": "b005d91e-45f0-4c1b-a4b7-45efe8aa08b4", + "notes": [] + }, + { + "similarityId": -81680995, + "status": "Recurrent", + "state": "To Verify", + "severity": "Information", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-24T14:21:13Z", + "sourceFileName": "/src/main/java/example123/single_customer_view/EventWithItemsKeyV1.java", + "destinationFileName": "/src/main/java/example123/single_customer_view/EventWithItemsKeyV1.java", + "sourceNode": "a0", + "destinationNode": "a0", + "sourceMethod": "customDecode", + "destinationMethod": "customDecode", + "sourceLine": 484, + "sourceCode": "} else a0.clear();", + "destinationLine": 484, + "destinationCode": "} else a0.clear();", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=Y3aceZH6jddhcx95OEt%2F2LLGvB0%3D", + "firstScanID": "b005d91e-45f0-4c1b-a4b7-45efe8aa08b4", + "notes": [] + }, + { + "similarityId": 1851967519, + "status": "Recurrent", + "state": "To Verify", + "severity": "Information", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-24T14:21:13Z", + "sourceFileName": "/src/main/java/example123/single_customer_view/EventWithItemsKeyV1.java", + "destinationFileName": "/src/main/java/example123/single_customer_view/EventWithItemsKeyV1.java", + "sourceNode": "if", + "destinationNode": "if", + "sourceMethod": "customEncode", + "destinationMethod": "customEncode", + "sourceLine": 465, + "sourceCode": "if (actualSize0 != size0)", + "destinationLine": 465, + "destinationCode": "if (actualSize0 != size0)", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=iwByIMOY5Ox2uap099wuoEsXVzI%3D", + "firstScanID": "b005d91e-45f0-4c1b-a4b7-45efe8aa08b4", + "notes": [] + } + ] + }, + { + "queryName": "Potentially_Serializable_Class_With_Sensitive_Data", + "queryDescriptionLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast/description/499/2168313460723921343", + "queryId": 2168313460723921343, + "description": "No query description available", + "vulnerabilitiesTotal": 6, + "queryPath": "Java/Java_Best_Coding_Practice/Potentially_Serializable_Class_With_Sensitive_Data", + "cweId": 499, + "categories": [ + { + "name": "OWASP Top 10 2013", + "subCategories": [ + "A6-Sensitive Data Exposure" + ] + }, + { + "name": "OWASP Top 10 2017", + "subCategories": [ + "A3-Sensitive Data Exposure" + ] + }, + { + "name": "OWASP Top 10 2021", + "subCategories": [ + "A4-Insecure Design" + ] + }, + { + "name": "PCI DSS v3.2.1", + "subCategories": [ + "PCI DSS (3.2.1) - 6.5.3 - Insecure cryptographic storage" + ] + }, + { + "name": "MOIS(KISA) Secure Coding 2021", + "subCategories": [ + "MOIS(KISA) Security Functions" + ] + }, + { + "name": "OWASP ASVS", + "subCategories": [ + "V09 Communication" + ] + } + ], + "vulnerabilities": [ + { + "similarityId": -765276279, + "status": "Recurrent", + "state": "To Verify", + "severity": "Information", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-05T17:38:27Z", + "sourceFileName": "/src/main/java/example123/customer/single_view/PayloadPersonV4.java", + "destinationFileName": "/src/main/java/example123/customer/single_view/PayloadPersonV4.java", + "sourceNode": "additionalPhone", + "destinationNode": "Builder", + "sourceLine": 967, + "sourceCode": "private java.lang.CharSequence additionalPhone;", + "destinationLine": 946, + "destinationCode": "public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase\u003cPayloadPersonV4\u003e", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=2brkl6eQixybw1ZvP%2FaD9KLimUA%3D", + "firstScanID": "1db8368e-1b90-4367-a1ab-dd5fea1084c3", + "notes": [] + }, + { + "similarityId": 1272328932, + "status": "Recurrent", + "state": "To Verify", + "severity": "Information", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-05T17:38:27Z", + "sourceFileName": "/src/main/java/example123/customer/single_view/PayloadPersonV4.java", + "destinationFileName": "/src/main/java/example123/customer/single_view/PayloadPersonV4.java", + "sourceNode": "additionalPhone", + "destinationNode": "PayloadPersonV4", + "sourceLine": 967, + "sourceCode": "private java.lang.CharSequence additionalPhone;", + "destinationLine": 15, + "destinationCode": "@org.apache.avro.specific.AvroGenerated", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=NP94lAYMgemapke4wSG78Vm99Ho%3D", + "firstScanID": "1db8368e-1b90-4367-a1ab-dd5fea1084c3", + "notes": [] + }, + { + "similarityId": 1517996265, + "status": "Recurrent", + "state": "To Verify", + "severity": "Information", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-05T17:38:27Z", + "sourceFileName": "/src/main/java/example123/customer/single_view/PayloadPersonV4.java", + "destinationFileName": "/src/main/java/example123/customer/single_view/PayloadPersonV4.java", + "sourceNode": "phone", + "destinationNode": "Builder", + "sourceLine": 966, + "sourceCode": "private java.lang.CharSequence phone;", + "destinationLine": 946, + "destinationCode": "public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase\u003cPayloadPersonV4\u003e", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=pPOTwxE6LwYQHAsLjVjsiFv43OY%3D", + "firstScanID": "1db8368e-1b90-4367-a1ab-dd5fea1084c3", + "notes": [] + }, + { + "similarityId": -791477180, + "status": "Recurrent", + "state": "To Verify", + "severity": "Information", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-05T17:38:27Z", + "sourceFileName": "/src/main/java/example123/customer/single_view/PayloadPersonV4.java", + "destinationFileName": "/src/main/java/example123/customer/single_view/PayloadPersonV4.java", + "sourceNode": "phone", + "destinationNode": "PayloadPersonV4", + "sourceLine": 966, + "sourceCode": "private java.lang.CharSequence phone;", + "destinationLine": 15, + "destinationCode": "@org.apache.avro.specific.AvroGenerated", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=AZvw6VtHA0L94%2FQdtzH9wX7QYKs%3D", + "firstScanID": "1db8368e-1b90-4367-a1ab-dd5fea1084c3", + "notes": [] + }, + { + "similarityId": -1555372122, + "status": "Recurrent", + "state": "To Verify", + "severity": "Information", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-05T17:38:27Z", + "sourceFileName": "/src/main/java/example123/customer/single_view/PayloadPersonV4.java", + "destinationFileName": "/src/main/java/example123/customer/single_view/PayloadPersonV4.java", + "sourceNode": "additionalPhone", + "destinationNode": "PayloadPersonV4", + "sourceLine": 97, + "sourceCode": "private java.lang.CharSequence additionalPhone;", + "destinationLine": 15, + "destinationCode": "@org.apache.avro.specific.AvroGenerated", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=j%2FaQQ3pN5bqnNbqXlh3omGE5w7I%3D", + "firstScanID": "1db8368e-1b90-4367-a1ab-dd5fea1084c3", + "notes": [] + }, + { + "similarityId": 403993414, + "status": "Recurrent", + "state": "To Verify", + "severity": "Information", + "foundDate": "2024-04-16T14:39:59Z", + "firstFoundDate": "2024-03-05T17:38:27Z", + "sourceFileName": "/src/main/java/example123/customer/single_view/PayloadPersonV4.java", + "destinationFileName": "/src/main/java/example123/customer/single_view/PayloadPersonV4.java", + "sourceNode": "phone", + "destinationNode": "PayloadPersonV4", + "sourceLine": 96, + "sourceCode": "private java.lang.CharSequence phone;", + "destinationLine": 15, + "destinationCode": "@org.apache.avro.specific.AvroGenerated", + "nodes": [], + "resultViewerLink": "https://ast.checkmarx.net/juke/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/20c7d605-51d2-4471-afd7-514774dfb9bd/sast?result-id=iQjDiFc2FTPUbn7hSXRyzb1Wfgc%3D", + "firstScanID": "1db8368e-1b90-4367-a1ab-dd5fea1084c3", + "notes": [] + } + ] + } + ] + }, + "iacScanResults": { + "totalResults": 10, + "severitiesBreakdown": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 9 + }, + { + "level": "Low", + "value": 1 + }, + { + "level": "Information", + "value": 0 + } + ], + "technology": [ + { + "name": "Kubernetes", + "totalResults": 4, + "queries": [ + { + "queryName": "Using Unrecommended Namespace", + "totalResults": 4, + "description": "Namespaces like 'default', 'kube-system' or 'kube-public' should not be used", + "category": "Insecure Configurations", + "resultsList": [ + { + "severity": "Medium", + "resultViewerLink": "https://ast.checkmarx.net/juke/20c7d605-51d2-4471-afd7-514774dfb9bd/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/kics?result-id=lhh6XPbJLc58Mvv859bsOnM3N6Q=", + "status": "Recurrent", + "state": "To Verify", + "firstScanID": "770fb4c5-e018-4218-b2b4-dab4994309eb", + "firstDetectionDate": "2023-07-17T18:40:20Z", + "lastDetectionDate": "2024-04-16T14:36:23Z", + "fileName": "/.aioros/development/03-serviceusage-networking.yaml", + "issueType": "MissingAttribute", + "actualValue": "metadata.namespace is undefined or null", + "expectedValue": "metadata.namespace should be defined and not null" + }, + { + "severity": "Medium", + "resultViewerLink": "https://ast.checkmarx.net/juke/20c7d605-51d2-4471-afd7-514774dfb9bd/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/kics?result-id=AorFkMT5KKT6DfXK+YfN7Ybl9Fw=", + "status": "Recurrent", + "state": "To Verify", + "firstScanID": "770fb4c5-e018-4218-b2b4-dab4994309eb", + "firstDetectionDate": "2023-07-17T18:40:20Z", + "lastDetectionDate": "2024-04-16T14:36:23Z", + "fileName": "/.aioros/production/05-serviceusage-redis.yaml", + "issueType": "MissingAttribute", + "actualValue": "metadata.namespace is undefined or null", + "expectedValue": "metadata.namespace should be defined and not null" + }, + { + "severity": "Medium", + "resultViewerLink": "https://ast.checkmarx.net/juke/20c7d605-51d2-4471-afd7-514774dfb9bd/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/kics?result-id=Zg5+/a5aE5Pg3GTl4pLEqLBVtDo=", + "status": "Recurrent", + "state": "To Verify", + "firstScanID": "770fb4c5-e018-4218-b2b4-dab4994309eb", + "firstDetectionDate": "2023-07-17T18:40:20Z", + "lastDetectionDate": "2024-04-16T14:36:23Z", + "fileName": "/.aioros/development/05-serviceusage-redis.yaml", + "issueType": "MissingAttribute", + "actualValue": "metadata.namespace is undefined or null", + "expectedValue": "metadata.namespace should be defined and not null" + }, + { + "severity": "Medium", + "resultViewerLink": "https://ast.checkmarx.net/juke/20c7d605-51d2-4471-afd7-514774dfb9bd/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/kics?result-id=EcHRtIbhJoeGq3IVAsCW+cLR4Rw=", + "status": "Recurrent", + "state": "To Verify", + "firstScanID": "770fb4c5-e018-4218-b2b4-dab4994309eb", + "firstDetectionDate": "2023-07-17T18:40:20Z", + "lastDetectionDate": "2024-04-16T14:36:23Z", + "fileName": "/.aioros/production/03-serviceusage-networking.yaml", + "issueType": "MissingAttribute", + "actualValue": "metadata.namespace is undefined or null", + "expectedValue": "metadata.namespace should be defined and not null" + } + ] + } + ] + }, + { + "name": "CICD", + "totalResults": 5, + "queries": [ + { + "queryName": "Unpinned Actions Full Length Commit SHA", + "totalResults": 5, + "description": "Pinning an action to a full length commit SHA is currently the only way to use an action as an immutable release. Pinning to a particular SHA helps mitigate the risk of a bad actor adding a backdoor to the action's repository, as they would need to generate a SHA-1 collision for a valid Git object payload. When selecting a SHA, you should verify it is from the action's repository and not a repository fork.", + "category": "Supply-Chain", + "resultsList": [ + { + "severity": "Medium", + "resultViewerLink": "https://ast.checkmarx.net/juke/20c7d605-51d2-4471-afd7-514774dfb9bd/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/kics?result-id=Mbn8Q9W7P8ySlvbKhIstFHZTT7o=", + "status": "Recurrent", + "state": "To Verify", + "firstScanID": "8e909aa4-ffe5-4fa6-aeda-3ff2857e6efc", + "firstDetectionDate": "2024-02-26T17:27:23Z", + "lastDetectionDate": "2024-04-16T14:36:23Z", + "fileName": "/.github/workflows/ci.yml", + "issueType": "IncorrectValue", + "actualValue": "Action is not pinned to a full length commit SHA.", + "expectedValue": "Action pinned to a full length commit SHA." + }, + { + "severity": "Medium", + "resultViewerLink": "https://ast.checkmarx.net/juke/20c7d605-51d2-4471-afd7-514774dfb9bd/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/kics?result-id=EiZqOwVB2pAfwNX1lkqr+1EykZc=", + "status": "Recurrent", + "state": "To Verify", + "firstScanID": "3d859bfc-e7c7-435d-862e-e50c0c257c23", + "firstDetectionDate": "2024-04-01T23:50:39Z", + "lastDetectionDate": "2024-04-16T14:36:23Z", + "fileName": "/.github/workflows/checkmarx.yaml", + "issueType": "IncorrectValue", + "actualValue": "Action is not pinned to a full length commit SHA.", + "expectedValue": "Action pinned to a full length commit SHA." + }, + { + "severity": "Medium", + "resultViewerLink": "https://ast.checkmarx.net/juke/20c7d605-51d2-4471-afd7-514774dfb9bd/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/kics?result-id=ajmu7/mNIMc+JLCZVBDM0yRwtH4=", + "status": "Recurrent", + "state": "To Verify", + "firstScanID": "3d859bfc-e7c7-435d-862e-e50c0c257c23", + "firstDetectionDate": "2024-04-01T23:50:39Z", + "lastDetectionDate": "2024-04-16T14:36:23Z", + "fileName": "/.github/workflows/checkmarx.yaml", + "issueType": "IncorrectValue", + "actualValue": "Action is not pinned to a full length commit SHA.", + "expectedValue": "Action pinned to a full length commit SHA." + }, + { + "severity": "Medium", + "resultViewerLink": "https://ast.checkmarx.net/juke/20c7d605-51d2-4471-afd7-514774dfb9bd/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/kics?result-id=gKo2jaF6n9mSWAogyDnoSsHV45c=", + "status": "Recurrent", + "state": "To Verify", + "firstScanID": "845c809d-6f15-4802-a8fc-7cfa84a9ca88", + "firstDetectionDate": "2024-02-14T22:47:51Z", + "lastDetectionDate": "2024-04-16T14:36:23Z", + "fileName": "/.github/workflows/ci.yml", + "issueType": "IncorrectValue", + "actualValue": "Action is not pinned to a full length commit SHA.", + "expectedValue": "Action pinned to a full length commit SHA." + }, + { + "severity": "Medium", + "resultViewerLink": "https://ast.checkmarx.net/juke/20c7d605-51d2-4471-afd7-514774dfb9bd/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/kics?result-id=xXj2JMgbqjRRB5irfTk0Zn/QXMQ=", + "status": "Recurrent", + "state": "To Verify", + "firstScanID": "50593b29-6d4f-4d62-a6df-95831d5e139f", + "firstDetectionDate": "2023-12-11T16:46:37Z", + "lastDetectionDate": "2024-04-16T14:36:23Z", + "fileName": "/.github/workflows/deploy_development.yml", + "issueType": "IncorrectValue", + "actualValue": "Action is not pinned to a full length commit SHA.", + "expectedValue": "Action pinned to a full length commit SHA." + } + ] + } + ] + }, + { + "name": "Dockerfile", + "totalResults": 1, + "queries": [ + { + "queryName": "Healthcheck Instruction Missing", + "totalResults": 1, + "description": "Ensure that HEALTHCHECK is being used. The HEALTHCHECK instruction tells Docker how to test a container to check that it is still working", + "category": "Insecure Configurations", + "resultsList": [ + { + "severity": "Low", + "resultViewerLink": "https://ast.checkmarx.net/juke/20c7d605-51d2-4471-afd7-514774dfb9bd/7c9b4b8e-6986-4e5f-a787-f7d2c93e622a/kics?result-id=vipqB4mUTCHtk9A/I4lw/ewPubQ=", + "status": "Recurrent", + "state": "To Verify", + "firstScanID": "a81fcfd6-3009-4e4c-9fab-3522577cd5b2", + "firstDetectionDate": "2024-04-10T12:21:12Z", + "lastDetectionDate": "2024-04-16T14:36:23Z", + "fileName": "/Dockerfile", + "issueType": "MissingAttribute", + "actualValue": "Dockerfile doesn't contain instruction 'HEALTHCHECK'", + "expectedValue": "Dockerfile should contain instruction 'HEALTHCHECK'" + } + ] + } + ] + } + ] + }, + "scaScanResults": { + "totalResults": 0, + "severitiesBreakdown": [], + "packages": [] + }, + "categories": [ + { + "name": "CWE top 25", + "subCategories": [ + { + "name": "CWE_top_25_380", + "vulnerabilitiesBox": { + "name": "CWE top 25", + "severityDistribution": [ + { + "level": "High", + "value": 3 + }, + { + "level": "Medium", + "value": 24 + }, + { + "level": "Low", + "value": 57 + }, + { + "level": "Information", + "value": 0 + } + ] + } + } + ] + }, + { + "name": "FISMA 2014", + "subCategories": [ + { + "name": "System_And_Information_Integrity_26", + "vulnerabilitiesBox": { + "name": "System And Information Integrity", + "severityDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 4 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + } + } + ] + }, + { + "name": "MOIS(KISA) Secure Coding 2021", + "subCategories": [ + { + "name": "MOIS_KISA__Error_processing_384", + "vulnerabilitiesBox": { + "name": "MOIS(KISA) Error processing", + "severityDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 2 + }, + { + "level": "Information", + "value": 0 + } + ] + } + }, + { + "name": "MOIS_KISA__Security_Functions_385", + "vulnerabilitiesBox": { + "name": "MOIS(KISA) Security Functions", + "severityDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 1 + }, + { + "level": "Low", + "value": 80 + }, + { + "level": "Information", + "value": 6 + } + ] + } + }, + { + "name": "MOIS_KISA__Verification_and_representation_of_input_data_387", + "vulnerabilitiesBox": { + "name": "MOIS(KISA) Verification and representation of input data", + "severityDistribution": [ + { + "level": "High", + "value": 3 + }, + { + "level": "Medium", + "value": 24 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + } + } + ] + }, + { + "name": "NIST SP 800-53", + "subCategories": [ + { + "name": "SI_10_Information_Input_Validation__P1__45", + "vulnerabilitiesBox": { + "name": "SI-10 Information Input Validation (P1)", + "severityDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 4 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + } + } + ] + }, + { + "name": "OWASP ASVS", + "subCategories": [ + { + "name": "V01_Architecture__Design_and_Threat_Modeling_388", + "vulnerabilitiesBox": { + "name": "V01 Architecture, Design and Threat Modeling", + "severityDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 1 + }, + { + "level": "Information", + "value": 0 + } + ] + } + }, + { + "name": "V02_Authentication_389", + "vulnerabilitiesBox": { + "name": "V02 Authentication", + "severityDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 23 + }, + { + "level": "Information", + "value": 0 + } + ] + } + }, + { + "name": "V06_Stored_Cryptography_393", + "vulnerabilitiesBox": { + "name": "V06 Stored Cryptography", + "severityDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 57 + }, + { + "level": "Information", + "value": 0 + } + ] + } + }, + { + "name": "V09_Communication_396", + "vulnerabilitiesBox": { + "name": "V09 Communication", + "severityDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 1 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 6 + } + ] + } + }, + { + "name": "V05_Validation__Sanitization_and_Encoding_392", + "vulnerabilitiesBox": { + "name": "V05 Validation, Sanitization and Encoding", + "severityDistribution": [ + { + "level": "High", + "value": 3 + }, + { + "level": "Medium", + "value": 4 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + } + }, + { + "name": "V12_Files_and_Resources_399", + "vulnerabilitiesBox": { + "name": "V12 Files and Resources", + "severityDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 20 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + } + }, + { + "name": "V14_Configuration_401", + "vulnerabilitiesBox": { + "name": "V14 Configuration", + "severityDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 2 + }, + { + "level": "Information", + "value": 0 + } + ] + } + } + ] + }, + { + "name": "OWASP Top 10 2013", + "subCategories": [ + { + "name": "A6_Sensitive_Data_Exposure_15", + "vulnerabilitiesBox": { + "name": "A6-Sensitive Data Exposure", + "severityDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 6 + } + ] + } + } + ] + }, + { + "name": "OWASP Top 10 2017", + "subCategories": [ + { + "name": "A3_Sensitive_Data_Exposure_51", + "vulnerabilitiesBox": { + "name": "A3-Sensitive Data Exposure", + "severityDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 6 + } + ] + } + }, + { + "name": "A5_Broken_Access_Control_53", + "vulnerabilitiesBox": { + "name": "A5-Broken Access Control", + "severityDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 4 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + } + } + ] + }, + { + "name": "OWASP Top 10 2021", + "subCategories": [ + { + "name": "A2_Cryptographic_Failures_403", + "vulnerabilitiesBox": { + "name": "A2-Cryptographic Failures", + "severityDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 1 + }, + { + "level": "Low", + "value": 23 + }, + { + "level": "Information", + "value": 0 + } + ] + } + }, + { + "name": "A1_Broken_Access_Control_402", + "vulnerabilitiesBox": { + "name": "A1-Broken Access Control", + "severityDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 8 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + } + }, + { + "name": "A6_Vulnerable_and_Outdated_Components_407", + "vulnerabilitiesBox": { + "name": "A6-Vulnerable and Outdated Components", + "severityDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 1 + }, + { + "level": "Information", + "value": 0 + } + ] + } + }, + { + "name": "A3_Injection_404", + "vulnerabilitiesBox": { + "name": "A3-Injection", + "severityDistribution": [ + { + "level": "High", + "value": 3 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + } + }, + { + "name": "A7_Identification_and_Authentication_Failures_408", + "vulnerabilitiesBox": { + "name": "A7-Identification and Authentication Failures", + "severityDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 57 + }, + { + "level": "Information", + "value": 0 + } + ] + } + }, + { + "name": "A4_Insecure_Design_405", + "vulnerabilitiesBox": { + "name": "A4-Insecure Design", + "severityDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 15 + }, + { + "level": "Low", + "value": 2 + }, + { + "level": "Information", + "value": 6 + } + ] + } + }, + { + "name": "A10_Server_Side_Request_Forgery_411", + "vulnerabilitiesBox": { + "name": "A10-Server-Side Request Forgery", + "severityDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 4 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 0 + } + ] + } + } + ] + }, + { + "name": "PCI DSS v3.2.1", + "subCategories": [ + { + "name": "PCI_DSS__3_2_1____6_5_3___Insecure_cryptographic_storage_414", + "vulnerabilitiesBox": { + "name": "PCI DSS (3.2.1) - 6.5.3 - Insecure cryptographic storage", + "severityDistribution": [ + { + "level": "High", + "value": 0 + }, + { + "level": "Medium", + "value": 0 + }, + { + "level": "Low", + "value": 0 + }, + { + "level": "Information", + "value": 6 + } + ] + } + } + ] + }, + { + "name": "SANS top 25", + "subCategories": [ + { + "name": "SANS_top_25_421", + "vulnerabilitiesBox": { + "name": "SANS top 25", + "severityDistribution": [ + { + "level": "High", + "value": 3 + }, + { + "level": "Medium", + "value": 21 + }, + { + "level": "Low", + "value": 57 + }, + { + "level": "Information", + "value": 0 + } + ] + } + } + ] + } + ], + "resolvedVulnerabilities": { + "resolvedTotal": 0, + "resolvedVulnerabilities": [] + }, + "vulnerabilityDetails": [ + { + "vulnerabilityName": "Reflected_XSS", + "risk": "A successful XSS exploit would allow an attacker to rewrite web pages and insert malicious scripts which would alter the intended output. This could include HTML fragments, CSS styling rules, arbitrary JavaScript, or references to third party code. An attacker could use this to steal users' passwords, collect personal data such as credit card details, provide false information, or run malware. From the victim’s point of view, this is performed by the genuine website, and the victim would blame the site for incurred damage.\n\nThe attacker could use social engineering to cause the user to send the website modified input, which will be returned in the requested web page.\n\n", + "cause": "The application creates web pages that include untrusted data, whether from user input, the application’s database, or from other external sources. The untrusted data is embedded directly in the page's HTML, causing the browser to display it as part of the web page. If the input includes HTML fragments or JavaScript, these are displayed too, and the user cannot tell that this is not the intended page. The vulnerability is the result of directly embedding arbitrary data without first encoding it in a format that would prevent the browser from treating it like HTML or code instead of plain text.\n\nNote that an attacker can exploit this vulnerability either by modifying the URL, or by submitting malicious data in the user input or other request fields.\n\n", + "generalRecommendations": "* Fully encode all dynamic data, regardless of source, before embedding it in output.\r\n* Encoding should be context-sensitive. For example:\r\n * HTML encoding for HTML content\r\n * HTML Attribute encoding for data output to attribute values\r\n * JavaScript encoding for server-generated JavaScript\r\n* It is recommended to use the platform-provided encoding functionality, or known security libraries for encoding output.\r\n* Implement a Content Security Policy (CSP) with explicit whitelists for the application's resources only. \r\n* As an extra layer of protection, validate all untrusted data, regardless of source (note this is not a replacement for encoding). Validation should be based on a whitelist: accept only data fitting a specified structure, rather than reject bad patterns. Check for:\r\n * Data type\r\n * Size\r\n * Range\r\n * Format\r\n * Expected values\r\n* In the `Content-Type` HTTP response header, explicitly define character encoding (charset) for the entire page. \r\n* Set the `HTTPOnly` flag on the session cookie for \"Defense in Depth\", to prevent any successful XSS exploits from stealing the cookie.\n\n", + "cweId": 79 + }, + { + "vulnerabilityName": "Client_Side_Injection", + "risk": "An attacker could directly access all of the system's data. The attacker would likely be able to steal any sensitive information stored by the system, including private user information, credit card details, proprietary business data, and any other secret data. Likewise, the attacker could possibly modify or erase existing data, or even add new bogus data. In some scenarios, it may even be possible to execute code on the database. \r\n\r\nIn addition to disclosing or altering confidential information directly, this vulnerability might also be used to achieve secondary effects, such as bypassing authentication, subverting security checks, or forging a data trail. \r\n\r\nFurther increasing the likelihood of exploit is the fact that this flaw is easy for attackers to find, and easy to exploit.\n\nSince this is a client-side issue, it will likely only expose data stored on the current device to retrieval or tampering.\n\n", + "cause": "The application stores and manages data in a database, by submitting a textual SQL query to the database engine for processing. The application creates the query by simple string concatenation, embedding untrusted data. However, there is no separation between data and code; furthermore, the embedded data is neither checked for data type validity nor subsequently sanitized. Thus, the untrusted data could contain SQL commands, or modify the intended query. The database would interpret the altered query and commands as if they originated from the application, and execute them accordingly.\n\n", + "generalRecommendations": "* Validate all untrusted data, regardless of source. Validation should be based on a whitelist: accept only data fitting a specified structure, rather than reject bad patterns. \r\n* In particular, check for:\r\n * Data type\r\n * Size\r\n * Range\r\n * Format\r\n * Expected values.\r\n* Restrict access to database objects and functionality, according to the Principle of Least Privilege.\r\n* Do not use dynamically concatenate strings to construct SQL queries. \r\n* Prefer using DB Stored Procedures for all data access, instead of ad-hoc dynamic queries. \r\n* Instead of unsafe string concatenation, use secure database components such as parameterized queries and object bindings (for example, commands and parameters). \r\n* Alternatively, an even better solution is to use an ORM library, in order to pre-define and encapsulate the allowed commands enabled for the application, instead of dynamically accessing the database directly. In this way the code plane and data plane should be isolated from each other.\n\n", + "cweId": 89 + }, + { + "vulnerabilityName": "Unchecked_Input_for_Loop_Condition", + "risk": "An attacker could input a very high value, potentially causing a denial of service (DoS).\n\n", + "cause": "The application performs some repetitive task in a loop, and defines the number of times to perform the loop according to user input. A very high value could cause the application to get stuck in the loop and to be unable to continue to other operations.\n\n", + "generalRecommendations": "Ideally, don’t base a loop on user-provided data. If it is necessary to do so, the user input must be first validated and its range should be limited.\n\n", + "cweId": 606 + }, + { + "vulnerabilityName": "Unchecked_Input_for_Loop_Condition", + "risk": "An attacker could input a very high value, potentially causing a denial of service (DoS).\n\n", + "cause": "The application performs some repetitive task in a loop, and defines the number of times to perform the loop according to user input. A very high value could cause the application to get stuck in the loop and to be unable to continue to other operations.\n\n", + "generalRecommendations": "Ideally, don’t base a loop on user-provided data. If it is necessary to do so, the user input must be first validated and its range should be limited.\n\n", + "cweId": 606 + }, + { + "vulnerabilityName": "SSRF", + "risk": "An attacker can abuse this flaw to make arbitrary requests, originating from the application server. This can be exploited to scan internal services; proxy attacks into a protected network; bypass network controls; download unauthorized files; access internal services and management interfaces; and possibly control the contents of requests and even steal server credentials.\n\n", + "cause": "The application accepts a URL (or other data) from the user, and uses this to make a request to another remote server.\r\n\r\nHowever, the attacker can inject an arbitrary URL into the request, causing the application to connect to any server the attacker wants. Thus, the attacker can abuse the application to gain access to services that would not otherwise be accessable, and cause the request to ostensibly originate from the application server.\n\n", + "generalRecommendations": "* Do not connect to arbitrary services based on user input.\r\n* If possible, the application should have the user's browser retrieve the desired information directly. \r\n* If it is necessary for the application to proxy the request on the server, explicitly whitelist the allowed target URLs, and do not include any sensitive server information.\n\n", + "cweId": 918 + }, + { + "vulnerabilityName": "SSL_Verification_Bypass", + "risk": "If the SSL/TLS library is configured to disable verification of the certificate's properties, such as trust chain, hostname, expiry and more - it is possible to cause the application to utilize an unvalidated certificate. This may allow an attacker to intercept the client requests, provide their own forged server certificate, and perform an active Man-in-the-Middle attacks - even over HTTPS. Thus an attacker would have complete access to the content of requests and responses, reading any secret information and tampering any sensitive data, including user credentials.\n\n", + "cause": "The application utilizes HTTPS, but is explicitly configured to disable verification of certificate authenticity. If the certificate signer is not verified all the way up to a trusted certificate authority, it is possible to issue a bogus certificate, and have it be accepted by the application. Since the application does not enforce the signing certificate is already configured in the system's trusted root certificate store, it is possible to simply use a self-signed certificate, with any user- or server-name, and the application will trust it.\n\n", + "generalRecommendations": "Generic Guidance: \n* Properly implement all checks necessary to ensure the identity of entities involved in encrypted communications.\n* Properly configure all parameters of HTTPS.\n* Never disable certificate verification.\n\n\n\n", + "cweId": 599 + }, + { + "vulnerabilityName": "Reflected_Relative_Path_Traversal", + "risk": "An attacker could define arbitrary file path for the application to use, potentially leading to:\r\n* Stealing sensitive files, such as configuration or system files\r\n* Overwriting files such as program binaries, configuration files, or system files\r\n* Deleting critical files, causing denial of service (DoS).\n\n", + "cause": "The application uses user input in the file path for accessing files on the application server’s local disk.\n\n", + "generalRecommendations": "1. Ideally, avoid depending on dynamic data for file selection.\n2. Validate all input, regardless of source. Validation should be based on a whitelist: accept only data fitting a specified structure, rather than reject bad patterns. Check for:\n * Data type\n * Size\n * Range\n * Format\n * Expected values\n4. Accept dynamic data only for the filename, not for the path and folders.\n5. Ensure that file path is fully canonicalized.\n6. Explicitly limit the application to use a designated folder that is separate from the applications binary folder.\n7. Restrict the privileges of the application’s OS user to necessary files and folders. The application should not be able to write to the application binary folder, and should not read anything outside of the application folder and data folder.\n\n", + "cweId": 23 + }, + { + "vulnerabilityName": "Reflected_Absolute_Path_Traversal", + "risk": "An attacker could define arbitrary file path for the application to use, potentially leading to:\r\n* Stealing sensitive files, such as configuration or system files\r\n* Overwriting files such as program binaries, configuration files, or system files\r\n* Deleting critical files, causing denial of service (DoS).\n\n", + "cause": "The application uses user input in the file path for accessing files on the application server’s local disk.\n\n", + "generalRecommendations": "1. Ideally, avoid depending on dynamic data for file selection.\n2. Validate all input, regardless of source. Validation should be based on a whitelist: accept only data fitting a specified structure, rather than reject bad patterns. Check for:\n * Data type\n * Size\n * Range\n * Format\n * Expected values\n4. Accept dynamic data only for the filename, not for the path and folders.\n5. Ensure that file path is fully canonicalized.\n6. Explicitly limit the application to use a designated folder that is separate from the applications binary folder.\n7. Restrict the privileges of the application’s OS user to necessary files and folders. The application should not be able to write to the application binary folder, and should not read anything outside of the application folder and data folder.\n\n", + "cweId": 36 + }, + { + "vulnerabilityName": "Denial_Of_Service_Resource_Exhaustion", + "risk": "Denial-of-Service (DoS) will result in inaccessibility to some, if not all, facets of an application.\n\n", + "cause": "Computing resources are limited by server specifications, be it memory, storage, CPU, bandwidth and more. Failure to ensure that these resources are properly generated, managed and released may result in a system failing in unexpected ways, which may result in Denial-of-Service.\n\n", + "generalRecommendations": "Practice caution when handling system resources, from pointers in memory to files in the file system, to prevent potential abuse of available resources.\n\n", + "cweId": 400 + }, + { + "vulnerabilityName": "TruffleHog_HighEntropy_Strings", + "risk": "Hardcoded passwords expose the application to password leakage. If an attacker gains access to the source code, she will be able to steal the embedded passwords, and use them to impersonate a valid user. This could include impersonating end users to the application, or impersonating the application to a remote system, such as a database or a remote web service. \r\n\r\nOnce the attacker succeeds in impersonating the user or application, she will have full access to the system, and be able to do anything the impersonated identity could do.", + "cause": "The application codebase has string literal passwords embedded in the source code. This hardcoded value is used either to compare to user-provided credentials, or to authenticate downstream to a remote system (such as a database or a remote web service). \r\n\r\nAn attacker only needs to gain access to the source code to reveal the hardcoded password. Likewise, the attacker can reverse engineer the compiled application binaries, and easily retrieve the embedded password. Once found, the attacker can easily use the password in impersonation attacks, either directly on the application or to the remote system. \r\n\r\nFurthermore, once stolen, this password cannot be easily changed to prevent further misuse, unless a new version of the application is compiled. Moreover, if this application is distributed to numerous systems, stealing the password from one system automatically allows a class break in to all the deployed systems.", + "generalRecommendations": "* Do not hardcode any secret data in source code, especially not passwords. \r\n* In particular, user passwords should be stored in a database or directory service, and protected with a strong password hash (e.g. bcrypt, scrypt, PBKDF2, or Argon2). Do not compare user passwords with a hardcoded value. \r\n* Sytem passwords should be stored in a configuration file or the database, and protected with strong encryption (e.g. AES-256). Encryption keys should be securely managed, and not hardcoded.", + "cweId": 798 + }, + { + "vulnerabilityName": "Use_of_Non_Cryptographic_Random", + "risk": "Random values are often used as a mechanism to prevent malicious users from knowing or predicting a given value, such as a password, encryption key, or session identifier. Depending on what this random value is used for, an attacker would be able to predict the next numbers generated, or previously generated values, based on sources often used to derive certain randomness; however, while they may seem random, large statistical samples would demonstrate that they are insufficiently random, producing a much smaller space of possible \"random\" values than a truly random sample would. This could enable an attacker to derive or guess this value, and thus hijack another user's session, impersonate another user, or crack an encryption key (depending on what the pseudo-random value was used for).\n\n", + "cause": "The application uses a weak method of generating pseudo-random values, such that other numbers could be determined from a relatively small sample size. Since the pseudo-random number generator used is designed for statistically uniform distribution of values, it is approximately deterministic. Thus, after collecting a few generated values, it would be possible for an attacker to calculate past or future values. \r\nSpecifically, if this pseudo-random value is used in any security context, such as one-time passwords, keys, secret identifiers or salts - an attacker would likely be able to predict the next value generated and steal it, or guess a previously generated value and spoof its original intent.\n\n", + "generalRecommendations": "* Always use a cryptographically secure pseudo-random number generator, instead of basic random methods, particularly when dealing with a security context\r\n* Use the cryptorandom generator that is built-in to your language or platform, and ensure it is securely seeded. Do not seed the generator with a weak, non-random seed. (In most cases, the default is securely random). \r\n* Ensure you use a long enough random value, thus making brute-force attacks unfeasible.\n\n", + "cweId": 330 + }, + { + "vulnerabilityName": "TruffleHog_Regex_Matches", + "risk": "Hardcoded passwords expose the application to password leakage. If an attacker gains access to the source code, she will be able to steal the embedded passwords, and use them to impersonate a valid user. This could include impersonating end users to the application, or impersonating the application to a remote system, such as a database or a remote web service. \r\n\r\nOnce the attacker succeeds in impersonating the user or application, she will have full access to the system, and be able to do anything the impersonated identity could do.", + "cause": "The application codebase has string literal passwords embedded in the source code. This hardcoded value is used either to compare to user-provided credentials, or to authenticate downstream to a remote system (such as a database or a remote web service). \r\n\r\nAn attacker only needs to gain access to the source code to reveal the hardcoded password. Likewise, the attacker can reverse engineer the compiled application binaries, and easily retrieve the embedded password. Once found, the attacker can easily use the password in impersonation attacks, either directly on the application or to the remote system. \r\n\r\nFurthermore, once stolen, this password cannot be easily changed to prevent further misuse, unless a new version of the application is compiled. Moreover, if this application is distributed to numerous systems, stealing the password from one system automatically allows a class break in to all the deployed systems.", + "generalRecommendations": "* Do not hardcode any secret data in source code, especially not passwords. \r\n* In particular, user passwords should be stored in a database or directory service, and protected with a strong password hash (e.g. bcrypt, scrypt, PBKDF2, or Argon2). Do not compare user passwords with a hardcoded value. \r\n* Sytem passwords should be stored in a configuration file or the database, and protected with strong encryption (e.g. AES-256). Encryption keys should be securely managed, and not hardcoded.", + "cweId": 798 + }, + { + "vulnerabilityName": "Missing_Rooted_Device_Check", + "risk": "A rooted device can be vulnerable to multiple forms of attack, as applications, services and more may have significant access to privileged device operations. These operations include directly reading and writing memory, full file system access and more.\r\n\r\nWhile no checks for a rooted device are bulletproof, as a malicious application will almost assuredly be able to suppress any such checks, they are nonetheless recommended to protect application users from using it on a compromised device, for instances such as when a device has been rooted but not yet compromised.\n\n", + "cause": "The absence of proper device root check indicates that it would function normally on a rooted device.\n\n", + "generalRecommendations": "Conduct checks, preferably at startup, to ensure the device is not rooted. If it is rooted, warn the user, and consider preventing them from using the application altogether, to prevent compromise of sensitive information within the application.\n\n", + "cweId": 693 + }, + { + "vulnerabilityName": "Improper_Error_Handling", + "risk": "An unhandled error may cause unexpected behavior if it is not properly checked, depending on implementation the likeliest scenario being denial-of-service if the unhandled error aggregates, or triggers further errors downstream. A suppressed error or one that is not properly logged and documented will likely lead to loss of relevant information, hinder troubleshooting and potentially obscure code quality and security related issues.\n\n", + "cause": "An error is thrown, but is not handled - the error itself is either intentionally suppressed or, through a certain logic flow, is never actively handled. If an error is properly suppressed or never used, it is implicitly suppressed - this implies it is not logged or logically validated by application code.\n\n", + "generalRecommendations": "* Always log errors to ensure availability of error-related information\r\n* Perform logical checks when handling error-prone code to root out any potential unexpected behavior in case an operation fails\r\n * Cover all potential edge cases, however unlikely their occurrence may be, to avoid troubleshooting problems in the future\n* In Go, when using panic() or a panic-prone piece of code (such as a 3rd party library), always consider the following:\r\n * `recover()` must be deferred via the `defer` keyword - otherwise, the value of `recover()` would be `nil`, and then when the panic call occurs nothing will \"catch\" it\r\n * A call to `recover()` must be immediately in the deferred function, which is either anonymous or named. If the deferred function calls another function that contains `recover()`, its value would be `nil` and the thrown panic will continue after deferred code has finished running\r\n * Goroutines which panic cannot be recovered by their calling code. If a deferred `recover()` call precedes a call to panic-prone code that is invoked as a Go routine (via `go`), the deferred code will be ignored, panic will terminate the program and a stack trace for every ongoing routine will be dumped\r\n * Return values from calls to `recover()` should be handled like errors - they should be logged, and should fit code flow in case a panic was caused", + "cweId": 248 + }, + { + "vulnerabilityName": "Deprecated_API", + "risk": "Referencing deprecated modules can cause an application to be exposed to known vulnerabilities, that have been publicly reported and already fixed. A common attack technique is to scan applications for these known vulnerabilities, and then exploit the application through these deprecated versions. However, even if deprecated code is used in a way that is completely secure, its very use and inclusion in the code base would encourage developers to re-use the deprecated element in the future, potentially leaving the application vulnerable to attack, which is why deprecated code should be eliminated from the code-base as a matter of practice.\r\n\r\nNote that the actual risk involved depends on the specifics of any known vulnerabilities in older versions.\n\n", + "cause": "The application references code elements that have been declared as deprecated. This could include classes, functions, methods, properties, modules, or obsolete library versions that are either out of date by version, or have been entirely deprecated. It is likely that the code that references the obsolete element was developed before it was declared as obsolete, and in the meantime the referenced code was updated.\n\nIn Go - preceding code with a comment whose prefix is `// Deprecated: ` will denote it as deprecated.", + "generalRecommendations": "* Always prefer to use the most updated versions of libraries, packages, and other dependancies.\r\n* Do not use or reference any class, method, function, property, or other element that has been declared deprecated.\n\n", + "cweId": 477 + }, + { + "vulnerabilityName": "Incorrect_Block_Delimitation", + "risk": "Since in some languages braces are optional for blocks, the code may not explicitly delimit a block that is intended to contain two or more instructions, creating a logic error. In some cases, the logic error can have security implications.", + "cause": "The programmer indented a statement's block composed by more than one instruction, but, since there were no braces, only the first instruction was influenced by that statement.", + "generalRecommendations": "Always use explicit block delimitation.", + "cweId": 483 + } + ] +} \ No newline at end of file diff --git a/unittests/tools/test_checkmarx_one_parser.py b/unittests/tools/test_checkmarx_one_parser.py index 398ea9aff5..74a112a9ec 100644 --- a/unittests/tools/test_checkmarx_one_parser.py +++ b/unittests/tools/test_checkmarx_one_parser.py @@ -1,3 +1,5 @@ +import datetime + from dojo.models import Test from dojo.tools.checkmarx_one.parser import CheckmarxOneParser @@ -63,3 +65,77 @@ def test_checkmarx_one_new_format(self): finding_test = findings[0] self.assertEqual("Medium", finding_test.severity) self.assertEqual("/.github/workflows/checkmarx.yaml", finding_test.file_path) + + def test_checkmarx_vulnerabilities_from_scan_results(self): + def test_iac_finding(finding): + self.assertEqual("Dockerfile: Healthcheck Instruction Missing", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual("/Dockerfile", finding.file_path) + self.assertEqual(datetime.datetime(2024, 4, 16, 14, 36, 23), finding.date.replace(tzinfo=None)) + self.assertEqual(( + "**Actual Value**: Dockerfile doesn't contain instruction 'HEALTHCHECK'\n" + "**Expected Value**: Dockerfile should contain instruction 'HEALTHCHECK'\n" + ), finding.mitigation) + self.assertIn(( + "Ensure that HEALTHCHECK is being used. The HEALTHCHECK instruction tells Docker how to test a container to check that it is still working\n\n" + "**Category**: Insecure Configurations\n" + "**Issue Type**: MissingAttribute" + ), finding.description) + + def test_sast_finding(finding): + self.assertEqual("Go/Go Low Visibility/Deprecated API", finding.title) + self.assertEqual("Low", finding.severity) + self.assertEqual("/scripts/export-csv-full-base/e.go", finding.file_path) + self.assertEqual(9, finding.line) + self.assertEqual(datetime.datetime(2024, 4, 16, 14, 39, 59), finding.date.replace(tzinfo=None)) + self.assertEqual(( + "* Always prefer to use the most updated versions of libraries, packages, and other dependancies.\r\n" + "* Do not use or reference any class, method, function, property, or other element that has been declared deprecated.\n\n" + ), finding.mitigation) + self.assertEqual(( + "Method @DestinationMethod in @DestinationFile, at line @DestinationLine, calls an obsolete API, @DestinationElement. " + "This has been deprecated, and should not be used in a modern\xa0codebase.\n\n\n\n" + "The application references code elements that have been declared as deprecated. This could include classes, functions, " + "methods, properties, modules, or obsolete library versions that are either out of date by version, or have been entirely " + "deprecated. It is likely that the code that references the obsolete element was developed before it was declared as obsolete, " + "and in the meantime the referenced code was updated.\n\n" + "In Go - preceding code with a comment whose prefix is `// Deprecated: ` will denote it as deprecated." + ), finding.description) + self.assertEqual(( + "Referencing deprecated modules can cause an application to be exposed to known vulnerabilities, that have been publicly " + "reported and already fixed. A common attack technique is to scan applications for these known vulnerabilities, and then " + "exploit the application through these deprecated versions. However, even if deprecated code is used in a way that is " + "completely secure, its very use and inclusion in the code base would encourage developers to re-use the deprecated element " + "in the future, potentially leaving the application vulnerable to attack, which is why deprecated code should be eliminated " + "from the code-base as a matter of practice.\r\n\r\n" + "Note that the actual risk involved depends on the specifics of any known vulnerabilities in older versions.\n\n" + ), finding.impact) + self.assertEqual(( + "- OWASP ASVS\n" + "\t- V01 Architecture, Design and Threat Modeling\n" + "- OWASP Top 10 2021\n" + "\t- A6-Vulnerable and Outdated Components\n" + ), finding.references) + + def test_sca_finding(finding): + # Not implemented yet + pass + + with open("unittests/scans/checkmarx_one/vulnerabilities_from_scan_results.json") as testfile: + parser = CheckmarxOneParser() + findings = parser.get_findings(testfile, Test()) + self.assertEqual(146, len(findings)) + for index in range(len(findings)): + print(index, findings[index]) + with self.subTest(i=0): + for finding in findings: + self.assertIsNotNone(finding.title) + self.assertIsNotNone(finding.test) + self.assertIsNotNone(finding.date) + self.assertIsNotNone(finding.severity) + self.assertIsNotNone(finding.description) + iac_finding = findings[145] + test_iac_finding(iac_finding) + sast_finding = findings[124] + self.maxDiff = None + test_sast_finding(sast_finding) From 6fd7edadbacc82f7cf944393b90e540aad6bdabe Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Sat, 4 May 2024 00:56:06 +0200 Subject: [PATCH 131/138] :sparkles: implement progpilot SAST parser #10044 (#10052) * :sparkles: implement progpilot SAST parser #10044 * add docs * finish progpilot * use more available Finding fields * ruff linter * advance unittests * fix ruff * Update unittests/tools/test_progpilot_parser.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Update unittests/tools/test_progpilot_parser.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Update unittests/tools/test_progpilot_parser.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Update unittests/tools/test_progpilot_parser.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * ruff * ruff --------- Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> --- .../en/integrations/parsers/file/progpilot.md | 8 + dojo/tools/progpilot/__init__.py | 1 + dojo/tools/progpilot/parser.py | 80 +++++++++ unittests/scans/progpilot/progpilot.json | 51 ++++++ unittests/scans/progpilot/progpilot2.json | 88 ++++++++++ unittests/scans/progpilot/progpilot3.json | 164 ++++++++++++++++++ unittests/scans/progpilot/progpilot4.json | 51 ++++++ unittests/tools/test_progpilot_parser.py | 44 +++++ 8 files changed, 487 insertions(+) create mode 100644 docs/content/en/integrations/parsers/file/progpilot.md create mode 100644 dojo/tools/progpilot/__init__.py create mode 100644 dojo/tools/progpilot/parser.py create mode 100644 unittests/scans/progpilot/progpilot.json create mode 100644 unittests/scans/progpilot/progpilot2.json create mode 100644 unittests/scans/progpilot/progpilot3.json create mode 100644 unittests/scans/progpilot/progpilot4.json create mode 100644 unittests/tools/test_progpilot_parser.py diff --git a/docs/content/en/integrations/parsers/file/progpilot.md b/docs/content/en/integrations/parsers/file/progpilot.md new file mode 100644 index 0000000000..2fa297117f --- /dev/null +++ b/docs/content/en/integrations/parsers/file/progpilot.md @@ -0,0 +1,8 @@ +--- +title: "Progpilot" +toc_hide: true +--- +This parser imports the Progpilot SAST JSON output. The scanner can be found [here](https://github.com/designsecurity/progpilot). + +### Sample Scan Data +Sample Progpilot Parser scans can be found [here](https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans/progpilot). \ No newline at end of file diff --git a/dojo/tools/progpilot/__init__.py b/dojo/tools/progpilot/__init__.py new file mode 100644 index 0000000000..3ad798a42b --- /dev/null +++ b/dojo/tools/progpilot/__init__.py @@ -0,0 +1 @@ +__author__ = "manuel-sommer" diff --git a/dojo/tools/progpilot/parser.py b/dojo/tools/progpilot/parser.py new file mode 100644 index 0000000000..e6a5d4b7a4 --- /dev/null +++ b/dojo/tools/progpilot/parser.py @@ -0,0 +1,80 @@ +import json + +from dojo.models import Finding + + +class ProgpilotParser: + def get_scan_types(self): + return ["Progpilot Scan"] + + def get_label_for_scan_types(self, scan_type): + return "Progpilot Scan" + + def get_description_for_scan_types(self, scan_type): + return "Progpilot JSON vulnerability report format." + + def get_findings(self, filename, test): + findings = [] + description = "" + results = json.load(filename) + for result in results: + source_name = result.get("source_name", None) + source_line = result.get("source_line", None) + source_column = result.get("source_column", None) + source_file = result.get("source_file", None) + tainted_flow = result.get("tainted_flow", None) + sink_name = result.get("sink_name", None) + sink_line = result.get("sink_line", None) + sink_column = result.get("sink_column", None) + sink_file = result.get("sink_file", None) + vuln_name = result.get("vuln_name", None) + vuln_cwe = result.get("vuln_cwe", None) + vuln_id = result.get("vuln_id", None) + vuln_type = result.get("vuln_type", None) + vuln_rule = result.get("vuln_rule", None) + vuln_line = result.get("vuln_line", None) + vuln_column = result.get("vuln_column", None) + vuln_file = result.get("vuln_file", None) + vuln_description = result.get("vuln_description", None) + description += "**vuln_type:** " + vuln_type + "\n" + if source_name is not None: + description += "**source_name:** " + str(source_name) + "\n" + if source_line is not None: + description += "**source_line:** " + str(source_line) + "\n" + if source_column is not None: + description += "**source_column:** " + str(source_column) + "\n" + if source_file is not None: + description += "**source_file:** " + str(source_file) + "\n" + if tainted_flow is not None: + description += "**tainted_flow:** " + str(tainted_flow) + "\n" + if sink_name is not None: + description += "**sink_name:** " + str(sink_name) + "\n" + if sink_column is not None: + description += "**sink_column:** " + str(sink_column) + "\n" + if vuln_rule is not None: + description += "**vuln_rule:** " + str(vuln_rule) + "\n" + if vuln_column is not None: + description += "**vuln_column:** " + str(vuln_column) + "\n" + if vuln_description is not None: + description += "**vuln_description:** " + str(vuln_description) + "\n" + find = Finding( + title=vuln_name, + test=test, + description=description, + severity="Medium", + dynamic_finding=False, + static_finding=True, + unique_id_from_tool=vuln_id + ) + if sink_line is not None: + find.line = sink_line + elif vuln_line is not None: + find.line = vuln_line + if sink_file is not None: + find.file_path = sink_file + elif vuln_file is not None: + find.file_path = vuln_file + if vuln_cwe is not None: + find.cwe = int(vuln_cwe.split("CWE_")[1]) + findings.append(find) + return findings diff --git a/unittests/scans/progpilot/progpilot.json b/unittests/scans/progpilot/progpilot.json new file mode 100644 index 0000000000..bfa3cc6e37 --- /dev/null +++ b/unittests/scans/progpilot/progpilot.json @@ -0,0 +1,51 @@ +[ + { + "source_name": [ + "$sql" + ], + "source_line": [ + 590 + ], + "source_column": [ + 25854 + ], + "source_file": [ + "\/home\/kali\/Modules\/progpilot\/Order.php" + ], + "tainted_flow": [ + [ + { + "flow_name": "$dni", + "flow_line": 588, + "flow_column": 25832, + "flow_file": "\/home\/User\/Modules\/progpilot\/Order.php" + }, + { + "flow_name": "$getValue_return", + "flow_line": 565, + "flow_column": 25050, + "flow_file": "\/home\/User\/Modules\/progpilot\/Order.php" + } + ] + ], + "sink_name": "executeS", + "sink_line": 593, + "sink_column": 26002, + "sink_file": "\/home\/User\/Modules\/progpilot\/Order.php", + "vuln_name": "sql_injection", + "vuln_cwe": "CWE_89", + "vuln_id": "9c4f078e57a235d34183ddb1dd39ef8b91fc2eeed26718c5c5eb053874e401e6", + "vuln_type": "taint-style" + }, + { + "vuln_rule": "MUST_VERIFY_DEFINITION", + "vuln_name": "security misconfiguration", + "vuln_line": 461, + "vuln_column": 18375, + "vuln_file": "\/home\/User\/Modules\/progpilot\/Order.php", + "vuln_description": "curl must verify that the certificate is trusted (CURLOPT_SSL_VERIFYPEER set to true)", + "vuln_cwe": "CWE_295", + "vuln_id": "797d1acd46cbf6305ec0a2480ed29414a76326bab6bebe533df8050f0205040d", + "vuln_type": "custom" + } +] \ No newline at end of file diff --git a/unittests/scans/progpilot/progpilot2.json b/unittests/scans/progpilot/progpilot2.json new file mode 100644 index 0000000000..2a71e89620 --- /dev/null +++ b/unittests/scans/progpilot/progpilot2.json @@ -0,0 +1,88 @@ +[ + { + "source_name": [ + "$json_encode_return" + ], + "source_line": [ + 61 + ], + "source_column": [ + 1590 + ], + "source_file": [ + "\/home\/User\/Modules\/progpilot\/ajax.php" + ], + "tainted_flow": [ + [ + { + "flow_name": "$json_encode_param0_line61_column1590_progpilot", + "flow_line": 61, + "flow_column": 1590, + "flow_file": "\/home\/User\/Modules\/progpilot\/ajax.php" + }, + { + "flow_name": "$response", + "flow_line": 59, + "flow_column": 1561, + "flow_file": "\/home\/User\/Modules\/progpilot\/ajax.php" + }, + { + "flow_name": "$resp", + "flow_line": 26, + "flow_column": 765, + "flow_file": "\/home\/User\/Modules\/progpilot\/ajax.php" + }, + { + "flow_name": "$validateAmount_return", + "flow_line": 26, + "flow_column": 773, + "flow_file": "\/home\/User\/Modules\/progpilot\/ajax.php" + }, + { + "flow_name": "$validateAmount_param0_line26_column773_progpilot", + "flow_line": 26, + "flow_column": 773, + "flow_file": "\/home\/User\/Modules\/progpilot\/ajax.php" + }, + { + "flow_name": "$vals", + "flow_line": 8, + "flow_column": 281, + "flow_file": "\/home\/User\/Modules\/progpilot\/ajax.php" + }, + { + "flow_name": "$json_decode_return", + "flow_line": 8, + "flow_column": 289, + "flow_file": "\/home\/User\/Modules\/progpilot\/ajax.php" + }, + { + "flow_name": "$json_decode_param0_line8_column289_progpilot", + "flow_line": 8, + "flow_column": 289, + "flow_file": "\/home\/User\/Modules\/progpilot\/ajax.php" + }, + { + "flow_name": "$frontRequest", + "flow_line": 7, + "flow_column": 231, + "flow_file": "\/home\/User\/Modules\/progpilot\/ajax.php" + }, + { + "flow_name": "$file_get_contents_return", + "flow_line": 7, + "flow_column": 247, + "flow_file": "\/home\/User\/Modules\/progpilot\/ajax.php" + } + ] + ], + "sink_name": "echo", + "sink_line": 61, + "sink_column": 1590, + "sink_file": "\/home\/kali\/Modules\/progpilot\/ajax.php", + "vuln_name": "xss", + "vuln_cwe": "CWE_79", + "vuln_id": "4c1c5e204a59146a9a046a6a49042ce9a26a7cfd952955ec8614a22b093e451d", + "vuln_type": "taint-style" + } +] \ No newline at end of file diff --git a/unittests/scans/progpilot/progpilot3.json b/unittests/scans/progpilot/progpilot3.json new file mode 100644 index 0000000000..bbd1d9da44 --- /dev/null +++ b/unittests/scans/progpilot/progpilot3.json @@ -0,0 +1,164 @@ +[ + { + "source_name": [ + "$sql" + ], + "source_line": [ + 610 + ], + "source_column": [ + 26536 + ], + "source_file": [ + "\/mnt\/c\/Users\/User\/Downloads\/OrderController (1).php" + ], + "tainted_flow": [ + [ + { + "flow_name": "$dni", + "flow_line": 608, + "flow_column": 26514, + "flow_file": "\/mnt\/c\/Users\/User\/Downloads\/OrderController (1).php" + }, + { + "flow_name": "$getValue_return", + "flow_line": 585, + "flow_column": 25732, + "flow_file": "\/mnt\/c\/Users\/User\/Downloads\/OrderController (1).php" + } + ] + ], + "sink_name": "executeS", + "sink_line": 613, + "sink_column": 26684, + "sink_file": "\/mnt\/c\/Users\/User\/Downloads\/OrderController (1).php", + "vuln_name": "sql_injection", + "vuln_cwe": "CWE_89", + "vuln_id": "49aff3865be911c68dd971f0108c74acac9c1db772eb0a17bb455b2232993e22", + "vuln_type": "taint-style" + }, + { + "source_name": [ + "$sql" + ], + "source_line": [ + 610 + ], + "source_column": [ + 26536 + ], + "source_file": [ + "\/mnt\/c\/Users\/User\/Downloads\/OrderController (1).php" + ], + "tainted_flow": [ + [ + { + "flow_name": "$dni", + "flow_line": 608, + "flow_column": 26514, + "flow_file": "\/mnt\/c\/Users\/User\/Downloads\/OrderController (1).php" + }, + { + "flow_name": "$getValue_return", + "flow_line": 565, + "flow_column": 25050, + "flow_file": "\/mnt\/c\/Users\/User\/Downloads\/OrderController.php" + } + ] + ], + "sink_name": "executeS", + "sink_line": 613, + "sink_column": 26684, + "sink_file": "\/mnt\/c\/Users\/User\/Downloads\/OrderController (1).php", + "vuln_name": "sql_injection", + "vuln_cwe": "CWE_89", + "vuln_id": "7cf37b7671cc8c7d72adadad7d173158ed0b808a445d8cac800a6a16463a4b18", + "vuln_type": "taint-style" + }, + { + "source_name": [ + "$json_encode_return" + ], + "source_line": [ + 61 + ], + "source_column": [ + 1590 + ], + "source_file": [ + "\/mnt\/c\/Users\/User\/Downloads\/ajax.php" + ], + "tainted_flow": [ + [ + { + "flow_name": "$json_encode_param0_line61_column1590_progpilot", + "flow_line": 61, + "flow_column": 1590, + "flow_file": "\/mnt\/c\/Users\/User\/Downloads\/ajax.php" + }, + { + "flow_name": "$response", + "flow_line": 59, + "flow_column": 1561, + "flow_file": "\/mnt\/c\/Users\/User\/Downloads\/ajax.php" + }, + { + "flow_name": "$resp", + "flow_line": 26, + "flow_column": 765, + "flow_file": "\/mnt\/c\/Users\/User\/Downloads\/ajax.php" + }, + { + "flow_name": "$validateAmount_return", + "flow_line": 26, + "flow_column": 773, + "flow_file": "\/mnt\/c\/Users\/User\/Downloads\/ajax.php" + }, + { + "flow_name": "$validateAmount_param0_line26_column773_progpilot", + "flow_line": 26, + "flow_column": 773, + "flow_file": "\/mnt\/c\/Users\/User\/Downloads\/ajax.php" + }, + { + "flow_name": "$vals", + "flow_line": 8, + "flow_column": 281, + "flow_file": "\/mnt\/c\/Users\/User\/Downloads\/ajax.php" + }, + { + "flow_name": "$json_decode_return", + "flow_line": 8, + "flow_column": 289, + "flow_file": "\/mnt\/c\/Users\/User\/Downloads\/ajax.php" + }, + { + "flow_name": "$json_decode_param0_line8_column289_progpilot", + "flow_line": 8, + "flow_column": 289, + "flow_file": "\/mnt\/c\/Users\/User\/Downloads\/ajax.php" + }, + { + "flow_name": "$frontRequest", + "flow_line": 7, + "flow_column": 231, + "flow_file": "\/mnt\/c\/Users\/User\/Downloads\/ajax.php" + }, + { + "flow_name": "$file_get_contents_return", + "flow_line": 7, + "flow_column": 247, + "flow_file": "\/mnt\/c\/Users\/User\/Downloads\/ajax.php" + } + ] + ], + "sink_name": "echo", + "sink_line": 61, + "sink_column": 1590, + "sink_file": "\/mnt\/c\/Users\/User\/Downloads\/ajax.php", + "vuln_name": "xss", + "vuln_cwe": "CWE_79", + "vuln_id": "ec40abc277f125bcbef6c07d0fa9996e65e58dbce75957fb162dd86139d8b615", + "vuln_type": "taint-style" + } +] \ No newline at end of file diff --git a/unittests/scans/progpilot/progpilot4.json b/unittests/scans/progpilot/progpilot4.json new file mode 100644 index 0000000000..bfa3cc6e37 --- /dev/null +++ b/unittests/scans/progpilot/progpilot4.json @@ -0,0 +1,51 @@ +[ + { + "source_name": [ + "$sql" + ], + "source_line": [ + 590 + ], + "source_column": [ + 25854 + ], + "source_file": [ + "\/home\/kali\/Modules\/progpilot\/Order.php" + ], + "tainted_flow": [ + [ + { + "flow_name": "$dni", + "flow_line": 588, + "flow_column": 25832, + "flow_file": "\/home\/User\/Modules\/progpilot\/Order.php" + }, + { + "flow_name": "$getValue_return", + "flow_line": 565, + "flow_column": 25050, + "flow_file": "\/home\/User\/Modules\/progpilot\/Order.php" + } + ] + ], + "sink_name": "executeS", + "sink_line": 593, + "sink_column": 26002, + "sink_file": "\/home\/User\/Modules\/progpilot\/Order.php", + "vuln_name": "sql_injection", + "vuln_cwe": "CWE_89", + "vuln_id": "9c4f078e57a235d34183ddb1dd39ef8b91fc2eeed26718c5c5eb053874e401e6", + "vuln_type": "taint-style" + }, + { + "vuln_rule": "MUST_VERIFY_DEFINITION", + "vuln_name": "security misconfiguration", + "vuln_line": 461, + "vuln_column": 18375, + "vuln_file": "\/home\/User\/Modules\/progpilot\/Order.php", + "vuln_description": "curl must verify that the certificate is trusted (CURLOPT_SSL_VERIFYPEER set to true)", + "vuln_cwe": "CWE_295", + "vuln_id": "797d1acd46cbf6305ec0a2480ed29414a76326bab6bebe533df8050f0205040d", + "vuln_type": "custom" + } +] \ No newline at end of file diff --git a/unittests/tools/test_progpilot_parser.py b/unittests/tools/test_progpilot_parser.py new file mode 100644 index 0000000000..0cfbaf1804 --- /dev/null +++ b/unittests/tools/test_progpilot_parser.py @@ -0,0 +1,44 @@ +from dojo.models import Test +from dojo.tools.progpilot.parser import ProgpilotParser + +from ..dojo_test_case import DojoTestCase + + +class TestProgpilotParser(DojoTestCase): + + def test_progpilotparser_single_has_many_findings(self): + testfile = open("unittests/scans/progpilot/progpilot.json") + parser = ProgpilotParser() + findings = parser.get_findings(testfile, Test()) + testfile.close() + self.assertEqual(2, len(findings)) + with self.subTest(i=0): + finding = findings[0] + self.assertEqual("Medium", finding.severity) + self.assertIsNotNone(finding.description) + self.assertGreater(len(finding.description), 0) + self.assertEqual(89, finding.cwe) + self.assertEqual("sql_injection", finding.title) + self.assertEqual("/home/User/Modules/progpilot/Order.php", finding.file_path) + self.assertEqual(593, finding.line) + + def test_progpilotparser_single_has_one_finding(self): + testfile = open("unittests/scans/progpilot/progpilot2.json") + parser = ProgpilotParser() + findings = parser.get_findings(testfile, Test()) + testfile.close() + self.assertEqual(1, len(findings)) + + def test_progpilotparser_single_has_many_findings3(self): + testfile = open("unittests/scans/progpilot/progpilot3.json") + parser = ProgpilotParser() + findings = parser.get_findings(testfile, Test()) + testfile.close() + self.assertEqual(3, len(findings)) + + def test_progpilotparser_single_has_many_findings4(self): + testfile = open("unittests/scans/progpilot/progpilot4.json") + parser = ProgpilotParser() + findings = parser.get_findings(testfile, Test()) + testfile.close() + self.assertEqual(2, len(findings)) From 3a79a560ecbd9aa4a71bd17373b659cfdb46b4e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 10:54:32 -0500 Subject: [PATCH 132/138] Bump coverage from 7.5.0 to 7.5.1 (#10123) Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.5.0 to 7.5.1. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.5.0...7.5.1) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 6c86c9c6d8..6a0ca3017b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ asteval==0.9.32 bleach==6.1.0 bleach[css] celery==5.4.0 -coverage==7.5.0 +coverage==7.5.1 defusedxml==0.7.1 django_celery_results==2.5.1 django-auditlog==2.3.0 From 246bf3e15081df1b10528de857fc0502d970f5f7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 10:55:20 -0500 Subject: [PATCH 133/138] Bump boto3 from 1.34.97 to 1.34.98 (#10122) Bumps [boto3](https://github.com/boto/boto3) from 1.34.97 to 1.34.98. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.34.97...1.34.98) --- updated-dependencies: - dependency-name: boto3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 6a0ca3017b..85e3bbabc2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -75,7 +75,7 @@ django-ratelimit==4.1.0 argon2-cffi==23.1.0 blackduck==1.1.3 pycurl==7.45.3 # Required for Celery Broker AWS (SQS) support -boto3==1.34.97 # Required for Celery Broker AWS (SQS) support +boto3==1.34.98 # Required for Celery Broker AWS (SQS) support netaddr==1.2.1 vulners==2.1.5 fontawesomefree==6.5.1 From 47683778a60ebb9b25406a044331f0e72d43003b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 10:56:04 -0500 Subject: [PATCH 134/138] Bump ruff from 0.4.2 to 0.4.3 (#10121) Bumps [ruff](https://github.com/astral-sh/ruff) from 0.4.2 to 0.4.3. - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md) - [Commits](https://github.com/astral-sh/ruff/compare/v0.4.2...v0.4.3) --- updated-dependencies: - dependency-name: ruff dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-lint.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-lint.txt b/requirements-lint.txt index 79039f7bbc..ace8ae4ab0 100644 --- a/requirements-lint.txt +++ b/requirements-lint.txt @@ -1 +1 @@ -ruff==0.4.2 \ No newline at end of file +ruff==0.4.3 \ No newline at end of file From 5b69a002ca879e139bfce7d426f2c1b6b97a9261 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 10:56:40 -0500 Subject: [PATCH 135/138] Bump sqlalchemy from 2.0.29 to 2.0.30 (#10120) Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 2.0.29 to 2.0.30. - [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases) - [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst) - [Commits](https://github.com/sqlalchemy/sqlalchemy/commits) --- updated-dependencies: - dependency-name: sqlalchemy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 85e3bbabc2..547bd7aa83 100644 --- a/requirements.txt +++ b/requirements.txt @@ -41,7 +41,7 @@ python-dateutil==2.9.0.post0 pytz==2024.1 redis==5.0.4 requests==2.31.0 -sqlalchemy==2.0.29 # Required by Celery broker transport +sqlalchemy==2.0.30 # Required by Celery broker transport urllib3==1.26.18 uWSGI==2.0.25.1 vobject==0.9.7 From e420d028478dff959e5148975d4d59abf858c983 Mon Sep 17 00:00:00 2001 From: dogboat <dogboat@users.noreply.github.com> Date: Mon, 6 May 2024 13:13:33 -0400 Subject: [PATCH 136/138] Class based reports views (#10124) * class-based-reports-views Initial work on class-based views for reports * class-based-reports-views Refactor a bit * class-based-reports-views move reports navbar entry into a block * class-based-reports-views clean up some variables * class-based-reports-views ReportFindingFilter add a few new filter fields * class-based-reports-views linting fix --- dojo/filters.py | 7 +- dojo/reports/urls.py | 4 +- dojo/reports/views.py | 155 ++++++++++++++++++++++----------------- dojo/reports/widgets.py | 36 ++------- dojo/templates/base.html | 2 + 5 files changed, 104 insertions(+), 100 deletions(-) diff --git a/dojo/filters.py b/dojo/filters.py index 460a21f6b0..08b84de46a 100644 --- a/dojo/filters.py +++ b/dojo/filters.py @@ -2881,6 +2881,7 @@ class ReportFindingFilter(FindingTagFilter): queryset=Product_Type.objects.none(), label="Product Type") test__engagement__product__lifecycle = MultipleChoiceFilter(choices=Product.LIFECYCLE_CHOICES, label="Product Lifecycle") + test__engagement = ModelMultipleChoiceFilter(queryset=Engagement.objects.none(), label="Engagement") severity = MultipleChoiceFilter(choices=SEVERITY_CHOICES) active = ReportBooleanFilter() is_mitigated = ReportBooleanFilter() @@ -2901,8 +2902,8 @@ class Meta: model = Finding # exclude sonarqube issue as by default it will show all without checking permissions exclude = ['date', 'cwe', 'url', 'description', 'mitigation', 'impact', - 'references', 'test', 'sonarqube_issue', - 'thread_id', 'notes', 'endpoints', + 'references', 'sonarqube_issue', + 'thread_id', 'notes', 'numerical_severity', 'reporter', 'last_reviewed', 'jira_creation', 'jira_change', 'files'] @@ -2952,6 +2953,8 @@ def __init__(self, *args, **kwargs): if 'test__engagement__product' in self.form.fields: self.form.fields[ 'test__engagement__product'].queryset = get_authorized_products(Permissions.Product_View) + if 'test__engagement' in self.form.fields: + self.form.fields['test__engagement'].queryset = get_authorized_engagements(Permissions.Engagement_View) @property def qs(self): diff --git a/dojo/reports/urls.py b/dojo/reports/urls.py index 31503b6c51..1d02fbbf55 100644 --- a/dojo/reports/urls.py +++ b/dojo/reports/urls.py @@ -23,13 +23,13 @@ re_path(r'^reports/cover$', views.report_cover_page, name='report_cover_page'), re_path(r'^reports/builder$', - views.report_builder, name='report_builder'), + views.ReportBuilder.as_view(), name='report_builder'), re_path(r'^reports/findings$', views.report_findings, name='report_findings'), re_path(r'^reports/endpoints$', views.report_endpoints, name='report_endpoints'), re_path(r'^reports/custom$', - views.custom_report, name='custom_report'), + views.CustomReport.as_view(), name='custom_report'), re_path(r'^reports/quick$', views.QuickReportView.as_view(), name='quick_report'), re_path(r'^reports/csv_export$', diff --git a/dojo/reports/views.py b/dojo/reports/views.py index 3b2d8c193b..cb7a599f11 100644 --- a/dojo/reports/views.py +++ b/dojo/reports/views.py @@ -3,11 +3,12 @@ import re from datetime import datetime from tempfile import NamedTemporaryFile +from typing import List from dateutil.relativedelta import relativedelta from django.conf import settings from django.core.exceptions import PermissionDenied -from django.http import Http404, HttpResponse, QueryDict +from django.http import Http404, HttpRequest, HttpResponse, QueryDict from django.shortcuts import get_object_or_404, render from django.utils import timezone from django.views import View @@ -30,6 +31,7 @@ PageBreak, ReportOptions, TableOfContents, + Widget, WYSIWYGContent, report_widget_factory, ) @@ -64,75 +66,94 @@ def report_url_resolver(request): return url_resolver + ":" + request.META['SERVER_PORT'] -def report_builder(request): - add_breadcrumb(title="Report Builder", top_level=True, request=request) - findings = get_authorized_findings(Permissions.Finding_View) - findings = ReportFindingFilter(request.GET, queryset=findings) - endpoints = Endpoint.objects.filter(finding__active=True, - finding__verified=True, - finding__false_p=False, - finding__duplicate=False, - finding__out_of_scope=False, - ).distinct() - filter_string_matching = get_system_setting("filter_string_matching", False) - filter_class = EndpointFilterWithoutObjectLookups if filter_string_matching else EndpointFilter - endpoints = filter_class(request.GET, queryset=endpoints, user=request.user) - - in_use_widgets = [ReportOptions(request=request)] - available_widgets = [CoverPage(request=request), - TableOfContents(request=request), - WYSIWYGContent(request=request), - FindingList(request=request, findings=findings), - EndpointList(request=request, endpoints=endpoints), - PageBreak()] - return render(request, - 'dojo/report_builder.html', - {"available_widgets": available_widgets, - "in_use_widgets": in_use_widgets}) - - -def custom_report(request): - # saving the report - form = CustomReportJsonForm(request.POST) - host = report_url_resolver(request) - if form.is_valid(): - selected_widgets = report_widget_factory(json_data=request.POST['json'], request=request, user=request.user, - finding_notes=False, finding_images=False, host=host) - report_format = 'AsciiDoc' - finding_notes = True - finding_images = True - - if 'report-options' in selected_widgets: - options = selected_widgets['report-options'] - report_format = options.report_type - finding_notes = (options.include_finding_notes == '1') - finding_images = (options.include_finding_images == '1') - - selected_widgets = report_widget_factory(json_data=request.POST['json'], request=request, user=request.user, - finding_notes=finding_notes, finding_images=finding_images, host=host) +class ReportBuilder(View): + def get(self, request: HttpRequest) -> HttpResponse: + add_breadcrumb(title="Report Builder", top_level=True, request=request) + return render(request, self.get_template(), self.get_context(request)) + + def get_findings(self, request: HttpRequest): + findings = get_authorized_findings(Permissions.Finding_View) + return ReportFindingFilter(self.request.GET, queryset=findings) + + def get_endpoints(self, request: HttpRequest): + endpoints = Endpoint.objects.filter(finding__active=True, + finding__verified=True, + finding__false_p=False, + finding__duplicate=False, + finding__out_of_scope=False, + ).distinct() + filter_string_matching = get_system_setting("filter_string_matching", False) + filter_class = EndpointFilterWithoutObjectLookups if filter_string_matching else EndpointFilter + return filter_class(request.GET, queryset=endpoints, user=request.user) + + def get_available_widgets(self, request: HttpRequest) -> List[Widget]: + return [ + CoverPage(request=request), + TableOfContents(request=request), + WYSIWYGContent(request=request), + FindingList(request=request, findings=self.get_findings(request)), + EndpointList(request=request, endpoints=self.get_endpoints(request)), + PageBreak()] + + def get_in_use_widgets(self, request): + return [ReportOptions(request=request)] - if report_format == 'AsciiDoc': - widgets = list(selected_widgets.values()) - return render(request, - 'dojo/custom_asciidoc_report.html', - {"widgets": widgets, - "host": host, - "finding_notes": finding_notes, - "finding_images": finding_images, - "user_id": request.user.id}) - elif report_format == 'HTML': - widgets = list(selected_widgets.values()) - return render(request, - 'dojo/custom_html_report.html', - {"widgets": widgets, - "host": "", - "finding_notes": finding_notes, - "finding_images": finding_images, - "user_id": request.user.id}) + def get_template(self): + return 'dojo/report_builder.html' + + def get_context(self, request: HttpRequest) -> dict: + return { + "available_widgets": self.get_available_widgets(request), + "in_use_widgets": self.get_in_use_widgets(request), } + + +class CustomReport(View): + def post(self, request: HttpRequest) -> HttpResponse: + # saving the report + form = self.get_form(request) + if form.is_valid(): + self._set_state(request) + return render(request, self.get_template(), self.get_context()) else: raise PermissionDenied() - else: - raise PermissionDenied() + + def _set_state(self, request: HttpRequest): + self.request = request + self.selected_widgets = self.get_selected_widgets(request) + self.widgets = list(self.selected_widgets.values()) + + def get_selected_widgets(self, request): + selected_widgets = report_widget_factory(json_data=request.POST['json'], request=request, finding_notes=False, + finding_images=False) + + if options := selected_widgets.get('report-options', None): + self.report_format = options.report_type + self.finding_notes = (options.include_finding_notes == '1') + self.finding_images = (options.include_finding_images == '1') + else: + self.report_format = 'AsciiDoc' + self.finding_notes = True + self.finding_images = True + + return report_widget_factory(json_data=request.POST['json'], request=request, finding_notes=self.finding_notes, + finding_images=self.finding_images) + + def get_form(self, request): + return CustomReportJsonForm(request.POST) + + def get_template(self): + if self.report_format == 'AsciiDoc': + return 'dojo/custom_asciidoc_report.html', + elif self.report_format == 'HTML': + return 'dojo/custom_html_report.html' + else: + raise PermissionDenied() + + def get_context(self): + return { + "widgets": self.widgets, + "finding_notes": self.finding_notes, + "finding_images": self.finding_images, } def report_findings(request): diff --git a/dojo/reports/widgets.py b/dojo/reports/widgets.py index 665b7758b4..8eef453bb8 100644 --- a/dojo/reports/widgets.py +++ b/dojo/reports/widgets.py @@ -247,11 +247,6 @@ class FindingList(Widget): def __init__(self, *args, **kwargs): if 'request' in kwargs: self.request = kwargs.get('request') - if 'user_id' in kwargs: - self.user_id = kwargs.get('user_id') - - if 'host' in kwargs: - self.host = kwargs.get('host') if 'findings' in kwargs: self.findings = kwargs.get('findings') @@ -290,10 +285,8 @@ def __init__(self, *args, **kwargs): def get_asciidoc(self): asciidoc = render_to_string("dojo/custom_asciidoc_report_findings.html", {"findings": self.findings.qs, - "host": self.host, "include_finding_notes": self.finding_notes, - "include_finding_images": self.finding_images, - "user_id": self.user_id}) + "include_finding_images": self.finding_images, }) return mark_safe(asciidoc) def get_html(self): @@ -301,9 +294,7 @@ def get_html(self): {"title": self.title, "findings": self.findings.qs, "include_finding_notes": self.finding_notes, - "include_finding_images": self.finding_images, - "host": self.host, - "user_id": self.user_id}) + "include_finding_images": self.finding_images, }) return mark_safe(html) def get_option_form(self): @@ -323,11 +314,6 @@ class EndpointList(Widget): def __init__(self, *args, **kwargs): if 'request' in kwargs: self.request = kwargs.get('request') - if 'user_id' in kwargs: - self.user_id = kwargs.get('user_id') - - if 'host' in kwargs: - self.host = kwargs.get('host') if 'endpoints' in kwargs: self.endpoints = kwargs.get('endpoints') @@ -363,18 +349,14 @@ def get_html(self): {"title": self.title, "endpoints": self.endpoints.qs, "include_finding_notes": self.finding_notes, - "include_finding_images": self.finding_images, - "host": self.host, - "user_id": self.user_id}) + "include_finding_images": self.finding_images, }) return mark_safe(html) def get_asciidoc(self): asciidoc = render_to_string("dojo/custom_asciidoc_report_endpoints.html", {"endpoints": self.endpoints.qs, - "host": self.host, "include_finding_notes": self.finding_notes, - "include_finding_images": self.finding_images, - "user_id": self.user_id}) + "include_finding_images": self.finding_images, }) return mark_safe(asciidoc) def get_option_form(self): @@ -388,8 +370,7 @@ def get_option_form(self): return mark_safe(html) -def report_widget_factory(json_data=None, request=None, user=None, finding_notes=False, finding_images=False, - host=None): +def report_widget_factory(json_data=None, request=None, finding_notes=False, finding_images=False): selected_widgets = OrderedDict() widgets = json.loads(json_data) for idx, widget in enumerate(widgets): @@ -413,9 +394,8 @@ def report_widget_factory(json_data=None, request=None, user=None, finding_notes filter_string_matching = get_system_setting("filter_string_matching", False) filter_class = EndpointFilterWithoutObjectLookups if filter_string_matching else EndpointFilter endpoints = filter_class(d, queryset=endpoints, user=request.user) - user_id = user.id if user is not None else None endpoints = EndpointList(request=request, endpoints=endpoints, finding_notes=finding_notes, - finding_images=finding_images, host=host, user_id=user_id) + finding_images=finding_images) selected_widgets[list(widget.keys())[0] + '-' + str(idx)] = endpoints @@ -429,11 +409,9 @@ def report_widget_factory(json_data=None, request=None, user=None, finding_notes d[item['name']] = item['value'] findings = ReportFindingFilter(d, queryset=findings) - user_id = user.id if user is not None else None selected_widgets[list(widget.keys())[0] + '-' + str(idx)] = FindingList(request=request, findings=findings, finding_notes=finding_notes, - finding_images=finding_images, - host=host, user_id=user_id) + finding_images=finding_images) if list(widget.keys())[0] == 'wysiwyg-content': wysiwyg_content = WYSIWYGContent(request=request) diff --git a/dojo/templates/base.html b/dojo/templates/base.html index 2f1cace966..765ec10dc5 100644 --- a/dojo/templates/base.html +++ b/dojo/templates/base.html @@ -372,6 +372,7 @@ {% endif %} </ul> </li> + {% block reports_tab %} <li> <a href="{% url 'report_builder' %}" aria-expanded="false" aria-label="Reports"> <i class="fa-solid fa-file-lines fa-fw"></i> @@ -380,6 +381,7 @@ </a> <!-- /.nav-second-level --> </li> + {% endblock %} <li> <a href="{% url 'metrics' %}?date=5&view=dashboard" aria-expanded="false" aria-label="Metrics"> <i class="fa-solid fa-chart-column fa-fw"></i> From 3cf8ce7ebbd901a943801fdf5dacb313cc7ae57b Mon Sep 17 00:00:00 2001 From: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> Date: Mon, 6 May 2024 12:24:49 -0500 Subject: [PATCH 137/138] Fix conflict oops --- unittests/tools/test_redhatsatellite_parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/tools/test_redhatsatellite_parser.py b/unittests/tools/test_redhatsatellite_parser.py index 52fa9e408d..da1175a8df 100644 --- a/unittests/tools/test_redhatsatellite_parser.py +++ b/unittests/tools/test_redhatsatellite_parser.py @@ -19,7 +19,7 @@ def test_parse_file_with_one_finding(self): self.assertEqual(1, len(findings)) def test_parse_file_with_multiple_findingse(self): - with open("unittests/scans/redhatsatellite/many_findings.json") as testfile: + with open("unittests/scans/redhatsatellite/many_findings.json") as testfile: parser = RedHatSatelliteParser() findings = parser.get_findings(testfile, Test()) self.assertEqual(3, len(findings)) From ef99c6e80078596452086d74c7c3e28cd628ecb1 Mon Sep 17 00:00:00 2001 From: DefectDojo release bot <dojo-release-bot@users.noreply.github.com> Date: Mon, 6 May 2024 17:51:43 +0000 Subject: [PATCH 138/138] Update versions in application files --- components/package.json | 2 +- dojo/__init__.py | 2 +- helm/defectdojo/Chart.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/package.json b/components/package.json index 631abc21df..5135d814f7 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "defectdojo", - "version": "2.34.0-dev", + "version": "2.34.0", "license" : "BSD-3-Clause", "private": true, "dependencies": { diff --git a/dojo/__init__.py b/dojo/__init__.py index 4758913441..0ea36d94b7 100644 --- a/dojo/__init__.py +++ b/dojo/__init__.py @@ -4,6 +4,6 @@ # Django starts so that shared_task will use this app. from .celery import app as celery_app # noqa: F401 -__version__ = '2.34.0-dev' +__version__ = '2.34.0' __url__ = 'https://github.com/DefectDojo/django-DefectDojo' __docs__ = 'https://documentation.defectdojo.com' diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index 1e4e029d2c..0dc02c38db 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 -appVersion: "2.34.0-dev" +appVersion: "2.34.0" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.126-dev +version: 1.6.126 icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap