diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index 84d7800bed..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 @@ -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 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 }}" 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: 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 \ diff --git a/Dockerfile.nginx-alpine b/Dockerfile.nginx-alpine index 872fdaee78..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.4-alpine@sha256:31bad00311cb5eeb8a6648beadcf67277a175da89989f14727420a80e2e76742 +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 b11a68fd11..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.4-alpine@sha256:31bad00311cb5eeb8a6648beadcf67277a175da89989f14727420a80e2e76742 +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/components/package.json b/components/package.json index 8b076e0bbb..5135d814f7 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "defectdojo", - "version": "2.33.7", + "version": "2.34.0", "license" : "BSD-3-Clause", "private": true, "dependencies": { @@ -24,18 +24,18 @@ "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-ui": "1.13.3", "jquery.cookie": "1.4.1", "jquery.flot.tooltip": "^0.9.0", "jquery.hotkeys": "jeresig/jquery.hotkeys#master", "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.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..e346338a1b 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== @@ -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" @@ -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" @@ -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" @@ -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" diff --git a/docker-compose.yml b/docker-compose.yml index 7d52c5db0b..3dd8ac76ee 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 @@ -148,14 +148,14 @@ services: volumes: - defectdojo_postgres:/var/lib/postgresql/data rabbitmq: - image: rabbitmq:3.13.0-alpine@sha256:b4abd8d41c68839068e8309067dd12c34c532d3effd81601f5f2a1587f5118d4 + image: rabbitmq:3.13.2-alpine@sha256:9880c790e61a6ba7f2740b208f5584c08ce2fe668ef4852d30e554a1c07b6f63 profiles: - mysql-rabbitmq - postgres-rabbitmq 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 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 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..1a35861ed1 --- /dev/null +++ b/docs/content/en/getting_started/upgrading/2.34.md @@ -0,0 +1,12 @@ +--- +title: 'Upgrading to DefectDojo Version 2.34.x' +toc_hide: true +weight: -20240402 +description: Breaking Change for AWS_Scout2. +--- + +**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 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/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/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/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/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 >}} 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/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 +--- diff --git a/dojo/__init__.py b/dojo/__init__.py index 24987ce2ac..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.33.7' +__version__ = '2.34.0' __url__ = 'https://github.com/DefectDojo/django-DefectDojo' __docs__ = 'https://documentation.defectdojo.com' 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 54d55a76d0..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: @@ -47,11 +49,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..bf999ac635 100644 --- a/dojo/api_v2/permissions.py +++ b/dojo/api_v2/permissions.py @@ -1,49 +1,38 @@ 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.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, + +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.auto_create_context import AutoCreateContextManager 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): 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 - ) - ) + 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: @@ -428,46 +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 - raise serializers.ValidationError( - "Engagement '%s' doesn''t exist" % engagement_id - ) + 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: @@ -475,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", ) @@ -489,38 +471,32 @@ 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 - raise serializers.ValidationError( - "product '%s' doesn''t exist" % product_id - ) + msg = f"Product \"{product_id}\" does not exist" + raise serializers.ValidationError(msg) 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): @@ -635,50 +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 - raise serializers.ValidationError( - "Test '%s' doesn't exist" % test_id - ) + 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: @@ -686,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", ) @@ -952,45 +919,37 @@ 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( - "Product Type '%s' doesn't exist" % (product_type_name) - ) + msg = f"Product Type \"{product_type_name}\" does not exist" + raise serializers.ValidationError(msg) 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) - ) + msg = f"Product \"{product_name}\" does not 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}\" does not exist" + raise serializers.ValidationError(msg) if engagement_name and not engagement: - raise serializers.ValidationError( - "Engagement '%s' doesn't exist in Product '%s'" - % (engagement_name, 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: - raise serializers.ValidationError( - "Test '%s' with scan_type '%s' doesn't exist in Engagement '%s'" - % (test_title, scan_type, 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: - raise serializers.ValidationError( - "Test with scan_type '%s' doesn't exist in Engagement '%s'" - % (scan_type, 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) @@ -1021,10 +980,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 @@ -1034,37 +995,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}\" 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 ): - 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 @@ -1072,10 +1025,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/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 5d228165f5..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" @@ -20,7 +22,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 +39,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 +94,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 688c66b295..c8ab20cc33 100644 --- a/dojo/api_v2/serializers.py +++ b/dojo/api_v2/serializers.py @@ -1,184 +1,132 @@ +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 -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, + +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.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, + 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") -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(): - raise serializers.ValidationError("test must be an integer") - - 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(): - raise serializers.ValidationError("engagement must be an integer") - - 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: 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 @@ -245,7 +193,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 @@ -260,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__) @@ -289,10 +237,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 @@ -300,14 +246,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 +335,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 @@ -595,17 +541,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 +677,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 +689,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 +701,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 +734,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 +829,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 +841,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 +870,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 +882,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 +911,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 +923,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 +935,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 +964,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 +976,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 +1006,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 +1076,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 +1123,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 +1140,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 +1158,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 +1177,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 +1215,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 +1269,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 +1298,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 @@ -1464,10 +1401,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, } ) @@ -1535,22 +1469,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: @@ -1728,7 +1659,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( @@ -1772,34 +1703,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): @@ -1809,8 +1735,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() @@ -1870,7 +1799,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] @@ -1902,38 +1831,33 @@ 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: - 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 @@ -1967,7 +1891,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 +1908,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( @@ -2014,9 +1938,8 @@ class Meta: 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 @@ -2032,9 +1955,8 @@ class Meta: 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 @@ -2059,9 +1981,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: @@ -2098,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) @@ -2160,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, @@ -2171,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 @@ -2182,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", @@ -2193,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: + 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: - ( - 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, + 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: @@ -2329,19 +2217,25 @@ 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): - raise serializers.ValidationError( - "Uploading a Report File is required for {}".format(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( - "Report file is too large. Maximum supported size is {} MB".format( - settings.SCAN_FILE_MAX_SIZE - ) - ) + 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") @@ -2350,16 +2244,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): + def validate_scan_date(self, value: str) -> None: 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 @@ -2490,185 +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 + 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") ) - 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 - ) - 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 - raise NotFound("test not found") - - if test: + msg = "A test could not be found!" + raise NotFound(msg) + # 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 @@ -2680,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: @@ -2688,19 +2512,28 @@ 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") if not file and requires_file(scan_type): - raise serializers.ValidationError( - "Uploading a Report File is required for {}".format(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( - "Report file is too large. Maximum supported size is {} MB".format( - settings.SCAN_FILE_MAX_SIZE - ) - ) + 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") @@ -2709,16 +2542,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 @@ -2739,38 +2570,30 @@ class EndpointMetaImporterSerializer(serializers.Serializer): 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 - ) - ) + msg = f"Report file is too large. Maximum supported size is {settings.SCAN_FILE_MAX_SIZE} MB" + raise serializers.ValidationError(msg) return 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, @@ -2816,7 +2639,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() @@ -2845,11 +2669,8 @@ 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 - ) - ) + msg = f"File is too large. Maximum supported size is {settings.SCAN_FILE_MAX_SIZE} MB" + raise serializers.ValidationError(msg) return data @@ -2981,9 +2802,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 @@ -3084,14 +2904,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 @@ -3122,9 +2942,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 @@ -3268,6 +3087,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/api_v2/views.py b/dojo/api_v2/views.py index 2149a86a35..9b5239f011 100644 --- a/dojo/api_v2/views.py +++ b/dojo/api_v2/views.py @@ -1,170 +1,170 @@ -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.importers.reimporter.utils import ( - get_target_engagement_if_exists, - get_target_product_if_exists, - get_target_test_if_exists, +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.auto_create_context import AutoCreateContextManager +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__) @@ -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() @@ -1214,9 +1218,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, ) @@ -2598,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): @@ -2777,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) @@ -2877,7 +2845,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")), ) @@ -2947,7 +2915,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/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 69f3884a4c..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): @@ -202,9 +203,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 +258,8 @@ 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) - ) + 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 +273,8 @@ 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)) + msg = f"Role {role} does not exist" + raise RoleDoesNotExistError(msg) roles = get_roles_with_permissions() permissions = roles.get(role) if not permissions: @@ -286,7 +286,8 @@ 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)) + 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/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 f2d73f0386..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__) @@ -20,7 +21,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..b7abd6c9ef 100644 --- a/dojo/components/sql_group_concat.py +++ b/dojo/components/sql_group_concat.py @@ -9,11 +9,11 @@ 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 "", - 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/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 d6d4c167b1..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__) @@ -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/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 f52a46311c..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__) @@ -92,7 +90,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 +118,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 +133,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 +160,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 +169,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 +180,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 +195,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 +221,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 +238,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 +281,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 @@ -322,7 +320,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/endpoint/views.py b/dojo/endpoint/views.py index bd1a85534e..acb956bba1 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__) @@ -215,9 +223,9 @@ 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='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,))) @@ -279,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', @@ -373,12 +381,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: @@ -393,7 +401,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, @@ -405,8 +413,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, @@ -489,7 +496,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'] @@ -500,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/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/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 bdf4c2cb14..5ac3340fcc 100644 --- a/dojo/engagement/views.py +++ b/dojo/engagement/views.py @@ -1,70 +1,110 @@ -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, Tuple -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, + ProductEngagementsFilter, + ProductEngagementsFilterWithoutObjectLookups, ) -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.default_importer import DefaultImporter +from dojo.models import ( + Check_List, + Cred_Mapping, + Development_Environment, + Dojo_User, + 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, + redirect_to_return_url_or_else, +) logger = logging.getLogger(__name__) @@ -104,7 +144,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') @@ -176,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( @@ -191,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, @@ -199,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() @@ -237,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 @@ -319,9 +362,9 @@ 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='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") @@ -362,8 +405,8 @@ def copy_engagement(request, eid): 'Engagement Copied successfully.', 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), + 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, ))), recipients=[engagement.lead], @@ -525,7 +568,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.', @@ -663,203 +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: - raise Exception('Either Engagement or Product has to be provided') - + 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: - raise Exception('Either Engagement or Product has to be provided') - - 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, - "Report file is too large. Maximum supported size is {} MB".format(settings.SCAN_FILE_MAX_SIZE), - 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('An exception error occurred during the report import:%s' % 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') @@ -872,8 +1139,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, ))) @@ -888,9 +1155,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, ))) @@ -1006,7 +1273,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') @@ -1056,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() @@ -1142,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') @@ -1246,8 +1512,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 @@ -1306,18 +1571,21 @@ 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, - "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, - request.build_absolute_uri( - (reverse("view_engagement", args=(eng.id, ))))), uid) + start_date, + end_date, + f"Engagement: {eng.name} ({eng.product.name})", + ( + 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' - response['Content-Disposition'] = 'attachment; filename=%s.ics' % eng.name + response['Content-Disposition'] = f'attachment; filename={eng.name}.ics' return response @@ -1332,7 +1600,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:] @@ -1340,7 +1609,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/filters.py b/dojo/filters.py index 8dc6137910..08b84de46a 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__) @@ -56,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})) @@ -131,7 +176,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 +224,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 +259,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: @@ -236,7 +281,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) @@ -246,7 +291,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']: @@ -277,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)' @@ -557,39 +602,39 @@ 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)), })), } 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: @@ -603,55 +648,55 @@ 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)), })), } 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: @@ -665,17 +710,17 @@ 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 })), } 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: @@ -710,7 +755,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: @@ -736,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): @@ -745,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): @@ -785,7 +830,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: @@ -858,7 +903,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[ @@ -874,6 +919,8 @@ class EngagementDirectFilterHelper(FilterSet): tag = CharFilter(field_name="tags__name", lookup_expr="icontains", label="Tag name contains") not_tag = CharFilter(field_name="tags__name", lookup_expr="icontains", label="Not tag name contains", exclude=True) has_tags = BooleanFilter(field_name="tags", lookup_expr="isnull", exclude=True, label="Has tags") + target_start = DateRangeFilter() + target_end = DateRangeFilter() test__engagement__product__lifecycle = MultipleChoiceFilter( choices=Product.LIFECYCLE_CHOICES, label="Product lifecycle", @@ -913,7 +960,7 @@ class EngagementDirectFilter(EngagementDirectFilterHelper, DojoFilter): queryset=Engagement.tags.tag_model.objects.all().order_by("name")) 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() @@ -996,9 +1043,9 @@ class EngagementFilter(EngagementFilterHelper, DojoFilter): queryset=Engagement.tags.tag_model.objects.all().order_by("name")) def __init__(self, *args, **kwargs): - super(EngagementFilter, self).__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) \ + 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() class Meta: @@ -1006,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", @@ -1075,7 +1148,7 @@ class ProductEngagementFilter(ProductEngagementFilterHelper, DojoFilter): queryset=Engagement.tags.tag_model.objects.all().order_by("name")) 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() @@ -1162,6 +1235,7 @@ class ProductFilterHelper(FilterSet): ('origin', 'origin'), ('external_audience', 'external_audience'), ('internet_accessible', 'internet_accessible'), + ('findings_count', 'findings_count') ), field_labels={ 'name': 'Product Name', @@ -1173,6 +1247,7 @@ class ProductFilterHelper(FilterSet): 'origin': 'Origin ', 'external_audience': 'External Audience ', 'internet_accessible': 'Internet Accessible ', + 'findings_count': 'Findings Count ', } ) @@ -1195,7 +1270,7 @@ def __init__(self, *args, **kwargs): self.user = None 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) class Meta: @@ -1221,7 +1296,7 @@ class ProductFilterWithoutObjectLookups(ProductFilterHelper): def __init__(self, *args, **kwargs): kwargs.pop("user", None) - super(ProductFilterWithoutObjectLookups, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) class Meta: model = Product @@ -1955,7 +2030,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) @@ -2381,12 +2456,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: @@ -2522,11 +2597,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: @@ -2685,7 +2760,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') @@ -2806,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() @@ -2826,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'] @@ -2877,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): @@ -2971,7 +3049,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: @@ -3090,7 +3168,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..3be69d7355 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") @@ -146,7 +156,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()) @@ -236,18 +247,19 @@ 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: - 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/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 9faef2cffc..44dcce6bea 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" @@ -1294,10 +1290,9 @@ def close_finding(request, fid): ) create_notification( event="other", - title="Closing of %s" % finding.title, + title=f"Closing of {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( @@ -1458,10 +1453,9 @@ def reopen_finding(request, fid): ) create_notification( event="other", - title="Reopening of %s" % finding.title, + title=f"Reopening of {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,))) @@ -1517,9 +1511,8 @@ 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), + 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( reverse("copy_finding", args=(finding_copy.id,)) @@ -1836,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", ) @@ -2291,8 +2283,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" @@ -2535,9 +2526,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 @@ -2545,23 +2534,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"]: @@ -2583,9 +2566,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 ) @@ -2598,9 +2579,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 @@ -2609,9 +2588,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 @@ -2641,9 +2618,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) @@ -2712,7 +2687,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: @@ -2733,18 +2708,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: @@ -2765,9 +2736,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) @@ -2879,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,) @@ -2887,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 @@ -2904,8 +2872,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,) @@ -2913,9 +2880,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 @@ -2931,8 +2897,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( [ @@ -2945,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 @@ -2975,9 +2939,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 @@ -3026,8 +2989,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 @@ -3121,9 +3084,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/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 2a5df5a775..9173745695 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__) @@ -121,9 +123,9 @@ 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='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/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/forms.py b/dojo/forms.py old mode 100755 new mode 100644 index 1d24ed429a..0bf5429f71 --- a/dojo/forms.py +++ b/dojo/forms.py @@ -1,58 +1,114 @@ +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, + is_scan_file_too_large, +) +from dojo.widgets import TableCheckboxWidget logger = logging.getLogger(__name__) @@ -75,7 +131,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) @@ -121,7 +177,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): @@ -144,7 +200,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) @@ -154,7 +210,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 +235,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 +249,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 +265,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 +278,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 +319,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 +350,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 +381,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 +395,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 +411,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 +424,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 +441,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 +465,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,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): - super(ImportScanForm, self).__init__(*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 @@ -514,13 +578,18 @@ def clean(self): cleaned_data = super().clean() 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)) 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}") + 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) 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 +603,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): @@ -596,14 +666,22 @@ 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) + 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] self.scan_type = None 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 @@ -614,12 +692,17 @@ 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) + 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: 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 +710,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 @@ -653,7 +737,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 +780,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.") @@ -727,7 +811,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 @@ -817,7 +901,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 +952,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 +976,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 +1027,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 +1060,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 +1108,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,16 +1120,16 @@ 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') + 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: @@ -1105,7 +1189,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,13 +1201,13 @@ 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') + 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: @@ -1173,7 +1257,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 +1265,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 +1333,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,17 +1379,17 @@ 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' - ' 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: @@ -1316,7 +1400,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,12 +1426,14 @@ 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.") + 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 @@ -1370,20 +1456,22 @@ 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: - 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 @@ -1409,7 +1497,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,20 +1540,20 @@ 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' - ' 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: @@ -1482,7 +1570,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 +1580,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'] @@ -1513,9 +1601,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 @@ -1536,7 +1623,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 +1649,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'] @@ -1572,8 +1659,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: @@ -1606,10 +1693,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 +1726,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 +1741,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 +1763,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 +1829,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) @@ -1765,7 +1852,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: @@ -1776,7 +1864,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 +1930,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 +1959,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 +1976,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 +1989,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 +2001,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 +2009,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 +2025,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 +2039,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 +2050,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 +2058,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 +2074,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 +2088,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 +2099,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 +2133,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): @@ -2056,11 +2144,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 @@ -2214,7 +2305,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 +2420,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 +2471,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', @@ -2428,7 +2519,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 @@ -2453,7 +2545,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 @@ -2480,16 +2572,15 @@ 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 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: @@ -2554,9 +2645,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 @@ -2574,7 +2664,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 @@ -2583,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: @@ -2625,7 +2724,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 +2766,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'] = '' @@ -2733,9 +2832,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 @@ -2829,15 +2928,17 @@ 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): 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." @@ -2855,9 +2956,10 @@ 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(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 +2994,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 +3070,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 +3089,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 +3128,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 @@ -3066,15 +3168,16 @@ 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(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 @@ -3097,13 +3200,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( @@ -3119,7 +3224,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()] @@ -3173,13 +3278,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 +3349,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 @@ -3326,7 +3436,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 +3458,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 +3515,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 +3534,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 +3543,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() @@ -3462,7 +3572,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 +3581,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/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 be7f5ea1d6..09ea0e7939 100644 --- a/dojo/group/utils.py +++ b/dojo/group/utils.py @@ -1,14 +1,16 @@ 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): 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/group/views.py b/dojo/group/views.py index 8cdf17b31c..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__) @@ -419,7 +435,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 +477,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/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/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 337df8d047..0000000000 --- a/dojo/importers/importer/importer.py +++ /dev/null @@ -1,409 +0,0 @@ -import base64 - -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.core import serializers -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.tools.factory import get_parser -import logging - - -logger = logging.getLogger(__name__) -deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication") - - -class DojoDefaultImporter(object): - - 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]): - 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: - raise ValidationError('API Scan Configuration has to be from same product as the Engagement') - - # 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 1515b6ba41..0000000000 --- a/dojo/importers/reimporter/reimporter.py +++ /dev/null @@ -1,785 +0,0 @@ -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.files.base import ContentFile -from django.utils import timezone -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") - - -class DojoDefaultReImporter(object): - @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: " - "{}".format(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="Finding has skipped reactivation from %s re-upload with user decision do_not_reactivate." - % scan_type, - 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, - 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="Re-activated by %s re-upload." % scan_type, 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( - [ - 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="Mitigated by %s re-upload." % test.test_type, 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( - [ - 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: - raise ValidationError( - "API Scan Configuration has to be from same product as the Test" - ) - 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 5347fbf67f..0000000000 --- a/dojo/importers/reimporter/utils.py +++ /dev/null @@ -1,259 +0,0 @@ -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.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: - raise ValueError('auto_create_context not True, unable to create non-existing product') - 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: - raise ValueError('auto_create_context not True, unable to create non-existing engagement') - 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') - - 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 0b98caf551..0000000000 --- a/dojo/importers/utils.py +++ /dev/null @@ -1,201 +0,0 @@ -from django.core.exceptions import ValidationError -from django.core.exceptions import MultipleObjectsReturned -from django.conf import settings -from django.utils.timezone import make_aware -from dojo.decorators import dojo_async_task -from dojo.celery import app -from dojo.endpoint.utils import endpoint_get_or_create -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__) - - -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: " - "{}".format(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): - raise Exception("Endpoints in your database are broken. Please access {} and migrate them to new format or " - "remove them.".format(reverse('endpoint_migrate'))) - - _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/jira_link/helper.py b/dojo/jira_link/helper.py index 090c75c897..49525785af 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__) @@ -87,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 @@ -121,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 @@ -427,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 @@ -604,7 +625,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 @@ -722,7 +744,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 +906,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 +1007,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 @@ -1082,12 +1104,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 +1127,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 +1139,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}" @@ -1203,7 +1229,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 +1375,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)) @@ -1468,7 +1494,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 +1508,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: @@ -1580,7 +1608,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 +1622,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 +1633,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 +1645,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/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..64abdf50ea 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__) @@ -538,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 a977d29c22..5ae54ae6bb 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 """ @@ -28,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/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 ab7432fdec..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 @@ -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/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 b92ff7921f..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__) @@ -21,7 +22,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 @@ -33,7 +35,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 +44,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..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')) @@ -28,7 +29,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 +38,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/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 865fa3a0e7..f0348f348e 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__) @@ -405,7 +413,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 +436,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 +1023,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] @@ -1052,7 +1060,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]) @@ -1085,7 +1093,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]) @@ -1143,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, @@ -1175,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/middleware.py b/dojo/middleware.py index 733c66f4cd..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('/'))] @@ -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 old mode 100755 new mode 100644 index 74b8da2688..6e7c136578 --- 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") @@ -142,7 +141,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 +218,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() @@ -268,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( @@ -704,12 +701,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() @@ -723,11 +720,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): @@ -748,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( @@ -786,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) @@ -820,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}] @@ -851,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. """ @@ -866,17 +867,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') - - def __str__(self): - return "%s: %s" % (self.name, self.value) - - class Meta: - unique_together = (('product', 'name'), - ('endpoint', 'name'), - ('finding', 'name')) + msg = 'Metadata entries may not have more than one relation, either a product, an endpoint either or a finding' + raise ValidationError(msg) class SLA_Configuration(models.Model): @@ -894,12 +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: - raise ValidationError('SLA Days must be at least 1') + 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) @@ -913,7 +907,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: @@ -931,7 +925,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: @@ -941,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) @@ -953,7 +949,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}' @@ -1065,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 @@ -1074,7 +1077,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: @@ -1084,7 +1087,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: @@ -1094,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): @@ -1215,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, @@ -1441,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 @@ -1489,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), @@ -1508,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" @@ -1555,18 +1552,17 @@ 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 "'{}' on '{}'".format(str(self.finding), str(self.endpoint)) + return f"'{str(self.finding)}' on '{str(self.endpoint)}'" def copy(self, finding=None): copy = self @@ -1580,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): @@ -1625,19 +1622,75 @@ 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"] 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 @@ -1646,7 +1699,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')) @@ -1654,102 +1707,52 @@ 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 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...' 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))) + 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 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...' 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))) + 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 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...' 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))) - if self.fragment == '': - self.fragment = None - - 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(u"=", 1) - if u"=" in qe - else (qe, None) - ) - for qe in self.query.split(u"&") - ) 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: - raise ValueError('hyperlink lib did not create URL as was expected') - return clean_url - else: - raise ValueError('Missing host') - except: - url = '' - if self.protocol: - url += '{}://'.format(self.protocol) - if self.userinfo: - url += '{}@'.format(self.userinfo) - if self.host: - url += self.host - if self.port: - url += ':{}'.format(self.port) - if self.path: - url += '{}{}'.format('/' if self.path[0] != '/' else '', self.path) - if self.query: - url += '?{}'.format(self.query) - if self.fragment: - url += '#{}'.format(self.fragment) - return url + 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 + + if errors: + raise ValidationError(errors) def __hash__(self): return self.__str__().__hash__() @@ -1919,7 +1922,8 @@ 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)) + 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: @@ -1927,7 +1931,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 @@ -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 "%s (%s)" % (self.title, self.test_type) + 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,8 +2574,89 @@ 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(Finding, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.unsaved_endpoints = [] self.unsaved_request = None @@ -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 @@ -2704,24 +2781,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 @@ -2734,17 +2803,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 @@ -2753,11 +2816,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( @@ -2835,9 +2894,6 @@ def get_severity(num_severity): return None - def __str__(self): - return self.title - def status(self): status = [] if self.under_review: @@ -3005,79 +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]) - - # 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(Finding, self).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"] @@ -3089,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 @@ -3101,7 +3084,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 @@ -3176,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 @@ -3244,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 @@ -3267,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: @@ -3280,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) @@ -3290,6 +3258,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 @@ -3309,7 +3278,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) @@ -3403,7 +3372,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 @@ -3419,7 +3388,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): @@ -3441,20 +3410,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 @@ -3495,20 +3464,20 @@ 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 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) @@ -3725,7 +3694,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 = ( @@ -3840,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(',')] @@ -3848,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 @@ -3921,13 +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 clean(self): - if not self.jira_instance: - raise ValidationError('Cannot save JIRA Project Configuration without JIRA Instance') - 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) + # declare form here as we can't import forms.py due to circular imports not even locally class JIRAForm_Admin(forms.ModelForm): @@ -3972,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 @@ -3980,15 +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)) - - 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) + msg = f'unknown object type while creating JIRA_Issue: {to_str_typed(obj)}' + raise TypeError(msg) NOTIFICATION_CHOICE_SLACK = ("slack", "slack") @@ -4044,6 +4015,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: @@ -4075,9 +4049,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') @@ -4190,12 +4161,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) @@ -4337,12 +4308,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) @@ -4366,12 +4337,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/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 d4a95109d9..4f4d16b8a1 100644 --- a/dojo/notifications/helper.py +++ b/dojo/notifications/helper.py @@ -1,8 +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 @@ -11,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__) @@ -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) @@ -87,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) @@ -120,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"] @@ -221,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) @@ -229,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') @@ -322,13 +328,13 @@ 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): - from dojo.utils import get_system_setting import json + from dojo.utils import get_system_setting + user_id = None res = requests.request( @@ -349,10 +355,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.") @@ -369,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 @@ -386,10 +392,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/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 ec2b1f7b45..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__) @@ -58,7 +60,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 +90,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/okta.py b/dojo/okta.py index 27ea21084d..47fa718de6 100644 --- a/dojo/okta.py +++ b/dojo/okta.py @@ -4,15 +4,15 @@ 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(object): +class OktaMixin: def api_url(self): return append_slash(self.setting('API_URL')) @@ -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/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..f2e05a613f 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 @@ -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/product/views.py b/dojo/product/views.py old mode 100755 new mode 100644 index 0724f7d4f3..024b5c5d02 --- 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__) @@ -78,10 +134,12 @@ def product(request): # otherwise the paginator will perform all the annotations/prefetching already only to count the total number of records # 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)) + ) filter_string_matching = get_system_setting("filter_string_matching", False) filter_class = ProductFilterWithoutObjectLookups if filter_string_matching else ProductFilter prod_filter = filter_class(request.GET, queryset=prods, user=request.user) - prod_list = get_page_items(request, prod_filter.qs, 25) # perform annotation/prefetching by replacing the queryset in the page with an annotated/prefetched queryset. @@ -291,7 +349,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' @@ -305,7 +364,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( @@ -374,7 +433,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( @@ -472,7 +531,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/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 84bb14c108..bb41a1cd63 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__) @@ -137,9 +148,9 @@ 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='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/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..ed48ce3190 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__) @@ -98,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/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 b6c3024bb0..cb7a599f11 100644 --- a/dojo/reports/views.py +++ b/dojo/reports/views.py @@ -1,35 +1,48 @@ +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 typing import List from dateutil.relativedelta import relativedelta from django.conf import settings -from django.http import Http404, HttpResponse, QueryDict -from django.shortcuts import render, get_object_or_404 -from django.utils import timezone from django.core.exceptions import PermissionDenied +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 +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, + Widget, + 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__) @@ -53,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): @@ -362,9 +394,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)) @@ -436,7 +470,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 +501,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() @@ -684,7 +718,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 fea5369667..8eef453bb8 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 @@ -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 @@ -57,7 +58,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 +110,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 +131,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 +152,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 +173,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 +198,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 +221,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' @@ -246,16 +247,12 @@ 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') 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') @@ -267,7 +264,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'): @@ -288,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): @@ -299,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): @@ -321,16 +314,12 @@ 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') 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') @@ -342,7 +331,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 @@ -360,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): @@ -385,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): @@ -410,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 @@ -426,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/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 8034ce713c..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__) @@ -208,8 +210,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/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..9867dfc62f 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__) @@ -423,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 @@ -490,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) @@ -504,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 a3c805ba39..48891b3662 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__) @@ -180,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. @@ -200,6 +204,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" @@ -217,7 +223,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 @@ -233,7 +239,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 @@ -285,6 +290,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"]), ) @@ -490,10 +497,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 = ( @@ -600,22 +604,23 @@ 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 = ( - 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 = [ @@ -895,9 +900,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: @@ -907,7 +913,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' @@ -919,7 +925,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') @@ -928,7 +934,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'), @@ -952,16 +958,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), ], }, @@ -1042,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'): @@ -1153,7 +1160,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/',) # ------------------------------------ @@ -1258,10 +1265,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 @@ -1474,10 +1481,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') @@ -1560,46 +1567,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, }, } @@ -1684,6 +1691,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") @@ -1703,6 +1711,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/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 02fc9f74d5..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') @@ -484,8 +510,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 +602,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/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 50d48049a8..8f4941bbe9 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") @@ -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,8 +42,8 @@ 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, - description='The engagement "%s" is stale. Target end was %s.' % (eng.name, eng.target_end.strftime("%b. %d, %Y")), + 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]) @@ -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/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 %} + {% block reports_tab %}
  • + {% endblock %}
  • {_(display)} {icon}' + # QueryDict.urlencode() used here to properly handle cases when keys have multiple values + link = f'{_(display)} {icon}' 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/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/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 c894be5064..7eee27829e 100644 --- a/dojo/test/views.py +++ b/dojo/test/views.py @@ -1,49 +1,83 @@ # # 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 django.conf import settings +from functools import reduce +from typing import Tuple + 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.default_reimporter import DefaultReImporter +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, + process_notifications, + redirect_to_return_url_or_else, +) logger = logging.getLogger(__name__) parse_logger = logging.getLogger('dojo') @@ -301,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") @@ -347,8 +381,8 @@ def copy_test(request, tid): 'Test Copied successfully.', 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), + 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,))), recipients=[test.engagement.lead], @@ -404,23 +438,21 @@ 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' - response['Content-Disposition'] = 'attachment; filename=%s.ics' % test.test_type.name + response['Content-Disposition'] = f'attachment; filename={test.test_type.name}.ics' return response @@ -595,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 @@ -658,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() @@ -703,7 +733,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, @@ -743,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', @@ -782,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('An exception error occurred during the report import:%s' % 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/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 old mode 100755 new mode 100644 index 180164b00b..8a1bb203f4 --- 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 fd3c475750..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__) @@ -61,7 +62,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 +90,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/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 f9fff0b109..93285a1fb5 100644 --- a/dojo/tools/acunetix/parse_acunetix360_json.py +++ b/dojo/tools/acunetix/parse_acunetix360_json.py @@ -1,16 +1,18 @@ 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 -class AcunetixJSONParser(object): +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 12ca4100a0..ae6ca8d5ee 100644 --- a/dojo/tools/acunetix/parse_acunetix_xml.py +++ b/dojo/tools/acunetix/parse_acunetix_xml.py @@ -1,18 +1,21 @@ 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__) -class AcunetixXMLParser(object): +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") @@ -54,7 +57,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"): @@ -81,7 +84,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 @@ -128,9 +131,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..aeb2aab875 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"] @@ -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 899e600a51..03e7cc1ee8 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(): @@ -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, @@ -85,11 +83,8 @@ def get_findings(self, filename, test): ] items.append(find) except (KeyError, IndexError) as err: - raise ValueError( - "Invalid format: {} key not found".format( - err - ) - ) + 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/anchore_grype/parser.py b/dojo/tools/anchore_grype/parser.py index cf3653ced2..395955b1eb 100644 --- a/dojo/tools/anchore_grype/parser.py +++ b/dojo/tools/anchore_grype/parser.py @@ -1,11 +1,12 @@ import json + from cvss import parser as cvss_parser from cvss.cvss3 import CVSS3 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` @@ -25,7 +26,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 +204,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 1df2fa94f9..1e31b08e68 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: @@ -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, @@ -68,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( - "Invalid format: {} key not found".format(err) - ) + 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_vulns/parser.py b/dojo/tools/anchorectl_vulns/parser.py index 77c350b56b..70371a955b 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"] @@ -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_blackduck/api_client.py b/dojo/tools/api_blackduck/api_client.py index fb8058bc8b..6d5342d580 100644 --- a/dojo/tools/api_blackduck/api_client.py +++ b/dojo/tools/api_blackduck/api_client.py @@ -16,11 +16,8 @@ def __init__(self, tool_config): timeout=120, ) else: - raise ValueError( - "Authentication type {} not supported".format( - tool_config.authentication_type - ) - ) + 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 cf7a143bb9..c2606cd0af 100644 --- a/dojo/tools/api_blackduck/importer.py +++ b/dojo/tools/api_blackduck/importer.py @@ -1,10 +1,11 @@ from django.core.exceptions import ValidationError + from dojo.models import Product_API_Scan_Configuration from .api_client import BlackduckAPI -class BlackduckApiImporter(object): +class BlackduckApiImporter: """ Import from BlackDuck API """ @@ -23,10 +24,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 +37,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_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..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: """ @@ -19,15 +20,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 - ) - ) + msg = f"bugcrowd Authentication type {tool_config.authentication_type} not supported" + raise Exception(msg) 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: @@ -95,11 +91,11 @@ 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( - url="{}/targets".format(self.bugcrowd_api_url) + url=f"{self.bugcrowd_api_url}/targets" ) response_targets.raise_for_status() if response_targets.ok: @@ -108,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}" ' @@ -117,19 +113,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 " - "filtering, check your configuration, HTTP response was: {}".format( - response_targets.text - ) + 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 " - "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}" ) + 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 3e41b6be20..677174cac0 100644 --- a/dojo/tools/api_bugcrowd/importer.py +++ b/dojo/tools/api_bugcrowd/importer.py @@ -1,12 +1,15 @@ 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__) -class BugcrowdApiImporter(object): +class BugcrowdApiImporter: """ Import from Bugcrowd API """ @@ -14,9 +17,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 +30,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 @@ -39,10 +40,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, @@ -51,17 +53,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 17cc04f84d..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" @@ -16,7 +18,7 @@ logger = logging.getLogger(__name__) -class ApiBugcrowdParser(object): +class ApiBugcrowdParser: """ Import from Bugcrowd API /submissions """ @@ -158,15 +160,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) @@ -202,11 +200,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 f51cef1dbe..36f37d734d 100644 --- a/dojo/tools/api_cobalt/api_client.py +++ b/dojo/tools/api_cobalt/api_client.py @@ -14,11 +14,8 @@ def __init__(self, tool_config): self.api_token = tool_config.api_key self.org_token = tool_config.extras else: - raise Exception( - "Cobalt.io Authentication type {} not supported".format( - tool_config.authentication_type - ) - ) + msg = f"Cobalt.io Authentication type {tool_config.authentication_type} not supported" + raise Exception(msg) def get_asset(self, asset_id): """ @@ -32,23 +29,25 @@ def get_asset(self, asset_id): if asset["resource"]["id"] == asset_id: return asset - raise Exception("Asset {} not found in organisation".format(asset_id)) + msg = f"Asset {asset_id} not found in organisation" + raise Exception(msg) 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(), ) 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): """ @@ -57,31 +56,30 @@ 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(), ) 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 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(), ) @@ -94,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) @@ -111,7 +110,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..068745cfee 100644 --- a/dojo/tools/api_cobalt/importer.py +++ b/dojo/tools/api_cobalt/importer.py @@ -1,12 +1,15 @@ 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__) -class CobaltApiImporter(object): +class CobaltApiImporter: """ Import from Cobalt.io API """ @@ -22,10 +25,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 +38,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_cobalt/parser.py b/dojo/tools/api_cobalt/parser.py index 0e77b0d279..df0425d92b 100644 --- a/dojo/tools/api_cobalt/parser.py +++ b/dojo/tools/api_cobalt/parser.py @@ -1,14 +1,15 @@ 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" -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..e74c6b9409 100644 --- a/dojo/tools/api_edgescan/api_client.py +++ b/dojo/tools/api_edgescan/api_client.py @@ -1,9 +1,10 @@ -import requests import json from json.decoder import JSONDecodeError +import requests + -class EdgescanAPI(object): +class EdgescanAPI: """ A simple client for the Edgescan API """ @@ -16,11 +17,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( - "Edgescan Authentication type {} not supported".format( - tool_config.authentication_type - ) - ) + msg = f"Edgescan Authentication type {tool_config.authentication_type} not supported" + raise Exception(msg) @staticmethod def get_extra_options(tool_config): @@ -28,7 +26,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 dc97edf82a..e740051afa 100644 --- a/dojo/tools/api_edgescan/importer.py +++ b/dojo/tools/api_edgescan/importer.py @@ -1,9 +1,11 @@ from django.core.exceptions import ValidationError + from dojo.models import Product_API_Scan_Configuration + from .api_client import EdgescanAPI -class EdgescanImporter(object): +class EdgescanImporter: """ Import from Edgescan API """ @@ -18,10 +20,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 +32,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_edgescan/parser.py b/dojo/tools/api_edgescan/parser.py index 3e186e6d6b..b9becbfc5d 100644 --- a/dojo/tools/api_edgescan/parser.py +++ b/dojo/tools/api_edgescan/parser.py @@ -1,14 +1,16 @@ 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"} SCANTYPE_EDGESCAN = "Edgescan Scan" -class ApiEdgescanParser(object): +class ApiEdgescanParser: """ Import from Edgescan API or JSON file """ 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 31a5c62e77..11406eb5a5 100644 --- a/dojo/tools/api_sonarqube/importer.py +++ b/dojo/tools/api_sonarqube/importer.py @@ -1,20 +1,21 @@ 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__) -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. @@ -61,10 +62,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 +79,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_sonarqube/parser.py b/dojo/tools/api_sonarqube/parser.py index f4e7162d31..972d8efc7d 100644 --- a/dojo/tools/api_sonarqube/parser.py +++ b/dojo/tools/api_sonarqube/parser.py @@ -1,10 +1,9 @@ from .importer import SonarQubeApiImporter - 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..67c724660d 100644 --- a/dojo/tools/api_sonarqube/updater.py +++ b/dojo/tools/api_sonarqube/updater.py @@ -2,12 +2,13 @@ from collections import deque from dojo.models import Sonarqube_Issue_Transition + from .importer import SonarQubeApiImporter 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 +120,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 +141,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 +149,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..1c97f8fe40 100644 --- a/dojo/tools/api_sonarqube/updater_from_source.py +++ b/dojo/tools/api_sonarqube/updater_from_source.py @@ -2,14 +2,15 @@ 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__) -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 +41,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 +49,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..0213e55e61 100644 --- a/dojo/tools/api_vulners/api_client.py +++ b/dojo/tools/api_vulners/api_client.py @@ -15,11 +15,8 @@ def __init__(self, tool_config): if tool_config.url: self.vulners_api_url = tool_config.url else: - raise Exception( - "Vulners.com Authentication type {} not supported".format( - tool_config.authentication_type - ) - ) + 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 fef0d40c66..89950ae97d 100644 --- a/dojo/tools/api_vulners/importer.py +++ b/dojo/tools/api_vulners/importer.py @@ -1,12 +1,15 @@ 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__) -class VulnersImporter(object): +class VulnersImporter: """ Import from Vulners API """ @@ -27,10 +30,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 +42,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/api_vulners/parser.py b/dojo/tools/api_vulners/parser.py index deba3c5762..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__) @@ -17,7 +19,7 @@ } -class ApiVulnersParser(object): +class ApiVulnersParser: """Parser that can load data from Vulners Scanner API""" def get_scan_types(self): @@ -42,9 +44,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 +55,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 4d3e5eccc7..bf9ed6eb41 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): @@ -24,12 +24,13 @@ 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 = dict() + dupes = {} for finding in root.iter("Vuln"): severity = self.convert_severity(finding.find("AttackScore").text) @@ -41,8 +42,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/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 old mode 100755 new mode 100644 index 22e67fe1b8..7ca6528de0 --- 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: @@ -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 c5831d025b..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 = { @@ -13,7 +15,7 @@ } -class AsffParser(object): +class AsffParser: def get_scan_types(self): return ["AWS Security Finding Format (ASFF) Scan"] @@ -26,7 +28,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") @@ -56,7 +58,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 +70,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/dojo/tools/auditjs/parser.py b/dojo/tools/auditjs/parser.py index 69031dc16b..678e11e8e6 100644 --- a/dojo/tools/auditjs/parser.py +++ b/dojo/tools/auditjs/parser.py @@ -1,12 +1,14 @@ 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(object): +class AuditJSParser: """Parser for AuditJS Scan tool""" def get_scan_types(self): @@ -36,10 +38,9 @@ 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 ?" - ) - dupes = dict() + msg = "Invalid JSON format. Are you sure you used --json option ?" + raise ValueError(msg) + dupes = {} for dependency in data: # reading package name in format pkg:npm/PACKAGE_NAME@PACKAGE_VERSION @@ -84,10 +85,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 b732003930..4a1ed7af91 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"] @@ -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() @@ -34,7 +35,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 +131,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 c36c87ad9b..60f7a5dc7e 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): @@ -23,10 +23,11 @@ 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 = dict() + dupes = {} data = json.load(file) for deserialized in data: 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 55b6d31afa..0000000000 --- a/dojo/tools/aws_scout2/parser.py +++ /dev/null @@ -1,197 +0,0 @@ -import json -import textwrap -from datetime import datetime - -from dojo.models import Finding -from html2text import html2text - - -class AWSScout2Parser(object): - # 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 = "%s **AWS Account:** %s\n" % ( - test_description, - aws_account_id, - ) - last_run = data["last_run"] - test_description = "%s **Ruleset:** %s\n" % ( - test_description, - last_run["ruleset_name"], - ) - test_description = "%s **Ruleset Description:** %s\n" % ( - test_description, - last_run["ruleset_about"], - ) - test_description = "%s **Command:** %s\n" % ( - 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 = "%s\n**%s** \n" % ( - test_description, - service.upper(), - ) - test_description = "%s\n* **Checked Items:** %s\n" % ( - test_description, - items["checked_items"], - ) - test_description = "%s* **Flagged Items:** %s\n" % ( - test_description, - items["flagged_items"], - ) - test_description = "%s* **Max Level:** %s\n" % ( - test_description, - items["max_level"], - ) - test_description = "%s* **Resource Count:** %s\n" % ( - test_description, - items["resources_count"], - ) - test_description = "%s* **Rules Count:** %s\n\n" % ( - 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) - + "**%s:** %s\n\n" % (key.title(), src) - ) - 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/dojo/tools/awssecurityhub/compliance.py b/dojo/tools/awssecurityhub/compliance.py index 3898442d69..8f12016ff8 100644 --- a/dojo/tools/awssecurityhub/compliance.py +++ b/dojo/tools/awssecurityhub/compliance.py @@ -1,19 +1,31 @@ from datetime import datetime + 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", "") 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..19987d0ddf 100644 --- a/dojo/tools/awssecurityhub/guardduty.py +++ b/dojo/tools/awssecurityhub/guardduty.py @@ -1,8 +1,9 @@ from datetime import datetime -from dojo.models import Finding, Endpoint +from dojo.models import Endpoint, Finding -class GuardDuty(object): + +class GuardDuty: def get_item(self, finding: dict, test): finding_id = finding.get("Id", "") title = finding.get("Title", "") @@ -15,7 +16,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 +30,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 +78,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..67c8f0e1cd 100644 --- a/dojo/tools/awssecurityhub/inspector.py +++ b/dojo/tools/awssecurityhub/inspector.py @@ -1,8 +1,9 @@ from datetime import datetime -from dojo.models import Finding, Endpoint +from dojo.models import Endpoint, Finding -class Inspector(object): + +class Inspector: def get_item(self, finding: dict, test): finding_id = finding.get("Id", "") title = finding.get("Title", "") @@ -12,7 +13,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 +51,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 +89,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/parser.py b/dojo/tools/awssecurityhub/parser.py index 7380ece695..b761bdd214 100644 --- a/dojo/tools/awssecurityhub/parser.py +++ b/dojo/tools/awssecurityhub/parser.py @@ -1,10 +1,13 @@ 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 +from dojo.tools.parser_test import ParserTest -class AwsSecurityHubParser(object): +class AwsSecurityHubParser: + ID = "AWS Security Hub" def get_scan_types(self): return ["AWS Security Hub Scan"] @@ -15,17 +18,39 @@ 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): - 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 +61,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 9d90519fb2..e4f02cf3b8 100644 --- a/dojo/tools/azure_security_center_recommendations/parser.py +++ b/dojo/tools/azure_security_center_recommendations/parser.py @@ -1,11 +1,12 @@ -import sys -import io import csv +import io +import sys from datetime import datetime + from dojo.models import Finding -class AzureSecurityCenterRecommendationsParser(object): +class AzureSecurityCenterRecommendationsParser: def get_scan_types(self): return ["Azure Security Center Recommendations Scan"] @@ -22,7 +23,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/bandit/parser.py b/dojo/tools/bandit/parser.py index 18b03967ad..b209648847 100644 --- a/dojo/tools/bandit/parser.py +++ b/dojo/tools/bandit/parser.py @@ -1,10 +1,11 @@ import json + import dateutil.parser from dojo.models import Finding -class BanditParser(object): +class BanditParser: def get_scan_types(self): return ["Bandit Scan"] @@ -17,7 +18,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 9c0126c3a6..0aca0bcbe4 100644 --- a/dojo/tools/bearer_cli/parser.py +++ b/dojo/tools/bearer_cli/parser.py @@ -1,8 +1,9 @@ import json + from dojo.models import Finding -class BearerParser(object): +class BearerParser: """ Bearer CLI tool is a SAST scanner for multiple languages """ @@ -19,7 +20,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 6cf5eb95d9..7c1e098a37 100644 --- a/dojo/tools/blackduck/importer.py +++ b/dojo/tools/blackduck/importer.py @@ -32,8 +32,8 @@ def _process_csvfile(self, report): If passed in a regular security.csv, process it. No file information then. """ - security_issues = dict() - with open(str(report), "r") as f: + security_issues = {} + with open(str(report)) as f: security_issues = self.__partition_by_key(f) project_ids = set(security_issues.keys()) @@ -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(): @@ -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..4b21c28619 100644 --- a/dojo/tools/blackduck/parser.py +++ b/dojo/tools/blackduck/parser.py @@ -1,10 +1,11 @@ import hashlib from dojo.models import Finding + 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 @@ -33,7 +34,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 @@ -45,16 +46,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 +86,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..2c7528ae2d 100644 --- a/dojo/tools/blackduck_binary_analysis/importer.py +++ b/dojo/tools/blackduck_binary_analysis/importer.py @@ -26,8 +26,8 @@ def _process_csvfile(self, report, orig_report_name): """ If passed a CSV file, process. """ - vulnerabilities = dict() - with open(str(report), "r") as f: + vulnerabilities = {} + 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..2f0523223e 100644 --- a/dojo/tools/blackduck_binary_analysis/parser.py +++ b/dojo/tools/blackduck_binary_analysis/parser.py @@ -1,11 +1,13 @@ import hashlib +from cvss import CVSS2, CVSS3 + from dojo.models import Finding + from .importer import BlackduckBinaryAnalysisImporter -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 @@ -33,7 +35,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 @@ -66,7 +68,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 +107,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 +115,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 +152,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..14bf05ce47 100644 --- a/dojo/tools/blackduck_component_risk/importer.py +++ b/dojo/tools/blackduck_component_risk/importer.py @@ -1,13 +1,13 @@ import csv import io -import zipfile import logging +import zipfile from pathlib import Path 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 @@ -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): """ @@ -39,8 +40,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 @@ -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/blackduck_component_risk/parser.py b/dojo/tools/blackduck_component_risk/parser.py index 644d525bcd..7e683364f4 100644 --- a/dojo/tools/blackduck_component_risk/parser.py +++ b/dojo/tools/blackduck_component_risk/parser.py @@ -1,9 +1,10 @@ # Author: apipia, wheelsvt -from .importer import BlackduckCRImporter from dojo.models import Finding +from .importer import BlackduckCRImporter + -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..dfd23fa43c 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"] @@ -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 941b55fd69..d3672255bf 100644 --- a/dojo/tools/bugcrowd/parser.py +++ b/dojo/tools/bugcrowd/parser.py @@ -3,10 +3,11 @@ import io from dateutil import parser + from dojo.models import Endpoint, Finding -class BugCrowdParser(object): +class BugCrowdParser: def get_scan_types(self): return ["BugCrowd Scan"] @@ -31,7 +32,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 +129,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 8d567af2ec..c960bb374c 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"] @@ -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 old mode 100755 new mode 100644 index bd59959867..f260e598b3 --- a/dojo/tools/burp/parser.py +++ b/dojo/tools/burp/parser.py @@ -1,14 +1,16 @@ import base64 import logging import re + import html2text from defusedxml import ElementTree as etree + from dojo.models import Endpoint, Finding 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. @@ -124,8 +126,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 +147,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 +162,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 7d62f9b637..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 @@ -15,7 +15,7 @@ """ -class BurpApiParser(object): +class BurpApiParser: """Parser that can load data from Burp API""" def get_scan_types(self): @@ -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 @@ -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_dastardly/parser.py b/dojo/tools/burp_dastardly/parser.py old mode 100755 new mode 100644 index e546c83978..3d60653488 --- a/dojo/tools/burp_dastardly/parser.py +++ b/dojo/tools/burp_dastardly/parser.py @@ -1,11 +1,13 @@ import logging + from defusedxml import ElementTree as etree + from dojo.models import Finding logger = logging.getLogger(__name__) -class BurpDastardlyParser(object): +class BurpDastardlyParser: def get_scan_types(self): return ["Burp Dastardly Scan"] @@ -23,7 +25,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 b80e0c54b7..4dc08625fb 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"] @@ -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 90d91c640c..f6d032bc28 100644 --- a/dojo/tools/burp_graphql/parser.py +++ b/dojo/tools/burp_graphql/parser.py @@ -1,15 +1,15 @@ -import logging import json +import logging import re -import html2text +import html2text from dojo.models import Endpoint, Finding logger = logging.getLogger(__name__) -class BurpGraphQLParser(object): +class BurpGraphQLParser: def get_scan_types(self): return ["Burp GraphQL API"] @@ -23,14 +23,15 @@ 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) 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,13 +59,14 @@ 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( "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"] @@ -95,7 +97,7 @@ def combine_findings(self, finding, issue): ) def create_finding(self, issue): - finding = dict() + finding = {} finding["Impact"] = "" finding["Description"] = "" finding["Mitigation"] = "" @@ -169,7 +171,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/cargo_audit/parser.py b/dojo/tools/cargo_audit/parser.py index fddf3be36a..e992e93651 100644 --- a/dojo/tools/cargo_audit/parser.py +++ b/dojo/tools/cargo_audit/parser.py @@ -1,9 +1,10 @@ -import json import hashlib +import json + 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/__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 index 1c2a7220ce..1cfdfdac25 --- 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"] @@ -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 = "" @@ -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 3de2980118..381f705f82 100644 --- a/dojo/tools/checkmarx_one/parser.py +++ b/dojo/tools/checkmarx_one/parser.py @@ -1,10 +1,14 @@ import datetime import json +from typing import List + from dateutil import parser -from dojo.models import Finding +from django.conf import settings + +from dojo.models import Finding, Test -class CheckmarxOneParser(object): +class CheckmarxOneParser: def get_scan_types(self): return ["Checkmarx One Scan"] @@ -22,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/dojo/tools/checkmarx_osa/parser.py b/dojo/tools/checkmarx_osa/parser.py index 30ae18e0f4..f61f5de656 100644 --- a/dojo/tools/checkmarx_osa/parser.py +++ b/dojo/tools/checkmarx_osa/parser.py @@ -1,12 +1,13 @@ import json import logging -from dojo.models import Finding from datetime import datetime +from dojo.models import Finding + logger = logging.getLogger(__name__) -class CheckmarxOsaParser(object): +class CheckmarxOsaParser: def get_scan_types(self): return ["Checkmarx OSA"] @@ -27,7 +28,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,20 +40,18 @@ 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 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"], @@ -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/checkov/parser.py b/dojo/tools/checkov/parser.py index c98e94537f..5628e53576 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"] @@ -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/chefinspect/parser.py b/dojo/tools/chefinspect/parser.py index adf85eb5ea..1dd413df62 100644 --- a/dojo/tools/chefinspect/parser.py +++ b/dojo/tools/chefinspect/parser.py @@ -1,8 +1,9 @@ import json + 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..784132e376 100644 --- a/dojo/tools/clair/clair_parser.py +++ b/dojo/tools/clair/clair_parser.py @@ -1,9 +1,11 @@ import logging + from dojo.models import Finding + 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..c42ba78b32 100644 --- a/dojo/tools/clair/clairklar_parser.py +++ b/dojo/tools/clair/clairklar_parser.py @@ -1,11 +1,13 @@ import logging + from dojo.models import Finding + logger = logging.getLogger(__name__) -class ClairKlarScan(object): +class ClairKlarScan: def get_items_klar(self, tree, test): - items = list() + items = [] clair_severities = [ "Unknown", "Negligible", @@ -22,7 +24,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 b0701de287..dd03c49d7c 100644 --- a/dojo/tools/clair/parser.py +++ b/dojo/tools/clair/parser.py @@ -1,9 +1,10 @@ import json + from dojo.tools.clair.clair_parser import ClairScan from dojo.tools.clair.clairklar_parser import ClairKlarScan -class ClairParser(object): +class ClairParser: def get_scan_types(self): return ["Clair Scan"] @@ -21,7 +22,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: @@ -37,5 +38,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/cloudsploit/parser.py b/dojo/tools/cloudsploit/parser.py index 38e518fc6e..22e8de1a2b 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 """ @@ -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 ea03fb33cf..2e4a74f41f 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"] @@ -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/codechecker/parser.py b/dojo/tools/codechecker/parser.py index 4866145c02..41998099e5 100644 --- a/dojo/tools/codechecker/parser.py +++ b/dojo/tools/codechecker/parser.py @@ -1,9 +1,10 @@ -import json import hashlib +import json + from dojo.models import Finding -class CodeCheckerParser(object): +class CodeCheckerParser: def get_scan_types(self): return ["Codechecker Report native"] @@ -48,7 +49,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 +58,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..73e3b94c7b 100644 --- a/dojo/tools/contrast/parser.py +++ b/dojo/tools/contrast/parser.py @@ -1,13 +1,13 @@ import csv +import datetime import hashlib import io import sys -import datetime from dojo.models import Endpoint, Finding -class ContrastParser(object): +class ContrastParser: """Contrast Scanner CSV Report""" def get_scan_types(self): @@ -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 @@ -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..c3b15f573f 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): @@ -20,12 +20,10 @@ 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 = list() + items = [] for issue in tree["viewContentsV1"]["rows"]: # get only security findings if "Security" != issue.get("displayIssueKind"): @@ -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 old mode 100755 new mode 100644 index 0ac2b37c0b..8770013b79 --- 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. @@ -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: @@ -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. @@ -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"): @@ -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): @@ -240,11 +240,12 @@ 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) 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/cred_scan/parser.py b/dojo/tools/cred_scan/parser.py index 2a2e616f44..6b67305caa 100644 --- a/dojo/tools/cred_scan/parser.py +++ b/dojo/tools/cred_scan/parser.py @@ -1,10 +1,12 @@ import csv import io + from dateutil import parser + 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 @@ -30,7 +32,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/crunch42/parser.py b/dojo/tools/crunch42/parser.py index e1a841e29a..ff09dddcd6 100644 --- a/dojo/tools/crunch42/parser.py +++ b/dojo/tools/crunch42/parser.py @@ -1,8 +1,9 @@ import json + from dojo.models import Finding -class Crunch42Parser(object): +class Crunch42Parser: def get_scan_types(self): return ["Crunch42 Scan"] @@ -21,7 +22,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/helpers.py b/dojo/tools/cyclonedx/helpers.py index ed64843c7d..fb658dfdc1 100644 --- a/dojo/tools/cyclonedx/helpers.py +++ b/dojo/tools/cyclonedx/helpers.py @@ -1,9 +1,11 @@ -from cvss import CVSS3 import logging + +from cvss import CVSS3 + 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..a57b6debaf 100644 --- a/dojo/tools/cyclonedx/json_parser.py +++ b/dojo/tools/cyclonedx/json_parser.py @@ -1,12 +1,15 @@ import json import logging + import dateutil + from dojo.models import Finding from dojo.tools.cyclonedx.helpers import Cyclonedxhelper + 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) @@ -86,7 +89,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")) @@ -126,9 +129,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..91ba3ab0a9 100644 --- a/dojo/tools/cyclonedx/xml_parser.py +++ b/dojo/tools/cyclonedx/xml_parser.py @@ -1,21 +1,23 @@ -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__) -class CycloneDXXMLParser(object): +class CycloneDXXMLParser: def _get_findings_xml(self, file, test): nscan = ElementTree.parse(file) 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( "}", "" @@ -158,7 +160,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 +209,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) @@ -294,9 +296,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..9fb2085a1f 100644 --- a/dojo/tools/dawnscanner/parser.py +++ b/dojo/tools/dawnscanner/parser.py @@ -2,10 +2,11 @@ import re from dateutil import parser + 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..870aba11fb 100644 --- a/dojo/tools/dependency_check/parser.py +++ b/dojo/tools/dependency_check/parser.py @@ -1,19 +1,19 @@ 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 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 @@ -355,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 965e3e3236..e7a39ea4bd 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. @@ -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 @@ -138,8 +143,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 +172,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 @@ -267,7 +270,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() @@ -278,15 +281,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/detect_secrets/parser.py b/dojo/tools/detect_secrets/parser.py index 0da274ba9f..7f139b8230 100644 --- a/dojo/tools/detect_secrets/parser.py +++ b/dojo/tools/detect_secrets/parser.py @@ -1,10 +1,12 @@ -import json import hashlib +import json + import dateutil.parser + 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..4c08b850e0 100644 --- a/dojo/tools/dockerbench/parser.py +++ b/dojo/tools/dockerbench/parser.py @@ -1,10 +1,10 @@ import json +from datetime import datetime from dojo.models import Finding -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..b650694078 100644 --- a/dojo/tools/dockle/parser.py +++ b/dojo/tools/dockle/parser.py @@ -1,9 +1,10 @@ -import json import hashlib +import json + 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/dsop/parser.py b/dojo/tools/dsop/parser.py index 597e69c105..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 @@ -16,7 +17,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 +30,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 +76,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 +122,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 +171,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 +209,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 c3e2167b8c..2b698e7b17 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"] @@ -28,7 +28,7 @@ def get_findings(self, filename, test): except Exception: data = json.loads(tree) - items = list() + items = [] for item in data: findingdetail = "" @@ -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/factory.py b/dojo/tools/factory.py old mode 100755 new mode 100644 index 55549cccd7..2ec6f7c036 --- 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 = {} @@ -25,35 +27,38 @@ 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(): - 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 +73,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 de745d236d..ca4d268668 100644 --- a/dojo/tools/fortify/fpr_parser.py +++ b/dojo/tools/fortify/fpr_parser.py @@ -1,10 +1,12 @@ import re import zipfile + from defusedxml import ElementTree + 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') @@ -18,7 +20,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/fortify/parser.py b/dojo/tools/fortify/parser.py index 7ef6a07f85..85fdc6d33e 100644 --- a/dojo/tools/fortify/parser.py +++ b/dojo/tools/fortify/parser.py @@ -1,8 +1,8 @@ -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(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..92469da88c 100644 --- a/dojo/tools/fortify/xml_parser.py +++ b/dojo/tools/fortify/xml_parser.py @@ -1,8 +1,9 @@ from defusedxml import ElementTree + 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 +121,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 +132,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 +145,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..d531f9b6f6 100644 --- a/dojo/tools/gcloud_artifact_scan/parser.py +++ b/dojo/tools/gcloud_artifact_scan/parser.py @@ -1,8 +1,9 @@ import json + from dojo.models import Finding -class GCloudArtifactScanParser(object): +class GCloudArtifactScanParser: def get_scan_types(self): return ["Google Cloud Artifact Vulnerability Scan"] @@ -20,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 def get_findings(self, json_output, test): 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 9f63bcd60e..e2fb66086b 100644 --- a/dojo/tools/generic/parser.py +++ b/dojo/tools/generic/parser.py @@ -1,15 +1,11 @@ -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 -class GenericParser(object): +class GenericParser: ID = "Generic Findings Import" def get_scan_types(self): @@ -23,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 = list() - 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: - raise ValueError(f"Required fields are missing: {missing}") - - # 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: - raise ValueError( - f"Not allowed fields are present: {not_allowed}" - ) - - 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 = dict() - 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("utf-8") - ).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/ggshield/parser.py b/dojo/tools/ggshield/parser.py old mode 100755 new mode 100644 index 3d6373c87e..383c334390 --- a/dojo/tools/ggshield/parser.py +++ b/dojo/tools/ggshield/parser.py @@ -1,10 +1,12 @@ -import json import hashlib -from dojo.models import Finding +import json + from dateutil import parser +from dojo.models import Finding + -class GgshieldParser(object): +class GgshieldParser: """ A class that can be used to parse the Gitleaks JSON report files """ @@ -24,7 +26,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 ac44d815e8..3739fc6f20 100644 --- a/dojo/tools/github_vulnerability/parser.py +++ b/dojo/tools/github_vulnerability/parser.py @@ -1,11 +1,12 @@ -import dateutil import json +import dateutil from cvss import parser as cvss_parser + from dojo.models import Finding -class GithubVulnerabilityParser(object): +class GithubVulnerabilityParser: def get_scan_types(self): return ["Github Vulnerability Scan"] @@ -20,9 +21,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"]: @@ -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" @@ -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( @@ -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/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..4aa245c399 100644 --- a/dojo/tools/gitlab_container_scan/parser.py +++ b/dojo/tools/gitlab_container_scan/parser.py @@ -2,10 +2,11 @@ import textwrap from dateutil.parser import parse + 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..83a7829af6 100644 --- a/dojo/tools/gitlab_dast/parser.py +++ b/dojo/tools/gitlab_dast/parser.py @@ -1,10 +1,11 @@ -import json import hashlib +import json from datetime import datetime -from dojo.models import Finding, Endpoint + +from dojo.models import Endpoint, Finding -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..2ec561500c 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"] @@ -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/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..f3c6f4c6ea 100644 --- a/dojo/tools/gitlab_secret_detection_report/parser.py +++ b/dojo/tools/gitlab_secret_detection_report/parser.py @@ -1,9 +1,10 @@ import json from datetime import datetime + 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..40ec9b9a81 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 """ @@ -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"): @@ -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/gosec/__init__.py b/dojo/tools/gosec/__init__.py old mode 100755 new mode 100644 diff --git a/dojo/tools/gosec/parser.py b/dojo/tools/gosec/parser.py index 4d3824913b..69056d9281 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"] @@ -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 = "" @@ -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/govulncheck/parser.py b/dojo/tools/govulncheck/parser.py index 31b8ec0c75..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__) @@ -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/h1/parser.py b/dojo/tools/h1/parser.py index 8d3409799f..9708bedfc0 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. """ @@ -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"] @@ -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"]: @@ -116,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() @@ -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..4186544b21 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 """ @@ -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 old mode 100755 new mode 100644 index 8f559acc53..fbf1a49b25 --- a/dojo/tools/hcl_appscan/parser.py +++ b/dojo/tools/hcl_appscan/parser.py @@ -1,9 +1,11 @@ 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(object): +class HCLAppScanParser: def get_scan_types(self): return ["HCLAppScan XML"] @@ -14,7 +16,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 @@ -27,9 +31,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: @@ -39,7 +42,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': @@ -107,7 +113,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/horusec/parser.py b/dojo/tools/horusec/parser.py index c8826dffab..8e9571820f 100644 --- a/dojo/tools/horusec/parser.py +++ b/dojo/tools/horusec/parser.py @@ -2,11 +2,12 @@ from datetime import datetime from dateutil.parser import parse + from dojo.models import Finding 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..f9044c0210 100644 --- a/dojo/tools/humble/parser.py +++ b/dojo/tools/humble/parser.py @@ -1,8 +1,9 @@ import json -from dojo.models import Finding, Endpoint +from dojo.models import Endpoint, Finding -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..472ffbbf6f 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 """ @@ -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 f24160ac7f..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__) @@ -20,7 +21,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) """ @@ -72,9 +73,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 +103,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 8e4147a228..72700fd72c 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"] @@ -24,13 +24,12 @@ 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) - dupes = dict() + dupes = {} # Now time to loop through individual issues and perform necessary # actions for issue in root.iter("issue-group"): @@ -107,7 +106,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 6265d1f620..5076259f7f 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"] @@ -22,11 +22,10 @@ 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 = dict() + dupes = {} for vulnerability in root.iter("Vulnerability"): """ @@ -83,7 +82,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/csv_handler.py b/dojo/tools/intsights/csv_handler.py new file mode 100644 index 0000000000..828cfaf802 --- /dev/null +++ b/dojo/tools/intsights/csv_handler.py @@ -0,0 +1,95 @@ +import collections +import csv +import io + + +class IntSightsCSVParser: + 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..ec315ac101 --- /dev/null +++ b/dojo/tools/intsights/json_handler.py @@ -0,0 +1,51 @@ +import json + + +class IntSightsJSONParser: + 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 = {} + 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 2c97225fae..cd6a61a57a 100644 --- a/dojo/tools/intsights/parser.py +++ b/dojo/tools/intsights/parser.py @@ -1,13 +1,11 @@ -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(object): +class IntSightsParser: """ IntSights Threat Intelligence Report """ @@ -23,144 +21,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. @@ -184,22 +44,18 @@ 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 = 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" - ) - + msg = "Filename extension not recognized. Use .json or .csv" + raise ValueError(msg) 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() diff --git a/dojo/tools/jfrog_xray_api_summary_artifact/parser.py b/dojo/tools/jfrog_xray_api_summary_artifact/parser.py index f62d353229..7453669b47 100644 --- a/dojo/tools/jfrog_xray_api_summary_artifact/parser.py +++ b/dojo/tools/jfrog_xray_api_summary_artifact/parser.py @@ -1,14 +1,14 @@ +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 -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"] @@ -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 b6901c289c..786635b3ff 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): @@ -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/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..36ffa900cf 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): @@ -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/kics/parser.py b/dojo/tools/kics/parser.py index 3f5a279762..f0b2c1defc 100644 --- a/dojo/tools/kics/parser.py +++ b/dojo/tools/kics/parser.py @@ -1,9 +1,10 @@ -import json import hashlib +import json + 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..4eeb8146af 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"] @@ -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 63a998f8ac..065eb45427 100644 --- a/dojo/tools/kubeaudit/parser.py +++ b/dojo/tools/kubeaudit/parser.py @@ -1,8 +1,9 @@ import json + from dojo.models import Finding -class KubeAuditParser(object): +class KubeAuditParser: def get_scan_types(self): return ["Kubeaudit Scan"] @@ -25,7 +26,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/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..54e2bfa842 100644 --- a/dojo/tools/kubehunter/parser.py +++ b/dojo/tools/kubehunter/parser.py @@ -1,9 +1,10 @@ import hashlib import json + 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. """ @@ -20,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 = {} # Find any missing attribute vulnerabilities = data['vulnerabilities'] diff --git a/dojo/tools/kubescape/parser.py b/dojo/tools/kubescape/parser.py index 716244a323..a5797e8402 100644 --- a/dojo/tools/kubescape/parser.py +++ b/dojo/tools/kubescape/parser.py @@ -1,8 +1,9 @@ import json + 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..5fc6464526 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"] @@ -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/meterian/parser.py b/dojo/tools/meterian/parser.py index e47cb46901..ab9fa93392 100644 --- a/dojo/tools/meterian/parser.py +++ b/dojo/tools/meterian/parser.py @@ -1,10 +1,10 @@ import json - from datetime import datetime + from dojo.models import Finding -class MeterianParser(object): +class MeterianParser: def get_scan_types(self): return ["Meterian Scan"] @@ -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 65032214c2..9764a2e8db 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): @@ -24,11 +24,10 @@ 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 = dict() + dupes = {} for session in root: url = session.find("URL").text endpoint = Endpoint.from_uri(url) @@ -82,7 +81,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..2cbdca7920 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,57 +30,57 @@ 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) + test_description = f"{test_description}\n**File Information:**\n" 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 = "" for url in data["urls"]: for curl in url["urls"]: - curl = "%s\n" % (curl) + curl = f"{curl}\n" 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..67c30ffb1c 100644 --- a/dojo/tools/mobsfscan/parser.py +++ b/dojo/tools/mobsfscan/parser.py @@ -1,10 +1,11 @@ -import json import hashlib +import json import re + 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..1d88b3cf11 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 @@ -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 3bcdf56e07..3ce7c9a562 100644 --- a/dojo/tools/ms_defender/parser.py +++ b/dojo/tools/ms_defender/parser.py @@ -1,9 +1,10 @@ import json -from dojo.models import Finding, Endpoint import zipfile +from dojo.models import Endpoint, Finding -class MSDefenderParser(object): + +class MSDefenderParser: """ Import from MSDefender findings """ @@ -34,15 +35,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 +83,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 +133,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/nancy/parser.py b/dojo/tools/nancy/parser.py index 4f8a65c4ed..19534728c8 100644 --- a/dojo/tools/nancy/parser.py +++ b/dojo/tools/nancy/parser.py @@ -1,10 +1,11 @@ import json from cvss.cvss3 import CVSS3 + from dojo.models import Finding -class NancyParser(object): +class NancyParser: def get_scan_types(self): return ["Nancy Scan"] @@ -27,7 +28,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 @@ -63,7 +65,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/dojo/tools/netsparker/parser.py b/dojo/tools/netsparker/parser.py index b79e043c81..1a61276fda 100644 --- a/dojo/tools/netsparker/parser.py +++ b/dojo/tools/netsparker/parser.py @@ -1,12 +1,13 @@ -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(object): +class NetsparkerParser: def get_scan_types(self): return ["Netsparker Scan"] @@ -22,7 +23,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 17be763568..f2f20ebd53 100644 --- a/dojo/tools/neuvector/parser.py +++ b/dojo/tools/neuvector/parser.py @@ -10,12 +10,12 @@ 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 = [] 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): @@ -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 @@ -102,9 +103,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 +128,7 @@ def convert_severity(severity): return severity.title() -class NeuVectorParser(object): +class NeuVectorParser: def get_scan_types(self): return [NEUVECTOR_SCAN_NAME] @@ -141,9 +140,10 @@ 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) 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 74e5e515fd..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)" @@ -11,7 +10,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 @@ -23,7 +22,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 @@ -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] @@ -147,9 +145,10 @@ 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) else: - raise ValueError("Unknown File Format") + msg = "Unknown File Format" + raise ValueError(msg) diff --git a/dojo/tools/nexpose/parser.py b/dojo/tools/nexpose/parser.py index 4fd1c85b67..67908e03d6 100644 --- a/dojo/tools/nexpose/parser.py +++ b/dojo/tools/nexpose/parser.py @@ -1,14 +1,15 @@ -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(object): +class NexposeParser: """ The objective of this class is to parse Nexpose's XML 2.0 Report. @@ -106,7 +107,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 +144,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 +164,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 +209,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 +366,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 2d06902e46..bde6ef3e62 100644 --- a/dojo/tools/nikto/json_parser.py +++ b/dojo/tools/nikto/json_parser.py @@ -1,13 +1,14 @@ import json + 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): 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/parser.py b/dojo/tools/nikto/parser.py index 99ea2f2697..6e0f49dbb9 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: @@ -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/nikto/xml_parser.py b/dojo/tools/nikto/xml_parser.py index 3480ffadd8..ab5dffe906 100644 --- a/dojo/tools/nikto/xml_parser.py +++ b/dojo/tools/nikto/xml_parser.py @@ -1,15 +1,18 @@ -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__) -class NiktoXMLParser(object): +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 old mode 100755 new mode 100644 index 171795126c..f0eb012895 --- a/dojo/tools/nmap/parser.py +++ b/dojo/tools/nmap/parser.py @@ -2,10 +2,11 @@ from cpe import CPE from defusedxml.ElementTree import parse + from dojo.models import Endpoint, Finding -class NmapParser(object): +class NmapParser: def get_scan_types(self): return ["Nmap Scan"] @@ -18,9 +19,10 @@ 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.") + msg = "This doesn't seem to be a valid Nmap xml file." + raise ValueError(msg) report_date = None try: @@ -35,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"] @@ -43,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" @@ -51,10 +53,10 @@ 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:** {0}%\n".format( + host_info += "**Accuracy:** {}%\n".format( os_match.attrib["accuracy"] ) @@ -74,31 +76,25 @@ 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: 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 @@ -129,7 +125,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 @@ -163,7 +159,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/noseyparker/parser.py b/dojo/tools/noseyparker/parser.py index acb28056f1..7e1138b1be 100644 --- a/dojo/tools/noseyparker/parser.py +++ b/dojo/tools/noseyparker/parser.py @@ -1,11 +1,11 @@ import hashlib import json - from datetime import datetime + from dojo.models import Finding -class NoseyParkerParser(object): +class NoseyParkerParser: """ Scanning secrets from repos """ @@ -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 a9b6dfe9bf..fc07e28100 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"] @@ -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") @@ -148,7 +147,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/npm_audit_7_plus/parser.py b/dojo/tools/npm_audit_7_plus/parser.py index 1a500b8e3b..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__) @@ -20,7 +21,7 @@ ''' -class NpmAudit7PlusParser(object): +class NpmAudit7PlusParser: """Represents the parser class.""" def get_scan_types(self): @@ -51,25 +52,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( - ("This parser only supports output from npm audit version" - " 7 and above.") + 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( - ("This parser only supports output from npm audit version" - " 7 and above.") + msg = ( + "This parser only supports output from npm audit version" + " 7 and above." ) + raise ValueError(msg) subtree = tree.get("vulnerabilities") return subtree @@ -125,7 +129,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 +191,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..0b4da91c4e 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"] @@ -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/nuclei/parser.py b/dojo/tools/nuclei/parser.py index 76ed959eac..4e97c4f6b7 100644 --- a/dojo/tools/nuclei/parser.py +++ b/dojo/tools/nuclei/parser.py @@ -1,15 +1,16 @@ -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__) -class NucleiParser(object): +class NucleiParser: """ A class that can be used to parse the nuclei (https://github.com/projectdiscovery/nuclei) JSON report file """ @@ -94,9 +95,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 9f3ba66132..a96a1cdcca 100644 --- a/dojo/tools/openscap/parser.py +++ b/dojo/tools/openscap/parser.py @@ -2,13 +2,13 @@ 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(object): +class OpenscapParser: def get_scan_types(self): return ["Openscap Vulnerability Scan"] @@ -26,36 +26,34 @@ 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 = {} - 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() + 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( - "./{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 +67,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 +82,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..ff9e8bf888 100644 --- a/dojo/tools/openvas/csv_parser.py +++ b/dojo/tools/openvas/csv_parser.py @@ -2,11 +2,13 @@ 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(object): +class ColumnMappingStrategy: mapped_column = None def __init__(self): @@ -37,7 +39,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 +48,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 +57,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 +67,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 +77,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 +92,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 +104,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 +114,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 +126,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 +141,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 +153,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 +162,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 +171,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 +180,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 +189,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 +198,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 +207,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 +216,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() @@ -260,7 +262,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 +270,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 +280,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/openvas/parser.py b/dojo/tools/openvas/parser.py old mode 100755 new mode 100644 index 6a1399f28e..ce548db587 --- 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..3746d5c27b 100644 --- a/dojo/tools/openvas/xml_parser.py +++ b/dojo/tools/openvas/xml_parser.py @@ -1,17 +1,18 @@ from xml.dom import NamespaceErr + from defusedxml import ElementTree as ET + from dojo.models import Finding -class OpenVASXMLParser(object): +class OpenVASXMLParser: def get_findings(self, filename, test): findings = [] 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 d2811d3e17..b2c33b0c45 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): @@ -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: @@ -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 8d04bac2d4..e9abb97770 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 @@ -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: @@ -33,14 +33,15 @@ 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 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: @@ -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/osv_scanner/parser.py b/dojo/tools/osv_scanner/parser.py index 4d6fff7ab4..42e9408825 100644 --- a/dojo/tools/osv_scanner/parser.py +++ b/dojo/tools/osv_scanner/parser.py @@ -1,8 +1,9 @@ import json + from dojo.models import Finding -class OSVScannerParser(object): +class OSVScannerParser: def get_scan_types(self): return ["OSV Scan"] @@ -28,7 +29,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"] @@ -37,7 +38,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 +66,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 = [] + 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 af07759f1e..6d42ee855e 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"] @@ -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") @@ -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/__init__.py b/dojo/tools/php_security_audit_v2/__init__.py old mode 100755 new mode 100644 diff --git a/dojo/tools/php_security_audit_v2/parser.py b/dojo/tools/php_security_audit_v2/parser.py index f1ee8022c1..91b7e4c6c3 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"] @@ -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/php_symfony_security_check/parser.py b/dojo/tools/php_symfony_security_check/parser.py index c5fb511880..a124a4d419 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"] @@ -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/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 e34c1c21f5..484d289b03 100644 --- a/dojo/tools/pmd/parser.py +++ b/dojo/tools/pmd/parser.py @@ -1,10 +1,11 @@ -import io import csv import hashlib +import io + from dojo.models import Finding -class PmdParser(object): +class PmdParser: def get_scan_types(self): return ["PMD Scan"] @@ -15,7 +16,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): @@ -54,7 +55,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..65ac0d8580 100644 --- a/dojo/tools/popeye/parser.py +++ b/dojo/tools/popeye/parser.py @@ -1,10 +1,11 @@ import hashlib import json import re + from dojo.models import Finding -class PopeyeParser(object): +class PopeyeParser: """ Popeye is a kubernetes cluster resource analyzer. """ @@ -21,7 +22,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/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/dojo/tools/pwn_sast/parser.py b/dojo/tools/pwn_sast/parser.py index 0b5a942eb4..0a4ba9652e 100644 --- a/dojo/tools/pwn_sast/parser.py +++ b/dojo/tools/pwn_sast/parser.py @@ -1,10 +1,10 @@ -import json import hashlib +import json 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/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 a415b4487f..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 @@ -173,7 +174,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 @@ -187,9 +188,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() @@ -281,7 +280,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 @@ -298,7 +297,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..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 @@ -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..c978750af5 100644 --- a/dojo/tools/qualys_webapp/parser.py +++ b/dojo/tools/qualys_webapp/parser.py @@ -1,11 +1,8 @@ -#!/usr/bin/env python -# -# -*- coding:utf-8 -*- - import base64 import re import xml.etree.ElementTree from datetime import datetime + from dojo.models import Endpoint, Finding try: @@ -58,8 +55,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 +116,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 @@ -464,7 +461,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 4ca94bdf5b..f241e18ee4 100644 --- a/dojo/tools/redhatsatellite/parser.py +++ b/dojo/tools/redhatsatellite/parser.py @@ -1,8 +1,9 @@ import json + from dojo.models import Finding -class RedHatSatelliteParser(object): +class RedHatSatelliteParser: def get_scan_types(self): return ["Red Hat Satellite"] @@ -26,7 +27,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")) @@ -62,17 +63,17 @@ 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: - 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/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..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() @@ -29,7 +31,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}, ) @@ -50,11 +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( - "Unable to query Target of Evaluations due to {} - {}".format( - 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"]] @@ -71,7 +70,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, @@ -84,8 +83,5 @@ def get_findings(self): if not self.filter_finding(finding): self.findings.append(finding) else: - raise Exception( - "Unable to collect findings from toe: {} due to {} - {}".format( - toe, 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/risk_recon/parser.py b/dojo/tools/risk_recon/parser.py index 8c70496d69..7d14b6ebce 100644 --- a/dojo/tools/risk_recon/parser.py +++ b/dojo/tools/risk_recon/parser.py @@ -1,11 +1,12 @@ import json import dateutil + from dojo.models import Finding from dojo.tools.risk_recon.api import RiskReconAPI -class RiskReconParser(object): +class RiskReconParser: def get_scan_types(self): return ["Risk Recon API Importer"] @@ -37,7 +38,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 da0baa6c83..4ffd6c9ade 100644 --- a/dojo/tools/rusty_hog/parser.py +++ b/dojo/tools/rusty_hog/parser.py @@ -1,9 +1,10 @@ import json -from dojo.tools.parser_test import ParserTest + from dojo.models import Finding +from dojo.tools.parser_test import ParserTest -class RustyhogParser(object): +class RustyhogParser: def get_scan_types(self): return ["Rusty Hog Scan"] @@ -27,13 +28,13 @@ 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()) def get_tests(self, scan_type, handle): tree = self.parse_json(handle) - tests = list() + tests = [] parsername = "Rusty Hog" for node in tree: if ( @@ -81,9 +82,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 +118,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 +134,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 +149,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..59dae7da29 100644 --- a/dojo/tools/sarif/parser.py +++ b/dojo/tools/sarif/parser.py @@ -2,18 +2,19 @@ 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__) 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 @@ -31,16 +32,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 +52,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) @@ -180,7 +181,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) @@ -267,9 +269,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```\n{get_snippet(result)}\n```\n" if rule is not None: if "name" in rule: description += f"**{_('Rule name')}:** {rule.get('name')}\n" @@ -462,7 +464,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 d4b1e6c076..b2b3b5f302 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 @@ -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 1d019606e5..e6344fa67a 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,31 +34,25 @@ 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"], ) # 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( @@ -72,7 +66,7 @@ def get_tests(self, scan_type, handle): ] ) - tests = list() + tests = [] test = ParserTest( name=self.ID, type=data["provider_name"], @@ -177,11 +171,11 @@ 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 = ( - 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/semgrep/parser.py b/dojo/tools/semgrep/parser.py index 94f5a1008c..97e711bf23 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"] @@ -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", []): @@ -139,20 +139,21 @@ 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 = "" 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 "= 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..6985117ecd --- /dev/null +++ b/dojo/tools/sonarqube/sonarqube_restapi_json.py @@ -0,0 +1,229 @@ +import re + +from dojo.models import Finding + + +class SonarQubeRESTAPIJSON: + 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") + 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, + cwe=cwe, + cvssv3_score=cvss, + tags=["vulnerability"], + ) + vulnids = [] + 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 = [] + for vulnid in vulnids: + item.unsaved_vulnerability_ids.append(vulnid) + 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..983678423a --- /dev/null +++ b/dojo/tools/sonarqube/sonarqube_restapi_zip.py @@ -0,0 +1,13 @@ +import json + +from dojo.tools.sonarqube.sonarqube_restapi_json import SonarQubeRESTAPIJSON + + +class SonarQubeRESTAPIZIP: + def get_items(self, files, test, mode): + total_findings_per_file = [] + 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..ac5ca6f68f --- /dev/null +++ b/dojo/tools/sonarqube/soprasteria_helper.py @@ -0,0 +1,141 @@ +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: + 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 = f"{vuln_cwe}{vuln_title}{vuln_description}{vuln_file_path}" + descriptionOneOccurence = f"Line: {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 = f"{find.description}\n{descriptionOneOccurence}" + find.mitigation = f"{find.mitigation}\n______\n{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 = f"{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..8865ac618e --- /dev/null +++ b/dojo/tools/sonarqube/soprasteria_html.py @@ -0,0 +1,85 @@ +import logging + +from dojo.tools.sonarqube.soprasteria_helper import SonarQubeSoprasteriaHelper + +logger = logging.getLogger(__name__) + + +class SonarQubeSoprasteriaHTML: + 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 = {} + 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 = {} + 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..5feb49343c --- /dev/null +++ b/dojo/tools/sonarqube/soprasteria_json.py @@ -0,0 +1,72 @@ +import logging + +from lxml import etree + +from dojo.tools.sonarqube.soprasteria_helper import SonarQubeSoprasteriaHelper + +logger = logging.getLogger(__name__) + + +class SonarQubeSoprasteriaJSON: + def get_json_items(self, json_content, test, mode): + dupes = {} + 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/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 2cd1bd58a9..367fd54d49 100644 --- a/dojo/tools/spotbugs/parser.py +++ b/dojo/tools/spotbugs/parser.py @@ -1,10 +1,12 @@ import re + import html2text from defusedxml import ElementTree as ET + from dojo.models import Finding -class SpotbugsParser(object): +class SpotbugsParser: """Parser for XML ouput file from Spotbugs (https://github.com/spotbugs/spotbugs)""" def get_scan_types(self): @@ -17,9 +19,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 1c0868b4c8..4e3ddb4b36 100644 --- a/dojo/tools/ssh_audit/parser.py +++ b/dojo/tools/ssh_audit/parser.py @@ -1,8 +1,9 @@ import json + from dojo.models import Endpoint, Finding -class SSHAuditParser(object): +class SSHAuditParser: def get_scan_types(self): return ["SSH Audit Importer"] @@ -51,7 +52,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 +70,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 +86,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 +102,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 +122,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 +140,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 +158,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 +176,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 +192,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 +208,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 5c99ef03e3..f70992674a 100644 --- a/dojo/tools/ssl_labs/parser.py +++ b/dojo/tools/ssl_labs/parser.py @@ -6,7 +6,7 @@ from dojo.models import Endpoint, Finding -class SslLabsParser(object): +class SslLabsParser: def get_scan_types(self): return ["SSL Labs Scan"] @@ -57,36 +57,36 @@ def get_findings(self, filename, test): if "ipAddress" in endpoints: ipAddress = endpoints["ipAddress"] - title = "TLS Grade '%s' for %s" % (grade, hostName) + 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"] - description = "%sCertifcate Subject: %s\n" % ( + description = "{}Certifcate Subject: {}\n".format( description, cert["subject"], ) - description = "%sIssuer Subject: %s\n" % ( + description = "{}Issuer Subject: {}\n".format( description, cert["issuerSubject"], ) - description = "%sSignature Algorithm: %s\n" % ( + description = "{}Signature Algorithm: {}\n".format( description, cert["sigAlg"], ) else: for cert in host["certs"]: - description = "%sCertifcate Subject: %s\n" % ( + description = "{}Certifcate Subject: {}\n".format( description, cert["subject"], ) - description = "%sIssuer Subject: %s\n" % ( + description = "{}Issuer Subject: {}\n".format( description, cert["issuerSubject"], ) - description = "%sSignature Algorithm: %s\n" % ( + description = "{}Signature Algorithm: {}\n".format( description, cert["sigAlg"], ) @@ -307,7 +307,7 @@ def get_findings(self, filename, test): protoName = "" for protocols in endpoints["details"]["protocols"]: - protoName = "%s %s %s\n" % ( + protoName = "{} {} {}\n".format( protoName, protocols["name"], protocols["version"], @@ -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 f5166c407d..421e197442 100644 --- a/dojo/tools/sslscan/parser.py +++ b/dojo/tools/sslscan/parser.py @@ -8,7 +8,7 @@ __author__ = "dr3dd589" -class SslscanParser(object): +class SslscanParser: def get_scan_types(self): return ["Sslscan"] @@ -23,10 +23,9 @@ 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." - ) - dupes = dict() + msg = "This doesn't seem to be a valid sslscan xml file." + raise NamespaceErr(msg) + dupes = {} for ssltest in root: for target in ssltest: title = "" @@ -85,7 +84,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 4f557d887a..a80965f294 100644 --- a/dojo/tools/sslyze/parser.py +++ b/dojo/tools/sslyze/parser.py @@ -2,7 +2,7 @@ from .parser_xml import SSLyzeXMLParser -class SslyzeParser(object): +class SslyzeParser: """SSLyze support JSON and XML""" def get_scan_types(self): @@ -18,11 +18,12 @@ 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) 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 f5491612c8..48dc625c04 100644 --- a/dojo/tools/sslyze/parser_json.py +++ b/dojo/tools/sslyze/parser_json.py @@ -68,7 +68,7 @@ REFERENCES = "TLS recommendations of German BSI: " + BSI_LINK -class SSLyzeJSONParser(object): +class SSLyzeJSONParser: def get_findings(self, json_output, test): if json_output is None: return @@ -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 @@ -587,7 +588,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 52b096a00b..07c2adcaad 100644 --- a/dojo/tools/sslyze/parser_xml.py +++ b/dojo/tools/sslyze/parser_xml.py @@ -49,18 +49,17 @@ PROTOCOLS = ["sslv2", "sslv3", "tlsv1", "tlsv1_1", "tlsv1_2", "tlsv1_3"] -class SSLyzeXMLParser(object): +class SSLyzeXMLParser: def get_findings(self, file, test): tree = ET.parse(file) # 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 = dict() + dupes = {} for target in results: host = target.attrib["host"] port = target.attrib["port"] @@ -153,7 +152,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/stackhawk/parser.py b/dojo/tools/stackhawk/parser.py index a8bb4aa09b..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): @@ -14,7 +15,7 @@ def __init__(self, completed_scan): self.service = completed_scan["scan"]["application"] -class StackHawkParser(object): +class StackHawkParser: """ DAST findings from StackHawk """ @@ -123,12 +124,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/parser.py b/dojo/tools/sysdig_reports/parser.py index e6b85b7db5..7d1ad6dc89 100644 --- a/dojo/tools/sysdig_reports/parser.py +++ b/dojo/tools/sysdig_reports/parser.py @@ -1,12 +1,13 @@ -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(object): +class SysdigReportsParser: """ Sysdig Report Importer - Runtime CSV """ @@ -39,8 +40,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 +104,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 +121,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/sysdig_reports/sysdig_csv_parser.py b/dojo/tools/sysdig_reports/sysdig_csv_parser.py index 21d5e946fa..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 @@ -26,11 +27,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/talisman/parser.py b/dojo/tools/talisman/parser.py index 8b07e52d88..20d2874c40 100644 --- a/dojo/tools/talisman/parser.py +++ b/dojo/tools/talisman/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class TalismanParser(object): +class TalismanParser: """ A class that can be used to parse the Talisman JSON report files """ @@ -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/tenable/csv_format.py b/dojo/tools/tenable/csv_format.py index 271ca4d9d6..c88287cf6e 100644 --- a/dojo/tools/tenable/csv_format.py +++ b/dojo/tools/tenable/csv_format.py @@ -13,7 +13,7 @@ LOGGER = logging.getLogger(__name__) -class TenableCSVParser(object): +class TenableCSVParser: def _validated_severity(self, severity): if severity not in Finding.SEVERITIES.keys(): severity = "Info" diff --git a/dojo/tools/tenable/parser.py b/dojo/tools/tenable/parser.py index 0b54e9ea2d..b24b072a68 100644 --- a/dojo/tools/tenable/parser.py +++ b/dojo/tools/tenable/parser.py @@ -2,7 +2,7 @@ from dojo.tools.tenable.xml_format import TenableXMLParser -class TenableParser(object): +class TenableParser: def get_scan_types(self): return ["Tenable Scan"] @@ -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 7fe466507f..d0c231b67d 100644 --- a/dojo/tools/tenable/xml_format.py +++ b/dojo/tools/tenable/xml_format.py @@ -10,7 +10,7 @@ LOGGER = logging.getLogger(__name__) -class TenableXMLParser(object): +class TenableXMLParser: def get_text_severity(self, severity_id): """Convert data of the report into severity""" severity = "Info" @@ -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 15e9e06813..ebc761f93b 100644 --- a/dojo/tools/terrascan/parser.py +++ b/dojo/tools/terrascan/parser.py @@ -1,9 +1,10 @@ -import json import hashlib +import json + from dojo.models import Finding -class TerrascanParser(object): +class TerrascanParser: """ A class that can be used to parse the terrascan JSON report file """ @@ -28,9 +29,10 @@ 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 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 0a03239c44..01369ea439 100644 --- a/dojo/tools/testssl/parser.py +++ b/dojo/tools/testssl/parser.py @@ -5,7 +5,7 @@ from dojo.models import Endpoint, Finding -class TestsslParser(object): +class TestsslParser: def get_scan_types(self): return ["Testssl Scan"] @@ -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 fd6751cc53..8e145a92d9 100644 --- a/dojo/tools/tfsec/parser.py +++ b/dojo/tools/tfsec/parser.py @@ -1,9 +1,10 @@ -import json import hashlib +import json + from dojo.models import Finding -class TFSecParser(object): +class TFSecParser: """ A class that can be used to parse the tfsec JSON report file """ @@ -32,11 +33,10 @@ 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 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 94cc9cd6af..418fabcf31 100644 --- a/dojo/tools/threagile/parser.py +++ b/dojo/tools/threagile/parser.py @@ -48,7 +48,7 @@ } -class ThreagileParser(object): +class ThreagileParser: """ Import ThreaAgile threatmodel risk finding in JSON format """ @@ -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 list() + 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/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/parser.py b/dojo/tools/trivy/parser.py index 262ee0736a..400f71c36d 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") @@ -145,12 +145,11 @@ 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 = 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..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: @@ -28,18 +29,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/trufflehog/parser.py b/dojo/tools/trufflehog/parser.py index 77235356c6..7c6dc905f0 100644 --- a/dojo/tools/trufflehog/parser.py +++ b/dojo/tools/trufflehog/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class TruffleHogParser(object): +class TruffleHogParser: def get_scan_types(self): return ["Trufflehog Scan"] diff --git a/dojo/tools/trufflehog3/parser.py b/dojo/tools/trufflehog3/parser.py index 3302af93c8..11cbe68072 100644 --- a/dojo/tools/trufflehog3/parser.py +++ b/dojo/tools/trufflehog3/parser.py @@ -4,7 +4,7 @@ from dojo.models import Finding -class TruffleHog3Parser(object): +class TruffleHog3Parser: def get_scan_types(self): return ["Trufflehog3 Scan"] @@ -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"): @@ -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/trustwave/__init__.py b/dojo/tools/trustwave/__init__.py old mode 100755 new mode 100644 diff --git a/dojo/tools/trustwave/parser.py b/dojo/tools/trustwave/parser.py index 1f51edfd71..229d658802 100644 --- a/dojo/tools/trustwave/parser.py +++ b/dojo/tools/trustwave/parser.py @@ -5,7 +5,7 @@ from dojo.models import Endpoint, Finding -class TrustwaveParser(object): +class TrustwaveParser: def get_scan_types(self): return ["Trustwave Scan (CSV)"] diff --git a/dojo/tools/trustwave_fusion_api/parser.py b/dojo/tools/trustwave_fusion_api/parser.py index d695e4ee6e..6b6bf2a27a 100644 --- a/dojo/tools/trustwave_fusion_api/parser.py +++ b/dojo/tools/trustwave_fusion_api/parser.py @@ -1,11 +1,13 @@ -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(object): +class TrustwaveFusionAPIParser: """ Import Trustwave Fusion Report from its API in JSON format """ diff --git a/dojo/tools/twistlock/parser.py b/dojo/tools/twistlock/parser.py index 5c7c23d887..d561555042 100644 --- a/dojo/tools/twistlock/parser.py +++ b/dojo/tools/twistlock/parser.py @@ -10,7 +10,7 @@ logger = logging.getLogger(__name__) -class TwistlockCSVParser(object): +class TwistlockCSVParser: def parse_issue(self, row, test): if not row: return None @@ -56,9 +56,7 @@ def parse_issue(self, row, test): duplicate=False, out_of_scope=False, mitigated=None, - severity_justification="(CVSS v3 base score: {})".format( - data_cvss - ), + severity_justification=f"(CVSS v3 base score: {data_cvss})", impact=data_severity, ) finding.description = finding.description.strip() @@ -71,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( @@ -94,12 +92,12 @@ def parse(self, filename, test): return list(dupes.values()) -class TwistlockJsonParser(object): +class TwistlockJsonParser: 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): @@ -110,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 @@ -179,9 +178,7 @@ def get_item(vulnerability, test): duplicate=False, out_of_scope=False, mitigated=None, - severity_justification="{} (CVSS v3 base score: {})\n\n{}".format( - vector, cvss, riskFactors - ), + severity_justification=f"{vector} (CVSS v3 base score: {cvss})\n\n{riskFactors}", impact=severity, ) finding.unsaved_vulnerability_ids = [vulnerability["id"]] @@ -205,7 +202,7 @@ def convert_severity(severity): return severity.title() -class TwistlockParser(object): +class TwistlockParser: def get_scan_types(self): return ["Twistlock Image Scan"] @@ -217,11 +214,12 @@ 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) 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 da44d8b206..9c2bc3a540 100644 --- a/dojo/tools/vcg/parser.py +++ b/dojo/tools/vcg/parser.py @@ -7,7 +7,7 @@ from dojo.models import Finding -class VCGFinding(object): +class VCGFinding: def get_finding_severity(self): return self.priority_mapping[self.priority] @@ -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" @@ -57,7 +57,7 @@ def __init__(self): self.priority_mapping[7] = "Info" -class VCGXmlParser(object): +class VCGXmlParser: @staticmethod def get_field_from_xml(issue, field): if ( @@ -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 @@ -128,7 +128,7 @@ def parse(self, content, test): return dupes -class VCGCsvParser(object): +class VCGCsvParser: @staticmethod def get_field_from_row(row, column): if row[column] is not None: @@ -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='"') @@ -199,7 +199,7 @@ def __init__(self): pass -class VCGParser(object): +class VCGParser: """VCG (VisualCodeGrepper) support CSV and XML""" def get_scan_types(self): @@ -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. @@ -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/json_parser.py b/dojo/tools/veracode/json_parser.py index 3bff5a9f1d..7f2111eff0 100644 --- a/dojo/tools/veracode/json_parser.py +++ b/dojo/tools/veracode/json_parser.py @@ -1,13 +1,14 @@ 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(object): +class VeracodeJSONParser: """This parser is written for Veracode REST Findings. API endpoints to use: https://docs.veracode.com/r/c_findings_v2_examples diff --git a/dojo/tools/veracode/parser.py b/dojo/tools/veracode/parser.py index 008234f21b..ec3f5ba00d 100644 --- a/dojo/tools/veracode/parser.py +++ b/dojo/tools/veracode/parser.py @@ -2,7 +2,7 @@ from dojo.tools.veracode.xml_parser import VeracodeXMLParser -class VeracodeParser(object): +class VeracodeParser: def get_scan_types(self): return ["Veracode Scan"] @@ -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/veracode/xml_parser.py b/dojo/tools/veracode/xml_parser.py index afdead5235..ce08e14f45 100644 --- a/dojo/tools/veracode/xml_parser.py +++ b/dojo/tools/veracode/xml_parser.py @@ -1,16 +1,16 @@ 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"} -class VeracodeXMLParser(object): +class VeracodeXMLParser: """This parser is written for Veracode Detailed XML reports, version 1.5. Version is annotated in the report, `detailedreport/@report_format_version`. @@ -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( @@ -298,9 +293,7 @@ def __xml_sca_flaw_to_finding( finding.severity = cls.__xml_flaw_to_severity(xml_node) finding.unsaved_vulnerability_ids = [xml_node.attrib["cve_id"]] finding.cwe = cls._get_cwe(xml_node.attrib["cwe_id"]) - finding.title = "Vulnerable component: {0}:{1}".format( - library, version - ) + finding.title = f"Vulnerable component: {library}:{version}" finding.component_name = library finding.component_version = version @@ -310,9 +303,9 @@ def __xml_sca_flaw_to_finding( _description = "This library has known vulnerabilities.\n" _description += ( - "**CVE:** {0} ({1})\n" - "CVS Score: {2} ({3})\n" - "Summary: \n>{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..7cb730801b 100644 --- a/dojo/tools/veracode_sca/parser.py +++ b/dojo/tools/veracode_sca/parser.py @@ -1,18 +1,17 @@ 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 -class VeracodeScaParser(object): +class VeracodeScaParser: vc_severity_mapping = { 1: "Info", 2: "Low", @@ -79,8 +78,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 +188,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..4245e72f1a 100644 --- a/dojo/tools/wapiti/parser.py +++ b/dojo/tools/wapiti/parser.py @@ -1,16 +1,15 @@ -import re import hashlib import logging +import re from defusedxml.ElementTree import parse from dojo.models import Endpoint, Finding - logger = logging.getLogger(__name__) -class WapitiParser(object): +class WapitiParser: """The web-application vulnerability scanner see: https://wapiti.sourceforge.io/ @@ -31,9 +30,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", @@ -45,7 +43,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 762847b81a..dcdf42effa 100644 --- a/dojo/tools/wazuh/parser.py +++ b/dojo/tools/wazuh/parser.py @@ -1,9 +1,10 @@ import hashlib import json -from dojo.models import Finding, Endpoint +from dojo.models import Endpoint, Finding -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 @@ -25,7 +26,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/wfuzz/parser.py b/dojo/tools/wfuzz/parser.py index eb6b318669..2ac1dfbb27 100644 --- a/dojo/tools/wfuzz/parser.py +++ b/dojo/tools/wfuzz/parser.py @@ -1,11 +1,12 @@ -import json import hashlib +import json + import hyperlink -from dojo.models import Finding, Endpoint +from dojo.models import Endpoint, Finding -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 4f819a29f9..77428939ec 100644 --- a/dojo/tools/whitehat_sentinel/parser.py +++ b/dojo/tools/whitehat_sentinel/parser.py @@ -2,12 +2,13 @@ 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(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 @@ -28,7 +29,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 @@ -36,9 +37,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 @@ -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/wiz/parser.py b/dojo/tools/wiz/parser.py index bec5fee29c..722a7d2dec 100644 --- a/dojo/tools/wiz/parser.py +++ b/dojo/tools/wiz/parser.py @@ -1,10 +1,11 @@ import csv import io import sys + 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..30f523265c 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): @@ -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 791aec06ef..bed38e19f4 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"] @@ -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: @@ -35,16 +35,13 @@ 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 - ) - ) + msg = f"'{filename}' is not a valid Xanitizer findings list report XML file." + raise ValueError(msg) return root def get_findings_internal(self, root, test): - items = list() + items = [] globalDate = root.get("timeStamp", default=None) if globalDate is not None: @@ -90,14 +87,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 +106,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 +117,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 +139,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..ff26ba37b4 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"] @@ -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): @@ -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) @@ -39,11 +43,43 @@ 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_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"): @@ -85,7 +121,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 +133,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 = [] + 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) @@ -169,7 +208,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 old mode 100755 new mode 100644 index f7411daea2..f8e983f152 --- 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"} @@ -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/urls.py b/dojo/urls.py old mode 100755 new mode 100644 index 4500e1e49d..b9d9493c66 --- 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() @@ -81,7 +126,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) @@ -166,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'): @@ -188,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 @@ -206,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: @@ -216,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/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 c3eee9cfbe..b84f171797 100644 --- a/dojo/user/validators.py +++ b/dojo/user/validators.py @@ -1,12 +1,13 @@ 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 -class MinLengthValidator(object): +class MinLengthValidator: def validate(self, password, user=None): if len(password) < get_system_setting('minimum_password_length'): raise ValidationError( @@ -20,7 +21,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 +35,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 +48,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 +61,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 +74,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/user/views.py b/dojo/user/views.py index 7e3d41938b..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__) @@ -617,7 +627,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 +654,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 1c9e56fbcc..f5605b9dba 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") @@ -136,7 +157,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 @@ -252,7 +274,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 @@ -486,13 +508,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 @@ -786,8 +812,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 +896,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 +991,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( @@ -1174,7 +1200,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 @@ -1228,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 @@ -1288,23 +1314,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() @@ -1360,7 +1384,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() @@ -1376,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) @@ -1514,8 +1538,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() @@ -1562,7 +1585,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 @@ -1755,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) @@ -1789,7 +1811,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): @@ -1855,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" @@ -1897,7 +1920,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', @@ -1921,20 +1944,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: @@ -1967,7 +1984,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 @@ -1981,29 +1998,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') @@ -2012,23 +2026,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.") @@ -2044,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 = [] @@ -2087,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: @@ -2113,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) @@ -2169,7 +2178,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) @@ -2214,7 +2224,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): @@ -2267,7 +2277,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 @@ -2277,7 +2287,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 old mode 100755 new mode 100644 index 829f749d64..db90c1f944 --- 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__) @@ -216,8 +221,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/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 49ae1d27be..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__) @@ -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/helm/defectdojo/Chart.lock b/helm/defectdojo/Chart.lock index a85360d454..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.1.4 + 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.0.1 -digest: sha256:7c38007c50dd3fddea2d065cf57848cf9ef65f6a3b9fc1ec6bf508214429704b -generated: "2024-03-25T19:30:19.499072006Z" + 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 c405d96054..0dc02c38db 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" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.125 +version: 1.6.126 icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap @@ -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 @@ -23,10 +23,10 @@ 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 - version: ~19.0.0 + version: ~19.1.0 repository: "https://charts.bitnami.com/bitnami" condition: redis.enabled 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 }} diff --git a/helm/defectdojo/values.yaml b/helm/defectdojo/values.yaml index 0591e45ca1..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: "" @@ -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: "" 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/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/requirements-lint.txt b/requirements-lint.txt index a35983113e..ace8ae4ab0 100644 --- a/requirements-lint.txt +++ b/requirements-lint.txt @@ -1 +1 @@ -ruff==0.3.5 \ No newline at end of file +ruff==0.4.3 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 53e3f07cd9..547bd7aa83 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,9 @@ # 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 -coverage==7.4.1 +celery==5.4.0 +coverage==7.5.1 defusedxml==0.7.1 django_celery_results==2.5.1 django-auditlog==2.3.0 @@ -26,56 +26,56 @@ 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.6.0 +jira==3.8.0 PyGithub==1.58.2 -lxml==5.1.0 -Markdown==3.5.2 +lxml==5.2.1 +Markdown==3.6 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 +cryptography==42.0.5 +python-dateutil==2.9.0.post0 pytz==2024.1 -redis==5.0.1 +redis==5.0.4 requests==2.31.0 -sqlalchemy==2.0.25 # Required by Celery broker transport +sqlalchemy==2.0.30 # Required by Celery broker transport urllib3==1.26.18 -uWSGI==2.0.23 -vobject==0.9.6.1 +uWSGI==2.0.25.1 +vobject==0.9.7 whitenoise==5.2.0 titlecase==2.4.1 social-auth-app-django==5.4.1 -social-auth-core==4.5.2 +social-auth-core==4.5.4 Python-jose==3.3.0 -gitpython==3.1.41 -debugpy==1.8.0 +gitpython==3.1.43 +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==0.5.2 -django-split-settings==1.2.0 +JSON-log-formatter==1.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 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 -djangosaml2==1.9.1 -drf-spectacular==0.27.1 -drf-spectacular-sidecar==2024.3.4 +djangosaml2==1.9.2 +drf-spectacular==0.27.2 +drf-spectacular-sidecar==2024.5.1 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 -netaddr==0.10.1 +blackduck==1.1.3 +pycurl==7.45.3 # 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 diff --git a/ruff.toml b/ruff.toml index b9e647656c..20593fa239 100644 --- a/ruff.toml +++ b/ruff.toml @@ -31,13 +31,35 @@ 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", + "I", + "UP", + "YTT", + "ASYNC", + "EXE", + "TRIO", + "C4", + "DJ003", "DJ012", "DJ013", + "EM", + "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 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 05658982e2..5206be7ffd 100644 --- a/tests/announcement_banner_test.py +++ b/tests/announcement_banner_test.py @@ -1,17 +1,17 @@ -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): 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..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 @@ -464,7 +465,7 @@ def tearDownDriver(cls): dd_driver.quit() -class WebdriverOnlyNewLogFacade(object): +class WebdriverOnlyNewLogFacade: last_timestamp = 0 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 4c82f3e3ac..d6f0b46382 100644 --- a/tests/notifications_test.py +++ b/tests/notifications_test.py @@ -1,25 +1,25 @@ -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): 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_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 b50ce7395b..79ac3ac3c7 100644 --- a/tests/product_test.py +++ b/tests/product_test.py @@ -1,14 +1,15 @@ -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(object): +class WaitForPageLoad: def __init__(self, browser, timeout): self.browser = browser self.timeout = time.time() + timeout @@ -26,9 +27,8 @@ def __exit__(self, *_): return True else: time.sleep(0.2) - raise Exception( - 'Timeout waiting for {}s'.format(self.timeout) - ) + msg = f'Timeout waiting for {self.timeout}s' + raise Exception(msg) class ProductTest(BaseTestCase): 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 18a5d7b6f8..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: @@ -14,12 +15,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 +36,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 +59,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/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 62c9f46546..656ed87124 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__) @@ -27,7 +41,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') @@ -67,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 @@ -91,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 @@ -99,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 @@ -377,7 +391,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): @@ -461,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) @@ -470,122 +484,126 @@ 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') + response = self.client.get(reverse('finding-list') + f'{finding_id}/', format='json') self.assertEqual(200, response.status_code, response.content[:1000]) return response.data @@ -605,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 @@ -619,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 @@ -681,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/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/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/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/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/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/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/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. <br><br>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:<ul><li>ELBSecurityPolicy-2016-08</li><li>ELBSecurityPolicy-FS-2018-06</li><li>ELBSecurityPolicy-TLS-1-1-2017-01</li><li>ELBSecurityPolicy-TLS-1-2-2017-01</li><li>ELBSecurityPolicy-TLS-1-2-Ext-2018-06</li><li>ELBSecurityPolicy-FS-1-1-2019-08</li><li>ELBSecurityPolicy-FS-1-2-2019-08</li><li>ELBSecurityPolicy-FS-1-2-Res-2019-08</li></ul>","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.<br><br>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:<ul><li>ELBSecurityPolicy-2016-08</li><li>ELBSecurityPolicy-FS-2018-06</li><li>ELBSecurityPolicy-TLS-1-1-2017-01</li><li>ELBSecurityPolicy-TLS-1-2-2017-01</li><li>ELBSecurityPolicy-TLS-1-2-Ext-2018-06</li><li>ELBSecurityPolicy-FS-1-1-2019-08</li><li>ELBSecurityPolicy-FS-1-2-2019-08</li><li>ELBSecurityPolicy-FS-1-2-Res-2019-08</li></ul>","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": "<root_account>","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": "<root_account>","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 <samp>Effect: Allow</samp>, <samp>Action: *</samp> and <samp>Resource: *</samp>","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.<br><br>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.<br><br>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.<br><br><b>Note</b> 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.<br><br><b>Note</b> 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. <br><br>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. <br><br>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:<ul><li>ELBSecurityPolicy-2016-08</li><li>ELBSecurityPolicy-FS-2018-06</li><li>ELBSecurityPolicy-TLS-1-1-2017-01</li><li>ELBSecurityPolicy-TLS-1-2-2017-01</li><li>ELBSecurityPolicy-TLS-1-2-Ext-2018-06</li><li>ELBSecurityPolicy-FS-1-1-2019-08</li><li>ELBSecurityPolicy-FS-1-2-2019-08</li><li>ELBSecurityPolicy-FS-1-2-Res-2019-08</li></ul>", + "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.<br><br>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:<ul><li>ELBSecurityPolicy-2016-08</li><li>ELBSecurityPolicy-FS-2018-06</li><li>ELBSecurityPolicy-TLS-1-1-2017-01</li><li>ELBSecurityPolicy-TLS-1-2-2017-01</li><li>ELBSecurityPolicy-TLS-1-2-Ext-2018-06</li><li>ELBSecurityPolicy-FS-1-1-2019-08</li><li>ELBSecurityPolicy-FS-1-2-2019-08</li><li>ELBSecurityPolicy-FS-1-2-Res-2019-08</li></ul>", + "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": "<root_account>", + "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": "<root_account>", + "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 <samp>Effect: Allow</samp>, <samp>Action: *</samp> and <samp>Resource: *</samp>", + "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.<br><br>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.<br><br>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.<br><br><b>Note</b> 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.<br><br><b>Note</b> 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. <br><br>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.<br><br><b>Note: </b>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.<br><br><b>Note: </b>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.<br><br><b>Note: </b>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.<br><br><b>Note: </b>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.<br><br><b>Note: </b>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.<br><br><b>Note: </b>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.<br><br><b>Note: </b>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.<br><br><b>Note: </b>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 diff --git a/unittests/scans/sonarqube/empty_zip.zip b/unittests/scans/sonarqube/empty_zip.zip new file mode 100644 index 0000000000..c82ad8319b Binary files /dev/null and b/unittests/scans/sonarqube/empty_zip.zip differ 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 0000000000..92a82faf5a Binary files /dev/null and b/unittests/scans/sonarqube/findings_over_api.zip differ 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/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/test_adminsite.py b/unittests/test_adminsite.py index bc48a7ea45..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): @@ -13,7 +14,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_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 new file mode 100644 index 0000000000..06e5ad2f4c --- /dev/null +++ b/unittests/test_apiv2_limit_reqresp.py @@ -0,0 +1,42 @@ +from django.conf import settings +from django.urls import reverse +from rest_framework.authtoken.models import Token +from rest_framework.test import APIClient, APITestCase + + +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 diff --git a/unittests/test_apiv2_metadata.py b/unittests/test_apiv2_metadata.py index 6da260ec32..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): @@ -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_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 6e62f460d9..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): @@ -16,6 +17,9 @@ class ScanImportOptionsTest(APITestCase): </OWASPZAPReport> """ + def __del__(self): + self.payload['file'].close() + def setUp(self): token = Token.objects.get(user__username='admin') self.client = APIClient() @@ -26,19 +30,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_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 aab724f54a..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: @@ -91,7 +88,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 +97,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 f19ccb9602..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): @@ -39,29 +50,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))) + 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, 'CVE-1999-{}'.format(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, 'CVE-1999-{}'.format(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, 'CVE-2000-{}'.format(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, 'CVE-1999-{}'.format(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) @@ -70,7 +81,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 +94,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 +105,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_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 86d05f67c7..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") @@ -1158,12 +1161,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_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 e0ec437c42..a639999f16 100644 --- a/unittests/test_endpoint_meta_import.py +++ b/unittests/test_endpoint_meta_import.py @@ -1,18 +1,20 @@ +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__) # 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' @@ -204,11 +206,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_endpoint_model.py b/unittests/test_endpoint_model.py index 71535e0732..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): @@ -37,7 +38,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_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 853737850f..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") @@ -1675,12 +1678,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 +1737,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 +1749,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_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..9ab6936504 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): @@ -211,6 +214,53 @@ def test_get_file_path_with_link_and_source_code_management_uri_bitbucket_standa self.assertEqual('<a href=\"https://bb.example.com/users/some-user/repos/some-test-repo/browse/some-folder/some-file.ext?at=some-branch#5432" target=\"_blank\" title=\"some-folder/some-file.ext\">some-folder/some-file.ext</a>', 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('<a href=\"https://bb.example.com/some-test-user/some-test-repo/src/master/some-folder/some-file.ext#L5432" target=\"_blank\" title=\"some-folder/some-file.ext\">some-folder/some-file.ext</a>', 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('<a href=\"https://bb.example.com/some-test-user/some-test-repo/src/some-commit-hash/some-folder/some-file.ext#L5432" target=\"_blank\" title=\"some-folder/some-file.ext\">some-folder/some-file.ext</a>', finding.get_file_path_with_link()) + def test_get_file_path_with_xss_attack(self): test = Test() engagement = Engagement() 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 535bc488d1..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__) @@ -50,7 +52,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/' @@ -1786,33 +1788,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 +1828,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..fb9d46ce5d 100644 --- a/unittests/test_importers_closeold.py +++ b/unittests/test_importers_closeold.py @@ -1,75 +1,73 @@ -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.importers.default_importer import DefaultImporter 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__) 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 - 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(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 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, @@ -88,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 - 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(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 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 096539b292..40caea86f9 100644 --- a/unittests/test_importers_importer.py +++ b/unittests/test_importers_importer.py @@ -1,21 +1,19 @@ -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.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.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__) @@ -41,121 +39,114 @@ 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: + 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, _created = Engagement.objects.get_or_create( + 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") + import_options = { + "user": user, + "lead": lead, + "scan_date": None, + "environment": environment, + "minimum_severity": "Info", + "active": True, + "verified": True, + "sync": True, + } + # create the test + # by default test_type == scan_type + test = importer.create_test(scan_type, scan_type, engagement=engagement, **import_options) + # parse the findings + parser = importer.get_parser(scan_type) + parsed_findings = parser.get_findings(scan, test) + # process + new_findings = importer.process_findings( + test, + parsed_findings, + **import_options, + ) + 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: + importer = DefaultImporter() + scan_type = SarifParser().get_scan_types()[0] # SARIF format implement the new method + user, _ = User.objects.get_or_create(username="admin") + 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(), + ) + environment, _ = Development_Environment.objects.get_or_create(name="Development") + 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 - 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: + 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") + 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(), + ) + environment, _ = Development_Environment.objects.get_or_create(name="Development") + 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) class FlexibleImportTestAPI(DojoAPITestCase): @@ -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, ["Product '%s' doesn't exist in Product_Type '%s'" % (PRODUCT_NAME_DEFAULT, 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, ["Engagement 'Engagement 1' doesn't exist in Product '%s'" % 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, ["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}" 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, ["Product '%s' doesn't exist in Product_Type '%s'" % (PRODUCT_NAME_DEFAULT, 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, ["Engagement 'Engagement 1' doesn't exist in Product '%s'" % 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, ["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}" 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_jira_config_engagement.py b/unittests/test_jira_config_engagement.py index 9506a264f6..cf952b6068 100644 --- a/unittests/test_jira_config_engagement.py +++ b/unittests/test_jira_config_engagement.py @@ -1,17 +1,21 @@ +# 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__) -class JIRAConfigEngagementBase(object): +class JIRAConfigEngagementBase: def get_new_engagement_with_jira_project_data(self): return { 'name': 'new engagement', 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 dd50794c0a..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__) @@ -44,7 +46,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_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 462843f2c6..cad7106cfb 100644 --- a/unittests/test_notifications.py +++ b/unittests/test_notifications.py @@ -1,5 +1,9 @@ +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 -from dojo.models import Product, User, Notifications class TestNotifications(DojoTestCase): @@ -55,3 +59,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 diff --git a/unittests/test_parsers.py b/unittests/test_parsers.py index ac2b75730c..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(), '..') @@ -29,20 +30,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 +81,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, "r").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_remote_user.py b/unittests/test_remote_user.py index 5d09cac922..c039e006db 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 @@ -198,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, {}) diff --git a/unittests/test_rest_framework.py b/unittests/test_rest_framework.py index 9e458c02b6..0427ceb1d9 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__) @@ -61,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() @@ -86,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 @@ -111,7 +193,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 +354,7 @@ class TestType(Enum): CONFIGURATION_PERMISSIONS = 3 -class BaseClass(): +class BaseClass: class RESTEndpointTest(DojoAPITestCase): def __init__(self, *args, **kwargs): DojoAPITestCase.__init__(self, *args, **kwargs) @@ -301,10 +383,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 @@ -376,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 @@ -390,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]) @@ -435,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') @@ -467,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) }) @@ -555,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]) @@ -582,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: @@ -605,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']) @@ -644,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]) @@ -666,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]) @@ -678,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]) @@ -692,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]) @@ -710,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]) @@ -740,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]) @@ -837,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]) @@ -858,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]) @@ -991,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]) @@ -1041,17 +1123,19 @@ 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', 'r') - } - 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', '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}/') @@ -1130,7 +1214,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/") @@ -1700,12 +1784,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,128 +1801,135 @@ def __init__(self, *args, **kwargs): self.permission_create = Permissions.Import_Scan_Result BaseClass.RESTEndpointTest.__init__(self, *args, **kwargs) - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + def __del__(self: object): + self.payload['file'].close() + + @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 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() - - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + 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.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 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() - - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + 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.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 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() - - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + 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.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 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') + @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): """ @@ -1846,93 +1939,95 @@ 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 - } - - 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() + 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 + } - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + 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.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 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') + @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 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): @@ -1947,89 +2042,92 @@ 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 - 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') + @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 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() - - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + 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.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 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() - - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + 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.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): """ @@ -2039,266 +2137,275 @@ 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 - } - - 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() + 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 + } - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + 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.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 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() - - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + 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.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 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') + @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 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 - @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 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() - - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + 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.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 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() - - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + 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.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 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') + @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 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() - - @patch('dojo.importers.reimporter.reimporter.DojoDefaultReImporter.reimport_scan') - @patch('dojo.importers.importer.importer.DojoDefaultImporter.import_scan') + 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.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 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): @@ -2373,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]) @@ -2618,6 +2725,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) @@ -2706,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]) 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 30b4721621..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__) @@ -162,7 +178,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/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 eedf73b159..bd94c2ac70 100644 --- a/unittests/tools/test_acunetix_parser.py +++ b/unittests/tools/test_acunetix_parser.py @@ -1,172 +1,202 @@ 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): 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 +204,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..29946312a8 100644 --- a/unittests/tools/test_anchore_engine_parser.py +++ b/unittests/tools/test_anchore_engine_parser.py @@ -1,39 +1,37 @@ -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): 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_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 668035b68c..0b41180de1 100644 --- a/unittests/tools/test_anchore_grype_parser.py +++ b/unittests/tools/test_anchore_grype_parser.py @@ -1,131 +1,125 @@ -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): 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..87968ea792 100644 --- a/unittests/tools/test_anchorectl_policies_parser.py +++ b/unittests/tools/test_anchorectl_policies_parser.py @@ -1,29 +1,28 @@ -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): 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..40295ec027 100644 --- a/unittests/tools/test_anchorectl_vulns_parser.py +++ b/unittests/tools/test_anchorectl_vulns_parser.py @@ -1,29 +1,28 @@ -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): 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..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 @@ -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_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 f9c8ad64fb..956bce388a 100644 --- a/unittests/tools/test_api_cobalt_parser.py +++ b/unittests/tools/test_api_cobalt_parser.py @@ -1,282 +1,271 @@ 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): 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_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 ed64677270..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): @@ -62,7 +64,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..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): @@ -31,7 +40,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_api_vulners_parser.py b/unittests/tools/test_api_vulners_parser.py index 0f58c604f4..ea370389ba 100644 --- a/unittests/tools/test_api_vulners_parser.py +++ b/unittests/tools/test_api_vulners_parser.py @@ -1,49 +1,50 @@ -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): 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_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 ad2ea81781..89f16334fa 100644 --- a/unittests/tools/test_aqua_parser.py +++ b/unittests/tools/test_aqua_parser.py @@ -1,40 +1,40 @@ -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): - 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: @@ -81,7 +81,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_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 bcbe7bb56b..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 @@ -12,7 +14,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 +37,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 +45,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 +54,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_auditjs_parser.py b/unittests/tools/test_auditjs_parser.py index 8d012aec61..629a6c9012 100644 --- a/unittests/tools/test_auditjs_parser.py +++ b/unittests/tools/test_auditjs_parser.py @@ -1,79 +1,77 @@ -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): 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_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 deleted file mode 100644 index 4309554346..0000000000 --- a/unittests/tools/test_aws_scout2_parser.py +++ /dev/null @@ -1,46 +0,0 @@ -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 - - -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) diff --git a/unittests/tools/test_awssecurityhub_parser.py b/unittests/tools/test_awssecurityhub_parser.py index 5f3621a609..3734f2e440 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): @@ -39,6 +40,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 +123,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) diff --git a/unittests/tools/test_azure_security_center_recommendations_parser.py b/unittests/tools/test_azure_security_center_recommendations_parser.py index 3f4a4c4a97..5ce988dfed 100644 --- a/unittests/tools/test_azure_security_center_recommendations_parser.py +++ b/unittests/tools/test_azure_security_center_recommendations_parser.py @@ -1,30 +1,32 @@ 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): 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 +34,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 +58,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 +82,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..f52a318738 100644 --- a/unittests/tools/test_bandit_parser.py +++ b/unittests/tools/test_bandit_parser.py @@ -1,105 +1,103 @@ 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): - 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_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 c6510f9ac2..c8e3f195b6 100644 --- a/unittests/tools/test_brakeman_parser.py +++ b/unittests/tools/test_brakeman_parser.py @@ -1,26 +1,25 @@ -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): 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..f21451e7c2 100644 --- a/unittests/tools/test_bugcrowd_parser.py +++ b/unittests/tools/test_bugcrowd_parser.py @@ -1,35 +1,37 @@ -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): 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_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 b180dc82ca..5a1bb6aceb 100644 --- a/unittests/tools/test_cargo_audit_parser.py +++ b/unittests/tools/test_cargo_audit_parser.py @@ -1,78 +1,79 @@ -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): 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_one_parser.py b/unittests/tools/test_checkmarx_one_parser.py index 4cda49a26e..74a112a9ec 100644 --- a/unittests/tools/test_checkmarx_one_parser.py +++ b/unittests/tools/test_checkmarx_one_parser.py @@ -1,5 +1,8 @@ +import datetime + from dojo.models import Test from dojo.tools.checkmarx_one.parser import CheckmarxOneParser + from ..dojo_test_case import DojoTestCase @@ -62,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) diff --git a/unittests/tools/test_checkmarx_osa_parser.py b/unittests/tools/test_checkmarx_osa_parser.py index 5fbf474ce2..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): @@ -185,9 +186,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..ef9f67dc1c 100644 --- a/unittests/tools/test_checkov_parser.py +++ b/unittests/tools/test_checkov_parser.py @@ -1,90 +1,91 @@ -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): 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..9455020257 100644 --- a/unittests/tools/test_chefinspect_parser.py +++ b/unittests/tools/test_chefinspect_parser.py @@ -1,24 +1,25 @@ -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): 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_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 a32929f888..d3bca067c1 100644 --- a/unittests/tools/test_cobalt_parser.py +++ b/unittests/tools/test_cobalt_parser.py @@ -1,25 +1,26 @@ -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): 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..fb118215c7 100644 --- a/unittests/tools/test_codechecker_parser.py +++ b/unittests/tools/test_codechecker_parser.py @@ -1,99 +1,100 @@ -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): 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..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): @@ -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..8a480a230d 100644 --- a/unittests/tools/test_coverity_api_parser.py +++ b/unittests/tools/test_coverity_api_parser.py @@ -1,98 +1,99 @@ 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): 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_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 2095af6941..c8aebcbdca 100644 --- a/unittests/tools/test_cred_scan_parser.py +++ b/unittests/tools/test_cred_scan_parser.py @@ -1,30 +1,32 @@ -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): 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..3f203bd3c5 100644 --- a/unittests/tools/test_crunch42_parser.py +++ b/unittests/tools/test_crunch42_parser.py @@ -1,32 +1,31 @@ -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): 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_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 7963acdcd7..c6a26d1e78 100644 --- a/unittests/tools/test_dependency_check_parser.py +++ b/unittests/tools/test_dependency_check_parser.py @@ -1,14 +1,15 @@ 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 from ..dojo_test_case import DojoTestCase -class TestFile(object): +class TestFile: def read(self): return self.content @@ -19,236 +20,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 +272,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..f2783229d9 100644 --- a/unittests/tools/test_dependency_track_parser.py +++ b/unittests/tools/test_dependency_track_parser.py @@ -1,101 +1,92 @@ -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): - 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)) - - 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]) + ) 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]) 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..0c11f06b8f 100644 --- a/unittests/tools/test_detect_secrets_parser.py +++ b/unittests/tools/test_detect_secrets_parser.py @@ -1,72 +1,75 @@ 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): 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..6a52066172 100644 --- a/unittests/tools/test_dockerbench_parser.py +++ b/unittests/tools/test_dockerbench_parser.py @@ -1,66 +1,65 @@ -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): 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..5baed6455c 100644 --- a/unittests/tools/test_dockle_parser.py +++ b/unittests/tools/test_dockle_parser.py @@ -1,48 +1,49 @@ -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): 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 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=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 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=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) 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 a266f9a255..d4ffd6ff5f 100644 --- a/unittests/tools/test_dsop_parser.py +++ b/unittests/tools/test_dsop_parser.py @@ -1,22 +1,22 @@ -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): 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_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 c0db182c2d..52140f66a5 100644 --- a/unittests/tools/test_fortify_parser.py +++ b/unittests/tools/test_fortify_parser.py @@ -1,89 +1,90 @@ from dojo.models import Test from dojo.tools.fortify.parser import FortifyParser + from ..dojo_test_case import DojoTestCase 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_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 de4b8252ec..5951f9a413 100644 --- a/unittests/tools/test_generic_parser.py +++ b/unittests/tools/test_generic_parser.py @@ -1,10 +1,12 @@ 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(object): +class TestFile: def read(self): return self.content @@ -24,24 +26,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 +435,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)) + self.assertEqual("localhost", endpoint.host) - endpoint = finding.unsaved_endpoints[0] - endpoint.clean() - self.assertEqual("www.example.com", 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 old mode 100755 new mode 100644 index 99c0ddd9d2..c95a70b8d0 --- a/unittests/tools/test_ggshield_parser.py +++ b/unittests/tools/test_ggshield_parser.py @@ -1,42 +1,40 @@ -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): 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..cff3956675 100644 --- a/unittests/tools/test_github_vulnerability_parser.py +++ b/unittests/tools/test_github_vulnerability_parser.py @@ -2,279 +2,280 @@ 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): """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_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 353f7e73db..7d778adc40 100644 --- a/unittests/tools/test_gitlab_dast_parser.py +++ b/unittests/tools/test_gitlab_dast_parser.py @@ -1,143 +1,144 @@ -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): 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..7601438490 100644 --- a/unittests/tools/test_gitlab_dep_scan_parser.py +++ b/unittests/tools/test_gitlab_dep_scan_parser.py @@ -1,80 +1,67 @@ -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): 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_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 0c8f84138a..f3ba72907b 100644 --- a/unittests/tools/test_gitleaks_parser.py +++ b/unittests/tools/test_gitleaks_parser.py @@ -1,115 +1,116 @@ -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): 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 +122,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..a4274301da 100644 --- a/unittests/tools/test_gosec_parser.py +++ b/unittests/tools/test_gosec_parser.py @@ -1,16 +1,17 @@ -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): 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..f90a699fb1 100644 --- a/unittests/tools/test_govulncheck_parser.py +++ b/unittests/tools/test_govulncheck_parser.py @@ -1,132 +1,129 @@ -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): 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..d216c0498e 100644 --- a/unittests/tools/test_h1_parser.py +++ b/unittests/tools/test_h1_parser.py @@ -1,24 +1,25 @@ -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): 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_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 5f1048e1e4..6a947d2d84 100644 --- a/unittests/tools/test_harbor_vulnerability_parser.py +++ b/unittests/tools/test_harbor_vulnerability_parser.py @@ -1,67 +1,68 @@ -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): 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_hcl_appscan_parser.py b/unittests/tools/test_hcl_appscan_parser.py index daaf04f4a5..ee33da0046 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): @@ -37,3 +38,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") 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 ccd99d4437..2b0a85a2ca 100644 --- a/unittests/tools/test_humble_parser.py +++ b/unittests/tools/test_humble_parser.py @@ -1,36 +1,34 @@ -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 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..76aad5a15c 100644 --- a/unittests/tools/test_huskyci_parser.py +++ b/unittests/tools/test_huskyci_parser.py @@ -1,39 +1,37 @@ -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): 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..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 @@ -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_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 74b9e12d23..ed79494c67 100644 --- a/unittests/tools/test_immuniweb_parser.py +++ b/unittests/tools/test_immuniweb_parser.py @@ -1,30 +1,31 @@ -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): 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..7afd0e33dd 100644 --- a/unittests/tools/test_intsights_parser.py +++ b/unittests/tools/test_intsights_parser.py @@ -1,79 +1,73 @@ -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( 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_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 608f92f15a..3e814dc87f 100644 --- a/unittests/tools/test_kics_parser.py +++ b/unittests/tools/test_kics_parser.py @@ -1,197 +1,198 @@ -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): 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..0d8a458719 100644 --- a/unittests/tools/test_kiuwan_parser.py +++ b/unittests/tools/test_kiuwan_parser.py @@ -1,36 +1,37 @@ -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): 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_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 0494e92ff3..e0c7b6181a 100644 --- a/unittests/tools/test_kubebench_parser.py +++ b/unittests/tools/test_kubebench_parser.py @@ -1,60 +1,61 @@ -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): 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..6912df0380 100644 --- a/unittests/tools/test_kubehunter_parser.py +++ b/unittests/tools/test_kubehunter_parser.py @@ -1,55 +1,51 @@ 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): 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..bccbed220a 100644 --- a/unittests/tools/test_kubescape_parser.py +++ b/unittests/tools/test_kubescape_parser.py @@ -1,32 +1,24 @@ -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): 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..d30a35752a 100644 --- a/unittests/tools/test_mend_parser.py +++ b/unittests/tools/test_mend_parser.py @@ -1,37 +1,38 @@ -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): 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..728c669020 100644 --- a/unittests/tools/test_meterian_parser.py +++ b/unittests/tools/test_meterian_parser.py @@ -1,94 +1,83 @@ -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): 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..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): @@ -9,58 +10,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 +74,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_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 76e805852a..038bc09091 100644 --- a/unittests/tools/test_mobsfscan_parser.py +++ b/unittests/tools/test_mobsfscan_parser.py @@ -1,157 +1,155 @@ -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): 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..147eff5f2b 100644 --- a/unittests/tools/test_mozilla_observatory_parser.py +++ b/unittests/tools/test_mozilla_observatory_parser.py @@ -1,237 +1,238 @@ -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): - 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_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 55a8f36329..5918f12ce9 100644 --- a/unittests/tools/test_nancy_parser.py +++ b/unittests/tools/test_nancy_parser.py @@ -1,38 +1,39 @@ 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): 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("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..cf8b9837b8 100644 --- a/unittests/tools/test_netsparker_parser.py +++ b/unittests/tools/test_netsparker_parser.py @@ -1,84 +1,85 @@ -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): 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_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 41b9ddffdf..7b5afc112e 100644 --- a/unittests/tools/test_nexpose_parser.py +++ b/unittests/tools/test_nexpose_parser.py @@ -1,223 +1,224 @@ 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): 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..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): @@ -10,178 +11,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..a78474d89a 100644 --- a/unittests/tools/test_nmap_parser.py +++ b/unittests/tools/test_nmap_parser.py @@ -1,133 +1,134 @@ 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): 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..4e98bbc04f 100644 --- a/unittests/tools/test_noseyparker_parser.py +++ b/unittests/tools/test_noseyparker_parser.py @@ -1,47 +1,45 @@ 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): 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_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 c1c23d306a..fac2473b51 100644 --- a/unittests/tools/test_npm_audit_parser.py +++ b/unittests/tools/test_npm_audit_parser.py @@ -1,88 +1,84 @@ 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): 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)) - - 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) + 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) 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 +91,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_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 432960dfb9..2ffde1fb02 100644 --- a/unittests/tools/test_nuclei_parser.py +++ b/unittests/tools/test_nuclei_parser.py @@ -1,240 +1,239 @@ -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): 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_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 f31b6e7727..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): @@ -80,7 +81,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_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 af7dac0050..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): @@ -19,7 +21,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 +32,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) 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 fa1f911a07..e876d2c700 100644 --- a/unittests/tools/test_pmd_parser.py +++ b/unittests/tools/test_pmd_parser.py @@ -1,26 +1,27 @@ -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): 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_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_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)) diff --git a/unittests/tools/test_pwn_sast_parser.py b/unittests/tools/test_pwn_sast_parser.py index 4c1a2e2e24..e24bdaaca3 100644 --- a/unittests/tools/test_pwn_sast_parser.py +++ b/unittests/tools/test_pwn_sast_parser.py @@ -1,42 +1,43 @@ -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): 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..9605e814c3 100644 --- a/unittests/tools/test_qualys_infrascan_webgui_parser.py +++ b/unittests/tools/test_qualys_infrascan_webgui_parser.py @@ -1,80 +1,80 @@ 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): 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..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): @@ -16,12 +18,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 +35,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 +82,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 +99,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_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 b1c2771bcf..da1175a8df 100644 --- a/unittests/tools/test_redhatsatellite_parser.py +++ b/unittests/tools/test_redhatsatellite_parser.py @@ -1,27 +1,35 @@ -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): 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]) + + 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]) diff --git a/unittests/tools/test_retirejs_parser.py b/unittests/tools/test_retirejs_parser.py index 4961b93bac..2802d3667a 100644 --- a/unittests/tools/test_retirejs_parser.py +++ b/unittests/tools/test_retirejs_parser.py @@ -1,42 +1,43 @@ -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): - 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..839c6cf80d 100644 --- a/unittests/tools/test_risk_recon_parser.py +++ b/unittests/tools/test_risk_recon_parser.py @@ -1,34 +1,35 @@ 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): 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_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 4cf17c7da6..472e15b822 100644 --- a/unittests/tools/test_rusty_hog_parser.py +++ b/unittests/tools/test_rusty_hog_parser.py @@ -1,122 +1,123 @@ -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): 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..dcc4d41e23 100644 --- a/unittests/tools/test_sarif_parser.py +++ b/unittests/tools/test_sarif_parser.py @@ -17,43 +17,45 @@ 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;``` +``` +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:** @@ -62,274 +64,276 @@ 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\",```""" +``` + \"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", @@ -342,7 +346,9 @@ def test_gitleaks(self): self.assertEqual("Medium", finding.severity) description = """**Result message:** AWS Access Key secret detected **Snippet:** -``` \"raw_source_code_extract\": \"AKIAIOSFODNN7EXAMPLE\",```""" +``` + \"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", @@ -355,197 +361,213 @@ def test_gitleaks(self): self.assertEqual("Medium", finding.severity) description = """**Result message:** AWS Access Key secret detected **Snippet:** -``` self.assertEqual(\"AWS\\nAKIAIOSFODNN7EXAMPLE\", first_finding.description)```""" +``` + 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): - 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);``` +``` + 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);``` +``` + 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) {``` +``` + 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);``` +``` + 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);``` +``` + 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) {``` +``` + 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('/')) 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 **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 +585,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..befdf404c8 100644 --- a/unittests/tools/test_scantist_parser.py +++ b/unittests/tools/test_scantist_parser.py @@ -1,39 +1,40 @@ -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): 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..40e6761f84 100644 --- a/unittests/tools/test_scout_suite_parser.py +++ b/unittests/tools/test_scout_suite_parser.py @@ -1,88 +1,89 @@ 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): - 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..27a6d1b755 100644 --- a/unittests/tools/test_semgrep_parser.py +++ b/unittests/tools/test_semgrep_parser.py @@ -1,142 +1,134 @@ -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): 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..b39ac83257 100644 --- a/unittests/tools/test_skf_parser.py +++ b/unittests/tools/test_skf_parser.py @@ -1,16 +1,17 @@ -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): 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_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 04e048a633..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 @@ -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,3 +561,92 @@ 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( + 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.unsaved_vulnerability_ids[0]) + 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.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.unsaved_vulnerability_ids[0]) + item = findings[4] + 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( + 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) + my_file_handle.close() + + 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)) + my_file_handle.close() + + 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)) + my_file_handle.close() + + 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) + my_file_handle.close() 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 ff98db715e..b105ebb20a 100644 --- a/unittests/tools/test_spotbugs_parser.py +++ b/unittests/tools/test_spotbugs_parser.py @@ -1,10 +1,10 @@ -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): - def test_no_findings(self): parser = SpotbugsParser() findings = parser.get_findings(get_unit_tests_path() + "/scans/spotbugs/no_finding.xml", Test()) @@ -76,19 +76,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 +93,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): diff --git a/unittests/tools/test_ssh_audit_parser.py b/unittests/tools/test_ssh_audit_parser.py index a7bbf22256..a29d36c1a9 100644 --- a/unittests/tools/test_ssh_audit_parser.py +++ b/unittests/tools/test_ssh_audit_parser.py @@ -1,44 +1,45 @@ -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): 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_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 b9d518fe7f..b685178247 100644 --- a/unittests/tools/test_sslscan_parser.py +++ b/unittests/tools/test_sslscan_parser.py @@ -1,30 +1,31 @@ -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): 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..4493d4d180 100644 --- a/unittests/tools/test_sslyze_parser.py +++ b/unittests/tools/test_sslyze_parser.py @@ -1,80 +1,81 @@ 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): 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 +92,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 +131,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..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 @@ -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..00979f66e8 100644 --- a/unittests/tools/test_sysdig_reports_parser.py +++ b/unittests/tools/test_sysdig_reports_parser.py @@ -1,72 +1,67 @@ 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): 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 b79c48c3d7..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): @@ -12,289 +14,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"), "rt") - 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..4fa717fccd 100644 --- a/unittests/tools/test_terrascan_parser.py +++ b/unittests/tools/test_terrascan_parser.py @@ -1,117 +1,118 @@ -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): 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..785c1b51f7 100644 --- a/unittests/tools/test_testssl_parser.py +++ b/unittests/tools/test_testssl_parser.py @@ -1,111 +1,112 @@ -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): 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..f3974c20d0 100644 --- a/unittests/tools/test_tfsec_parser.py +++ b/unittests/tools/test_tfsec_parser.py @@ -1,108 +1,109 @@ -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): 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..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): @@ -12,148 +13,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..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): @@ -13,144 +14,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 <non root user name>\' line to the Dockerfile', finding.mitigation) - references = '''https://avd.aquasec.com/misconfig/ds002 + self.assertEqual(description, finding.description) + self.assertEqual('Add \'USER <non root user name>\' 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 +167,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..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): @@ -12,96 +14,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..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): @@ -12,31 +13,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..f09272e445 100644 --- a/unittests/tools/test_trustwave_fusion_api_parser.py +++ b/unittests/tools/test_trustwave_fusion_api_parser.py @@ -1,77 +1,78 @@ -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): 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..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): @@ -15,43 +16,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_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 5b030be780..59c5a7bc1e 100644 --- a/unittests/tools/test_vcg_parser.py +++ b/unittests/tools/test_vcg_parser.py @@ -1,16 +1,15 @@ -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(object): +class TestFile: def read(self): return self.content @@ -181,7 +180,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) diff --git a/unittests/tools/test_veracode_parser.py b/unittests/tools/test_veracode_parser.py index 55799e9cf8..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): @@ -23,10 +25,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 +38,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 +69,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 +114,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 +148,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 +167,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 +184,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 +203,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 +231,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 +253,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 +343,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 +415,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..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): @@ -18,46 +19,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 +68,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 +94,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..3b5bc74235 100644 --- a/unittests/tools/test_wapiti_parser.py +++ b/unittests/tools/test_wapiti_parser.py @@ -1,67 +1,68 @@ -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): 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..1e881e1d02 100644 --- a/unittests/tools/test_wazuh_parser.py +++ b/unittests/tools/test_wazuh_parser.py @@ -1,53 +1,54 @@ -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): 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..e9f1e69411 100644 --- a/unittests/tools/test_wfuzz_parser.py +++ b/unittests/tools/test_wfuzz_parser.py @@ -1,58 +1,59 @@ -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): 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_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 6683da4bcd..65e91fc23b 100644 --- a/unittests/tools/test_whitehat_sentinel_parser.py +++ b/unittests/tools/test_whitehat_sentinel_parser.py @@ -1,31 +1,31 @@ -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): 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..040d7791e1 100644 --- a/unittests/tools/test_wiz_parser.py +++ b/unittests/tools/test_wiz_parser.py @@ -1,44 +1,45 @@ -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): - 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..c3932ebe75 100644 --- a/unittests/tools/test_wpscan_parser.py +++ b/unittests/tools/test_wpscan_parser.py @@ -1,154 +1,154 @@ 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): 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..8b46a61dea 100644 --- a/unittests/tools/test_xanitizer_parser.py +++ b/unittests/tools/test_xanitizer_parser.py @@ -1,35 +1,34 @@ -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): 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 d887225946..2a43e6222a 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): @@ -16,70 +17,77 @@ 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) + 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") + 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): + with open("unittests/scans/yarn_audit/issue_6495.json") as testfile: parser = YarnAuditParser() - parser.get_findings(testfile, self.get_test()) + findings = 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)) + 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_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") + 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") diff --git a/unittests/tools/test_zap_parser.py b/unittests/tools/test_zap_parser.py index 7167fb9c5e..c7b738155c 100644 --- a/unittests/tools/test_zap_parser.py +++ b/unittests/tools/test_zap_parser.py @@ -1,227 +1,228 @@ -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): - 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 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 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) 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 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 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) 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 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\n<!DOCTYPE html><html><head><title>Apache 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 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) 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