diff --git a/.github/workflows/generate-doc.yml b/.github/workflows/generate-doc.yml new file mode 100644 index 0000000..9284f9d --- /dev/null +++ b/.github/workflows/generate-doc.yml @@ -0,0 +1,20 @@ +name: Generate Readme Doc +on: + workflow_dispatch: + push: + paths: + - '*.json' + - 'readme.html' + - 'manual_readme_content.md' + tags-ignore: + - '**' + branches-ignore: + - next + - main +jobs: + generate-doc: + runs-on: ubuntu-latest + steps: + - uses: 'phantomcyber/dev-cicd-tools/github-actions/generate-doc@main' + with: + GITHUB_TOKEN: ${{ secrets.SOAR_APPS_TOKEN }} diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 6f15b22..131c639 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -1,7 +1,7 @@ name: Linting on: [push, pull_request] jobs: - lint: + lint: # Run per push for internal contributers. This isn't possible for forked pull requests, # so we'll need to run on PR events for external contributers. # String comparison below is case insensitive. diff --git a/.github/workflows/review-release.yml b/.github/workflows/review-release.yml new file mode 100644 index 0000000..6f3bf31 --- /dev/null +++ b/.github/workflows/review-release.yml @@ -0,0 +1,22 @@ +name: Review Release +concurrency: + group: app-release + cancel-in-progress: true +permissions: + contents: read + id-token: write + statuses: write +on: + workflow_dispatch: + inputs: + task_token: + description: 'StepFunction task token' + required: true + +jobs: + review: + uses: 'phantomcyber/dev-cicd-tools/.github/workflows/review-release.yml@main' + with: + task_token: ${{ inputs.task_token }} + secrets: + resume_release_role_arn: ${{ secrets.RESUME_RELEASE_ROLE_ARN }} diff --git a/.github/workflows/start-release.yml b/.github/workflows/start-release.yml index d5fb354..7bbce79 100644 --- a/.github/workflows/start-release.yml +++ b/.github/workflows/start-release.yml @@ -1,9 +1,13 @@ name: Start Release -on: workflow_dispatch +on: + workflow_dispatch: + push: + tags: + - '*-beta*' jobs: start-release: runs-on: ubuntu-latest steps: - uses: 'phantomcyber/dev-cicd-tools/github-actions/start-release@main' with: - GITHUB_TOKEN: ${{ secrets.SOAR_APPS_TOKEN }} \ No newline at end of file + GITHUB_TOKEN: ${{ secrets.SOAR_APPS_TOKEN }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 207fabc..c8355cb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,11 +1,11 @@ repos: - repo: https://github.com/phantomcyber/dev-cicd-tools - rev: v1.4 + rev: v1.16 hooks: - id: org-hook - id: package-app-dependencies - repo: https://github.com/Yelp/detect-secrets - rev: v1.1.0 + rev: v1.4.0 hooks: - id: detect-secrets args: ['--no-verify', '--exclude-files', '^awswafv2.json$'] diff --git a/LICENSE b/LICENSE index f003b93..4300457 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2021 Splunk Inc. + Copyright (c) 2021-2024 Splunk Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7b60883 --- /dev/null +++ b/README.md @@ -0,0 +1,244 @@ +[comment]: # "Auto-generated SOAR connector documentation" +# AWS WAF V2 + +Publisher: Splunk +Connector Version: 2.1.8 +Product Vendor: AWS +Product Name: WAF V2 +Product Version Supported (regex): ".\*" +Minimum Product Version: 6.1.1 + +This app integrates with AWS WAF to add and delete IP addresses using API version V2 + +[comment]: # " File: README.md" +[comment]: # " Copyright (c) 2018-2021 Splunk Inc." +[comment]: # "" +[comment]: # " SPLUNK CONFIDENTIAL - Use or disclosure of this material in whole or in part" +[comment]: # " without a valid written license from Splunk Inc. is PROHIBITED." +[comment]: # "" +## Asset Configuration + +There are two ways to configure an AWS WAF asset. The first is to configure the **access_key** , +**secret_key** and **region** variables. If it is preferred to use a role and Phantom is running as +an EC2 instance, the **use_role** checkbox can be checked instead. This will allow the role that is +attached to the instance to be used. Please see the [AWS EC2 and IAM +documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html) +for more information. + +Region parameter provided in the asset configuration parameter and region of the bucket which is +created in AWS console must match, otherwise the user will get an InvalidLocationConstraint error. + +For the **Update bucket** action, the +API is unable to validate the KMS key. Hence, it is recommended to provide a +valid KMS key in this action parameter, otherwise it will affect the S3 bucket. For example, +if we update the S3 bucket with an invalid KMS key and run the +'create object' action on the bucket then the action will not work for encryption = NONE. + +## Assumed Role Credentials + +The optional **credentials** action parameter consists of temporary **assumed role** credentials +that will be used to perform the action instead of those that are configured in the **asset** . The +parameter is not designed to be configured manually, but should instead be used in conjunction with +the Phantom AWS Security Token Service app. The output of the **assume_role** action of the STS app +with data path **assume_role\_\:action_result.data.\*.Credentials** consists of a dictionary +containing the **AccessKeyId** , **SecretAccessKey** , **SessionToken** and **Expiration** key/value +pairs. This dictionary can be passed directly into the credentials parameter in any of the following +actions within a playbook. For more information, please see the [AWS Identity and Access Management +documentation](https://docs.aws.amazon.com/iam/index.html) . + + +### Configuration Variables +The below configuration variables are required for this Connector to operate. These variables are specified when configuring a WAF V2 asset in SOAR. + +VARIABLE | REQUIRED | TYPE | DESCRIPTION +-------- | -------- | ---- | ----------- +**access_key_id** | optional | password | Access Key ID +**access_key_secret** | optional | password | Access Key Secret +**scope** | required | string | Specifies whether this is for an AWS CloudFront distribution or a regional application +**region** | required | string | Region +**use_role** | optional | boolean | Use attached role when running Phantom in EC2 + +### Supported Actions +[test connectivity](#action-test-connectivity) - Validate the asset configuration for connectivity using supplied configuration +[add ip](#action-add-ip) - Add new IP(s) to an existing IP set or a new IP set +[delete ip](#action-delete-ip) - Remove IP(s) from an existing IP set +[delete ip set](#action-delete-ip-set) - Remove the specified IP Set +[list acls](#action-list-acls) - List all ACLs +[list ip sets](#action-list-ip-sets) - List all IP sets + +## action: 'test connectivity' +Validate the asset configuration for connectivity using supplied configuration + +Type: **test** +Read only: **True** + +#### Action Parameters +No parameters are required for this action + +#### Action Output +No Output + +## action: 'add ip' +Add new IP(s) to an existing IP set or a new IP set + +Type: **contain** +Read only: **False** + +The ip_set_id or ip_set_name must be given as input for adding an IP to the IP set, ip_set_id will be considered if both ip_set_id and ip_set_name is provided in input. If the given ip_set_name does not exist on the server and the name matches the WAF IP set name criteria, the new IP set with a given input will be created on the server. + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**ip_set_id** | optional | ID of the IP set | string | `awswaf ip set id` +**ip_set_name** | optional | Name of the IP set | string | `awswaf ip set name` +**ip_address** | required | IP Address (Allows comma-separated) | string | `awswaf ip mask` +**credentials** | optional | Assumed role credentials | string | `aws credentials` + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.ip_address | string | `awswaf ip mask` | 126.0.0.0/24 +action_result.parameter.ip_set_id | string | `awswaf ip set id` | 0778db34-cc96-4795-8c14-d1a146888391 +action_result.parameter.ip_set_name | string | `awswaf ip set name` | test_ip_set test_ip_set_6 +action_result.data.\*.Id | string | `awswaf ip set id` | b53eef26-f2be-44ef-9bcf-c16c3d07d791 +action_result.data.\*.ResponseMetadata.HTTPHeaders.content-length | string | | 54 +action_result.data.\*.ResponseMetadata.HTTPHeaders.content-type | string | | application/x-amz-json-1.1 +action_result.data.\*.ResponseMetadata.HTTPHeaders.date | string | | Thu, 04 Apr 2019 09:02:54 GMT +action_result.data.\*.ResponseMetadata.HTTPHeaders.x-amzn-requestid | string | | 6e762be6-56b8-11e9-ab52-739c81485c05 +action_result.data.\*.ResponseMetadata.HTTPStatusCode | numeric | | 200 +action_result.data.\*.ResponseMetadata.RequestId | string | | 6e762be6-56b8-11e9-ab52-739c81485c05 +action_result.data.\*.ResponseMetadata.RetryAttempts | numeric | | 0 +action_result.summary.ip_status | string | | IP(s) added successfully +action_result.message | string | | Ip status: IP(s) added successfully +action_result.data.\*.NextLockToken | string | | +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 +action_result.parameter.credentials | string | `aws credentials` | {'AccessKeyId': '\*REDACTED\*', 'Expiration': '2021-06-07 22:28:04', 'SecretAccessKey': '\*REDACTED\*', 'SessionToken': '\*REDACTED\*'} + +## action: 'delete ip' +Remove IP(s) from an existing IP set + +Type: **correct** +Read only: **False** + +The ip_set_id or ip_set_name must be given as input for deleting an IP from the IP set, ip_set_id will be considered if both ip_set_id and ip_set_name is provided in input. + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**ip_set_id** | optional | IP Set ID | string | `awswaf ip set id` +**ip_set_name** | optional | IP Set Name | string | `awswaf ip set name` +**ip_address** | required | IP Address (Allows comma-separated) | string | `awswaf ip mask` +**credentials** | optional | Assumed role credentials | string | `aws credentials` + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.ip_address | string | `awswaf ip mask` | 126.0.0.0/24 +action_result.parameter.ip_set_id | string | `awswaf ip set id` | 0778db34-cc96-4795-8c14-d1a146888391 +action_result.parameter.ip_set_name | string | `awswaf ip set name` | test_ip test_ip_set_5 +action_result.data.\*.ResponseMetadata.HTTPHeaders.content-length | string | | 54 +action_result.data.\*.ResponseMetadata.HTTPHeaders.content-type | string | | application/x-amz-json-1.1 +action_result.data.\*.ResponseMetadata.HTTPHeaders.date | string | | Thu, 04 Apr 2019 09:08:32 GMT +action_result.data.\*.ResponseMetadata.HTTPHeaders.x-amzn-requestid | string | | 389889ac-56b9-11e9-ab52-739c81485c05 +action_result.data.\*.ResponseMetadata.HTTPStatusCode | numeric | | 200 +action_result.data.\*.ResponseMetadata.RequestId | string | | 389889ac-56b9-11e9-ab52-739c81485c05 +action_result.data.\*.ResponseMetadata.RetryAttempts | numeric | | 0 +action_result.summary.ip_status | string | | IP(s) deleted successfully +action_result.message | string | | Ip status: IP(s) deleted successfully +action_result.data.\*.NextLockToken | string | | +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 +action_result.parameter.credentials | string | `aws credentials` | {'AccessKeyId': '\*REDACTED\*', 'Expiration': '2021-06-07 22:28:04', 'SecretAccessKey': '\*REDACTED\*', 'SessionToken': '\*REDACTED\*'} + +## action: 'delete ip set' +Remove the specified IP Set + +Type: **correct** +Read only: **False** + +The ip_set_id or ip_set_name must be given as input for deleting an IP set, ip_set_id will be used if both ip_set_id and ip_set_name is provided in input. + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**ip_set_id** | optional | IP Set ID | string | `awswaf ip set id` +**ip_set_name** | optional | IP Set Name | string | `awswaf ip set name` +**credentials** | optional | Assumed role credentials | string | `aws credentials` + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.data.\*.ResponseMetadata.RequestId | string | | 0c28d801-b618-49b8-b904-2ff6698bb038 +action_result.data.\*.ResponseMetadata.HTTPHeaders.date | string | | Wed, 22 Sep 2021 20:04:47 GMT +action_result.data.\*.ResponseMetadata.HTTPHeaders.content-type | string | | application/x-amz-json-1.1 +action_result.data.\*.ResponseMetadata.HTTPHeaders.content-length | string | | 2 +action_result.data.\*.ResponseMetadata.HTTPHeaders.x-amzn-requestid | string | | 0c28d801-b618-49b8-b904-2ff6698bb038 +action_result.data.\*.ResponseMetadata.RetryAttempts | numeric | | 0 +action_result.data.\*.ResponseMetadata.HTTPStatusCode | numeric | | 200 +action_result.status | string | | success +action_result.message | string | | Delete status: IP Set deleted successfully +action_result.summary.delete_status | string | | IP Set deleted successfully +action_result.parameter.ip_set_id | string | `awswaf ip set id` | 25b7e872-0645-4229-91d5-28e2369262aa +action_result.parameter.ip_set_name | string | `awswaf ip set name` | new_ip_set_1383662 +action_result.parameter.credentials | string | `aws credentials` | {'AccessKeyId': '\*REDACTED\*', 'Expiration': '2021-06-07 22:28:04', 'SecretAccessKey': '\*REDACTED\*', 'SessionToken': '\*REDACTED\*'} +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'list acls' +List all ACLs + +Type: **investigate** +Read only: **True** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**limit** | optional | Maximum number of results (default: 100) | numeric | +**credentials** | optional | Assumed role credentials | string | `aws credentials` + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.limit | numeric | | 50 +action_result.data.\*.ARN | string | | +action_result.data.\*.LockToken | string | | +action_result.data.\*.Description | string | | +action_result.data.\*.Name | string | | test_acl_2 +action_result.data.\*.Id | string | | 1d5f92b0-c376-4095-a939-efd04f62fda1 +action_result.summary.number_of_acls | numeric | | 4 +action_result.message | string | | Number of acls: 4 +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 +action_result.parameter.credentials | string | `aws credentials` | {'AccessKeyId': '\*REDACTED\*', 'Expiration': '2021-06-07 22:28:04', 'SecretAccessKey': '\*REDACTED\*', 'SessionToken': '\*REDACTED\*'} + +## action: 'list ip sets' +List all IP sets + +Type: **investigate** +Read only: **True** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**limit** | optional | Maximum number of results (default: 100) | numeric | +**credentials** | optional | Assumed role credentials | string | `aws credentials` + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.limit | numeric | | 50 +action_result.data.\*.Id | string | `awswaf ip set id` | 0778db34-cc96-4795-8c14-d1a146888391 +action_result.data.\*.Name | string | `awswaf ip set name` | test_ip +action_result.data.\*.ARN | string | | +action_result.data.\*.LockToken | string | | +action_result.data.\*.Description | string | | +action_result.summary.number_of_ip_sets | numeric | | 56 +action_result.message | string | | Number of ip sets: 56 +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 +action_result.parameter.credentials | string | `aws credentials` | {'AccessKeyId': '\*REDACTED\*', 'Expiration': '2021-06-07 22:28:04', 'SecretAccessKey': '\*REDACTED\*', 'SessionToken': '\*REDACTED\*'} \ No newline at end of file diff --git a/__init__.py b/__init__.py index 8b7a30b..5f2ad2d 100644 --- a/__init__.py +++ b/__init__.py @@ -1,6 +1,6 @@ # File: __init__.py # -# Copyright (c) 2021 Splunk Inc. +# Copyright (c) 2021-2024 Splunk Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/awswafv2.json b/awswafv2.json index 40d3f8c..7f7a7aa 100644 --- a/awswafv2.json +++ b/awswafv2.json @@ -9,70 +9,18 @@ "product_name": "WAF V2", "product_version_regex": ".*", "publisher": "Splunk", - "license": "Copyright (c) 2021 Splunk Inc.", - "app_version": "2.1.7", - "utctime_updated": "2021-12-22T19:56:43.000000Z", + "license": "Copyright (c) 2021-2024 Splunk Inc.", + "app_version": "2.1.8", + "utctime_updated": "2022-01-07T20:07:08.000000Z", "package_name": "phantom_awswafv2", "main_module": "awswafv2_connector.py", - "min_phantom_version": "4.10.0.40961", + "min_phantom_version": "6.1.1", "fips_compliant": true, "app_wizard_version": "1.0.0", "python_version": "3", "latest_tested_versions": [ "Cloud, API WAFv2 tested on 12-03-2021" ], - "pip_dependencies": { - "wheel": [ - { - "module": "boto3", - "input_file": "wheels/boto3-1.17.30-py2.py3-none-any.whl" - }, - { - "module": "botocore", - "input_file": "wheels/botocore-1.20.30-py2.py3-none-any.whl" - }, - { - "module": "certifi", - "input_file": "wheels/certifi-2021.10.8-py2.py3-none-any.whl" - }, - { - "module": "chardet", - "input_file": "wheels/chardet-3.0.4-py2.py3-none-any.whl" - }, - { - "module": "docutils", - "input_file": "wheels/docutils-0.16-py2.py3-none-any.whl" - }, - { - "module": "idna", - "input_file": "wheels/idna-2.10-py2.py3-none-any.whl" - }, - { - "module": "jmespath", - "input_file": "wheels/jmespath-0.10.0-py2.py3-none-any.whl" - }, - { - "module": "python_dateutil", - "input_file": "wheels/python_dateutil-2.8.2-py2.py3-none-any.whl" - }, - { - "module": "requests", - "input_file": "wheels/requests-2.25.0-py2.py3-none-any.whl" - }, - { - "module": "s3transfer", - "input_file": "wheels/s3transfer-0.3.4-py2.py3-none-any.whl" - }, - { - "module": "six", - "input_file": "wheels/six-1.15.0-py2.py3-none-any.whl" - }, - { - "module": "urllib3", - "input_file": "wheels/urllib3-1.26.7-py2.py3-none-any.whl" - } - ] - }, "configuration": { "access_key_id": { "description": "Access Key ID", @@ -338,7 +286,7 @@ "data_path": "action_result.parameter.credentials", "data_type": "string", "example_values": [ - "{'AccessKeyId': 'ASIASJL6ZZZZZ3M7QC2J', 'Expiration': '2021-06-07 22:28:04', 'SecretAccessKey': 'ZZZZZAmvLPictcVBPvjJx0d7MRezOuxiLCMZZZZZ', 'SessionToken': 'ZZZZZXIvYXdzEN///////////wEaDFRU0s4AVrw0k0oYICK4ATAzOqzAkg9bHY29lYmP59UvVOHjLufOy4s7SnAzOxGqGIXnukLis4TWNhrJl5R5nYyimrm6K/9d0Cw2SW9gO0ZRjEJHWJ+yY5Qk2QpWctS2BGn4n+G8cD6zEweCCMj+ScI5p8n7YI4wOdvXvOsVMmjV6F09Ujqr1w+NwoKXlglznXGs/7Q1kNZOMiioEhGUyoiHbQb37GCKslDK+oqe0KNaUKQ96YCepaLgMbMquDgdAM8I0TTxUO0o5ILF/gUyLT04R7QlOfktkdh6Qt0atTS+xeKi1hirKRizpJ8jjnxGQIikPRToL2v3ZZZZZZ=='}" + "{'AccessKeyId': '*REDACTED*', 'Expiration': '2021-06-07 22:28:04', 'SecretAccessKey': '*REDACTED*', 'SessionToken': '*REDACTED*'}" ], "contains": [ "aws credentials" @@ -531,7 +479,7 @@ "data_path": "action_result.parameter.credentials", "data_type": "string", "example_values": [ - "{'AccessKeyId': 'ASIASJL6ZZZZZ3M7QC2J', 'Expiration': '2021-06-07 22:28:04', 'SecretAccessKey': 'ZZZZZAmvLPictcVBPvjJx0d7MRezOuxiLCMZZZZZ', 'SessionToken': 'ZZZZZXIvYXdzEN///////////wEaDFRU0s4AVrw0k0oYICK4ATAzOqzAkg9bHY29lYmP59UvVOHjLufOy4s7SnAzOxGqGIXnukLis4TWNhrJl5R5nYyimrm6K/9d0Cw2SW9gO0ZRjEJHWJ+yY5Qk2QpWctS2BGn4n+G8cD6zEweCCMj+ScI5p8n7YI4wOdvXvOsVMmjV6F09Ujqr1w+NwoKXlglznXGs/7Q1kNZOMiioEhGUyoiHbQb37GCKslDK+oqe0KNaUKQ96YCepaLgMbMquDgdAM8I0TTxUO0o5ILF/gUyLT04R7QlOfktkdh6Qt0atTS+xeKi1hirKRizpJ8jjnxGQIikPRToL2v3ZZZZZZ=='}" + "{'AccessKeyId': '*REDACTED*', 'Expiration': '2021-06-07 22:28:04', 'SecretAccessKey': '*REDACTED*', 'SessionToken': '*REDACTED*'}" ], "contains": [ "aws credentials" @@ -678,7 +626,7 @@ "data_path": "action_result.parameter.credentials", "data_type": "string", "example_values": [ - "{'AccessKeyId': 'ASIASJL6ZZZZZ3M7QC2J', 'Expiration': '2021-06-07 22:28:04', 'SecretAccessKey': 'ZZZZZAmvLPictcVBPvjJx0d7MRezOuxiLCMZZZZZ', 'SessionToken': 'ZZZZZXIvYXdzEN///////////wEaDFRU0s4AVrw0k0oYICK4ATAzOqzAkg9bHY29lYmP59UvVOHjLufOy4s7SnAzOxGqGIXnukLis4TWNhrJl5R5nYyimrm6K/9d0Cw2SW9gO0ZRjEJHWJ+yY5Qk2QpWctS2BGn4n+G8cD6zEweCCMj+ScI5p8n7YI4wOdvXvOsVMmjV6F09Ujqr1w+NwoKXlglznXGs/7Q1kNZOMiioEhGUyoiHbQb37GCKslDK+oqe0KNaUKQ96YCepaLgMbMquDgdAM8I0TTxUO0o5ILF/gUyLT04R7QlOfktkdh6Qt0atTS+xeKi1hirKRizpJ8jjnxGQIikPRToL2v3ZZZZZZ=='}" + "{'AccessKeyId': '*REDACTED*', 'Expiration': '2021-06-07 22:28:04', 'SecretAccessKey': '*REDACTED*', 'SessionToken': '*REDACTED*'}" ], "contains": [ "aws credentials" @@ -815,7 +763,7 @@ "data_path": "action_result.parameter.credentials", "data_type": "string", "example_values": [ - "{'AccessKeyId': 'ASIASJL6ZZZZZ3M7QC2J', 'Expiration': '2021-06-07 22:28:04', 'SecretAccessKey': 'ZZZZZAmvLPictcVBPvjJx0d7MRezOuxiLCMZZZZZ', 'SessionToken': 'ZZZZZXIvYXdzEN///////////wEaDFRU0s4AVrw0k0oYICK4ATAzOqzAkg9bHY29lYmP59UvVOHjLufOy4s7SnAzOxGqGIXnukLis4TWNhrJl5R5nYyimrm6K/9d0Cw2SW9gO0ZRjEJHWJ+yY5Qk2QpWctS2BGn4n+G8cD6zEweCCMj+ScI5p8n7YI4wOdvXvOsVMmjV6F09Ujqr1w+NwoKXlglznXGs/7Q1kNZOMiioEhGUyoiHbQb37GCKslDK+oqe0KNaUKQ96YCepaLgMbMquDgdAM8I0TTxUO0o5ILF/gUyLT04R7QlOfktkdh6Qt0atTS+xeKi1hirKRizpJ8jjnxGQIikPRToL2v3ZZZZZZ=='}" + "{'AccessKeyId': '*REDACTED*', 'Expiration': '2021-06-07 22:28:04', 'SecretAccessKey': '*REDACTED*', 'SessionToken': '*REDACTED*'}" ], "contains": [ "aws credentials" @@ -943,7 +891,7 @@ "data_path": "action_result.parameter.credentials", "data_type": "string", "example_values": [ - "{'AccessKeyId': 'ASIASJL6ZZZZZ3M7QC2J', 'Expiration': '2021-06-07 22:28:04', 'SecretAccessKey': 'ZZZZZAmvLPictcVBPvjJx0d7MRezOuxiLCMZZZZZ', 'SessionToken': 'ZZZZZXIvYXdzEN///////////wEaDFRU0s4AVrw0k0oYICK4ATAzOqzAkg9bHY29lYmP59UvVOHjLufOy4s7SnAzOxGqGIXnukLis4TWNhrJl5R5nYyimrm6K/9d0Cw2SW9gO0ZRjEJHWJ+yY5Qk2QpWctS2BGn4n+G8cD6zEweCCMj+ScI5p8n7YI4wOdvXvOsVMmjV6F09Ujqr1w+NwoKXlglznXGs/7Q1kNZOMiioEhGUyoiHbQb37GCKslDK+oqe0KNaUKQ96YCepaLgMbMquDgdAM8I0TTxUO0o5ILF/gUyLT04R7QlOfktkdh6Qt0atTS+xeKi1hirKRizpJ8jjnxGQIikPRToL2v3ZZZZZZ=='}" + "{'AccessKeyId': '*REDACTED*', 'Expiration': '2021-06-07 22:28:04', 'SecretAccessKey': '*REDACTED*', 'SessionToken': '*REDACTED*'}" ], "contains": [ "aws credentials" @@ -955,5 +903,37 @@ }, "versions": "EQ(*)" } - ] -} \ No newline at end of file + ], + "pip_dependencies": { + "wheel": [ + { + "module": "boto3", + "input_file": "wheels/shared/boto3-1.17.30-py2.py3-none-any.whl" + }, + { + "module": "botocore", + "input_file": "wheels/shared/botocore-1.20.30-py2.py3-none-any.whl" + }, + { + "module": "jmespath", + "input_file": "wheels/shared/jmespath-0.10.0-py2.py3-none-any.whl" + }, + { + "module": "python_dateutil", + "input_file": "wheels/shared/python_dateutil-2.8.2-py2.py3-none-any.whl" + }, + { + "module": "s3transfer", + "input_file": "wheels/shared/s3transfer-0.3.7-py2.py3-none-any.whl" + }, + { + "module": "six", + "input_file": "wheels/shared/six-1.16.0-py2.py3-none-any.whl" + }, + { + "module": "urllib3", + "input_file": "wheels/shared/urllib3-1.26.18-py2.py3-none-any.whl" + } + ] + } +} diff --git a/awswafv2_connector.py b/awswafv2_connector.py index baec036..fb77cb6 100644 --- a/awswafv2_connector.py +++ b/awswafv2_connector.py @@ -1,6 +1,6 @@ # File: awswafv2_connector.py # -# Copyright (c) 2021 Splunk Inc. +# Copyright (c) 2021-2024 Splunk Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -22,7 +22,6 @@ import botocore.response as br import phantom.app as phantom import requests -import six from boto3 import Session, client from botocore.config import Config from phantom.action_result import ActionResult @@ -64,7 +63,7 @@ def _sanitize_data(self, cur_obj): if isinstance(cur_obj, dict): new_dict = {} - for k, v in six.iteritems(cur_obj): + for k, v in cur_obj.items(): if isinstance(v, br.StreamingBody): content = v.read() new_dict[k] = json.loads(content) diff --git a/awswafv2_consts.py b/awswafv2_consts.py index 81a0ea0..1ba5ef9 100644 --- a/awswafv2_consts.py +++ b/awswafv2_consts.py @@ -1,6 +1,6 @@ # File: awswafv2_consts.py # -# Copyright (c) 2021 Splunk Inc. +# Copyright (c) 2021-2024 Splunk Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ # and limitations under the License. AWSWAF_VERSION_V2 = 'wafv2' AWSWAF_ACCESS_KEY = 'access_key_id' -AWSWAF_SECRET_KEY = 'access_key_secret' +AWSWAF_SECRET_KEY = 'access_key_secret' # pragma: allowlist secret AWSWAF_REGION = 'region' AWSWAF_SCOPE = 'scope' AWSWAF_SCOPE_CLOUDFRONT = 'CLOUDFRONT' diff --git a/exclude_files.txt b/exclude_files.txt index 4c81ebc..e9cafef 100644 --- a/exclude_files.txt +++ b/exclude_files.txt @@ -2,4 +2,4 @@ docker-compose.yml Makefile .git* .gitlab-ci.yml -whitesource-results \ No newline at end of file +whitesource-results diff --git a/manual_readme_content.md b/manual_readme_content.md new file mode 100644 index 0000000..64ce1ce --- /dev/null +++ b/manual_readme_content.md @@ -0,0 +1,35 @@ +[comment]: # " File: README.md" +[comment]: # " Copyright (c) 2018-2021 Splunk Inc." +[comment]: # "" +[comment]: # " SPLUNK CONFIDENTIAL - Use or disclosure of this material in whole or in part" +[comment]: # " without a valid written license from Splunk Inc. is PROHIBITED." +[comment]: # "" +## Asset Configuration + +There are two ways to configure an AWS WAF asset. The first is to configure the **access_key** , +**secret_key** and **region** variables. If it is preferred to use a role and Phantom is running as +an EC2 instance, the **use_role** checkbox can be checked instead. This will allow the role that is +attached to the instance to be used. Please see the [AWS EC2 and IAM +documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html) +for more information. + +Region parameter provided in the asset configuration parameter and region of the bucket which is +created in AWS console must match, otherwise the user will get an InvalidLocationConstraint error. + +For the **Update bucket** action, the +API is unable to validate the KMS key. Hence, it is recommended to provide a +valid KMS key in this action parameter, otherwise it will affect the S3 bucket. For example, +if we update the S3 bucket with an invalid KMS key and run the +'create object' action on the bucket then the action will not work for encryption = NONE. + +## Assumed Role Credentials + +The optional **credentials** action parameter consists of temporary **assumed role** credentials +that will be used to perform the action instead of those that are configured in the **asset** . The +parameter is not designed to be configured manually, but should instead be used in conjunction with +the Phantom AWS Security Token Service app. The output of the **assume_role** action of the STS app +with data path **assume_role\_\:action_result.data.\*.Credentials** consists of a dictionary +containing the **AccessKeyId** , **SecretAccessKey** , **SessionToken** and **Expiration** key/value +pairs. This dictionary can be passed directly into the credentials parameter in any of the following +actions within a playbook. For more information, please see the [AWS Identity and Access Management +documentation](https://docs.aws.amazon.com/iam/index.html) . diff --git a/readme.html b/readme.html deleted file mode 100644 index df34af5..0000000 --- a/readme.html +++ /dev/null @@ -1,18 +0,0 @@ - - - -

Asset Configuration

-There are two ways to configure an AWS WAF asset. The first is to configure the access_key, secret_key and region variables. If it is preferred to use a role and Phantom is running as an EC2 instance, the use_role checkbox can be checked instead. This will allow the role that is attached to the instance to be used. Please see the AWS EC2 and IAM documentation for more information. - -

Region parameter provided in the asset configuration parameter and region of the bucket which is created in AWS console must match, otherwise the user will get an InvalidLocationConstraint error.

-

For the Update bucket action, the API is unable to validate the KMS key. Hence, it is recommended to provide a valid KMS key in this action parameter, otherwise it will affect the S3 bucket. For example, if we update the S3 bucket with an invalid KMS key and run the 'create object' action on the bucket then the action will not work for encryption = NONE.

- -

Assumed Role Credentials

-The optional credentials action parameter consists of temporary assumed role credentials that will be used to perform the action instead of those that are configured in the asset. The parameter is not designed to be configured manually, but should instead be used in conjunction with the Phantom AWS Security Token Service app. The output of the assume_role action of the STS app with data path assume_role_<number>:action_result.data.*.Credentials consists of a dictionary containing the AccessKeyId, SecretAccessKey, SessionToken and Expiration key/value pairs. This dictionary can be passed directly into the credentials parameter in any of the following actions within a playbook. For more information, please see the AWS Identity and Access Management documentation. - - diff --git a/readme.md b/readme.md deleted file mode 100644 index 6af9740..0000000 --- a/readme.md +++ /dev/null @@ -1,244 +0,0 @@ -[comment]: # "Auto-generated SOAR connector documentation" -# AWS WAF V2 - -Publisher: Splunk -Connector Version: 2\.1\.7 -Product Vendor: AWS -Product Name: WAF V2 -Product Version Supported (regex): "\.\*" -Minimum Product Version: 4\.10\.0\.40961 - -This app integrates with AWS WAF to add and delete IP addresses using API version V2 - -[comment]: # " File: readme.md" -[comment]: # " Copyright (c) 2018-2021 Splunk Inc." -[comment]: # "" -[comment]: # " SPLUNK CONFIDENTIAL - Use or disclosure of this material in whole or in part" -[comment]: # " without a valid written license from Splunk Inc. is PROHIBITED." -[comment]: # "" -## Asset Configuration - -There are two ways to configure an AWS WAF asset. The first is to configure the **access_key** , -**secret_key** and **region** variables. If it is preferred to use a role and Phantom is running as -an EC2 instance, the **use_role** checkbox can be checked instead. This will allow the role that is -attached to the instance to be used. Please see the [AWS EC2 and IAM -documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html) -for more information. - -Region parameter provided in the asset configuration parameter and region of the bucket which is -created in AWS console must match, otherwise the user will get an InvalidLocationConstraint error. - -For the **Update bucket** action, the -API is unable to validate the KMS key. Hence, it is recommended to provide a -valid KMS key in this action parameter, otherwise it will affect the S3 bucket. For example, -if we update the S3 bucket with an invalid KMS key and run the -'create object' action on the bucket then the action will not work for encryption = NONE. - -## Assumed Role Credentials - -The optional **credentials** action parameter consists of temporary **assumed role** credentials -that will be used to perform the action instead of those that are configured in the **asset** . The -parameter is not designed to be configured manually, but should instead be used in conjunction with -the Phantom AWS Security Token Service app. The output of the **assume_role** action of the STS app -with data path **assume_role\_\:action_result.data.\*.Credentials** consists of a dictionary -containing the **AccessKeyId** , **SecretAccessKey** , **SessionToken** and **Expiration** key/value -pairs. This dictionary can be passed directly into the credentials parameter in any of the following -actions within a playbook. For more information, please see the [AWS Identity and Access Management -documentation](https://docs.aws.amazon.com/iam/index.html) . - - -### Configuration Variables -The below configuration variables are required for this Connector to operate. These variables are specified when configuring a WAF V2 asset in SOAR. - -VARIABLE | REQUIRED | TYPE | DESCRIPTION --------- | -------- | ---- | ----------- -**access\_key\_id** | optional | password | Access Key ID -**access\_key\_secret** | optional | password | Access Key Secret -**scope** | required | string | Specifies whether this is for an AWS CloudFront distribution or a regional application -**region** | required | string | Region -**use\_role** | optional | boolean | Use attached role when running Phantom in EC2 - -### Supported Actions -[test connectivity](#action-test-connectivity) - Validate the asset configuration for connectivity using supplied configuration -[add ip](#action-add-ip) - Add new IP\(s\) to an existing IP set or a new IP set -[delete ip](#action-delete-ip) - Remove IP\(s\) from an existing IP set -[delete ip set](#action-delete-ip-set) - Remove the specified IP Set -[list acls](#action-list-acls) - List all ACLs -[list ip sets](#action-list-ip-sets) - List all IP sets - -## action: 'test connectivity' -Validate the asset configuration for connectivity using supplied configuration - -Type: **test** -Read only: **True** - -#### Action Parameters -No parameters are required for this action - -#### Action Output -No Output - -## action: 'add ip' -Add new IP\(s\) to an existing IP set or a new IP set - -Type: **contain** -Read only: **False** - -The ip\_set\_id or ip\_set\_name must be given as input for adding an IP to the IP set, ip\_set\_id will be considered if both ip\_set\_id and ip\_set\_name is provided in input\. If the given ip\_set\_name does not exist on the server and the name matches the WAF IP set name criteria, the new IP set with a given input will be created on the server\. - -#### Action Parameters -PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS ---------- | -------- | ----------- | ---- | -------- -**ip\_set\_id** | optional | ID of the IP set | string | `awswaf ip set id` -**ip\_set\_name** | optional | Name of the IP set | string | `awswaf ip set name` -**ip\_address** | required | IP Address \(Allows comma\-separated\) | string | `awswaf ip mask` -**credentials** | optional | Assumed role credentials | string | `aws credentials` - -#### Action Output -DATA PATH | TYPE | CONTAINS ---------- | ---- | -------- -action\_result\.status | string | -action\_result\.parameter\.ip\_address | string | `awswaf ip mask` -action\_result\.parameter\.ip\_set\_id | string | `awswaf ip set id` -action\_result\.parameter\.ip\_set\_name | string | `awswaf ip set name` -action\_result\.data\.\*\.Id | string | `awswaf ip set id` -action\_result\.data\.\*\.ResponseMetadata\.HTTPHeaders\.content\-length | string | -action\_result\.data\.\*\.ResponseMetadata\.HTTPHeaders\.content\-type | string | -action\_result\.data\.\*\.ResponseMetadata\.HTTPHeaders\.date | string | -action\_result\.data\.\*\.ResponseMetadata\.HTTPHeaders\.x\-amzn\-requestid | string | -action\_result\.data\.\*\.ResponseMetadata\.HTTPStatusCode | numeric | -action\_result\.data\.\*\.ResponseMetadata\.RequestId | string | -action\_result\.data\.\*\.ResponseMetadata\.RetryAttempts | numeric | -action\_result\.summary\.ip\_status | string | -action\_result\.message | string | -action\_result\.data\.\*\.NextLockToken | string | -summary\.total\_objects | numeric | -summary\.total\_objects\_successful | numeric | -action\_result\.parameter\.credentials | string | `aws credentials` - -## action: 'delete ip' -Remove IP\(s\) from an existing IP set - -Type: **correct** -Read only: **False** - -The ip\_set\_id or ip\_set\_name must be given as input for deleting an IP from the IP set, ip\_set\_id will be considered if both ip\_set\_id and ip\_set\_name is provided in input\. - -#### Action Parameters -PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS ---------- | -------- | ----------- | ---- | -------- -**ip\_set\_id** | optional | IP Set ID | string | `awswaf ip set id` -**ip\_set\_name** | optional | IP Set Name | string | `awswaf ip set name` -**ip\_address** | required | IP Address \(Allows comma\-separated\) | string | `awswaf ip mask` -**credentials** | optional | Assumed role credentials | string | `aws credentials` - -#### Action Output -DATA PATH | TYPE | CONTAINS ---------- | ---- | -------- -action\_result\.status | string | -action\_result\.parameter\.ip\_address | string | `awswaf ip mask` -action\_result\.parameter\.ip\_set\_id | string | `awswaf ip set id` -action\_result\.parameter\.ip\_set\_name | string | `awswaf ip set name` -action\_result\.data\.\*\.ResponseMetadata\.HTTPHeaders\.content\-length | string | -action\_result\.data\.\*\.ResponseMetadata\.HTTPHeaders\.content\-type | string | -action\_result\.data\.\*\.ResponseMetadata\.HTTPHeaders\.date | string | -action\_result\.data\.\*\.ResponseMetadata\.HTTPHeaders\.x\-amzn\-requestid | string | -action\_result\.data\.\*\.ResponseMetadata\.HTTPStatusCode | numeric | -action\_result\.data\.\*\.ResponseMetadata\.RequestId | string | -action\_result\.data\.\*\.ResponseMetadata\.RetryAttempts | numeric | -action\_result\.summary\.ip\_status | string | -action\_result\.message | string | -action\_result\.data\.\*\.NextLockToken | string | -summary\.total\_objects | numeric | -summary\.total\_objects\_successful | numeric | -action\_result\.parameter\.credentials | string | `aws credentials` - -## action: 'delete ip set' -Remove the specified IP Set - -Type: **correct** -Read only: **False** - -The ip\_set\_id or ip\_set\_name must be given as input for deleting an IP set, ip\_set\_id will be used if both ip\_set\_id and ip\_set\_name is provided in input\. - -#### Action Parameters -PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS ---------- | -------- | ----------- | ---- | -------- -**ip\_set\_id** | optional | IP Set ID | string | `awswaf ip set id` -**ip\_set\_name** | optional | IP Set Name | string | `awswaf ip set name` -**credentials** | optional | Assumed role credentials | string | `aws credentials` - -#### Action Output -DATA PATH | TYPE | CONTAINS ---------- | ---- | -------- -action\_result\.data\.\*\.ResponseMetadata\.RequestId | string | -action\_result\.data\.\*\.ResponseMetadata\.HTTPHeaders\.date | string | -action\_result\.data\.\*\.ResponseMetadata\.HTTPHeaders\.content\-type | string | -action\_result\.data\.\*\.ResponseMetadata\.HTTPHeaders\.content\-length | string | -action\_result\.data\.\*\.ResponseMetadata\.HTTPHeaders\.x\-amzn\-requestid | string | -action\_result\.data\.\*\.ResponseMetadata\.RetryAttempts | numeric | -action\_result\.data\.\*\.ResponseMetadata\.HTTPStatusCode | numeric | -action\_result\.status | string | -action\_result\.message | string | -action\_result\.summary\.delete\_status | string | -action\_result\.parameter\.ip\_set\_id | string | `awswaf ip set id` -action\_result\.parameter\.ip\_set\_name | string | `awswaf ip set name` -action\_result\.parameter\.credentials | string | `aws credentials` -summary\.total\_objects | numeric | -summary\.total\_objects\_successful | numeric | - -## action: 'list acls' -List all ACLs - -Type: **investigate** -Read only: **True** - -#### Action Parameters -PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS ---------- | -------- | ----------- | ---- | -------- -**limit** | optional | Maximum number of results \(default\: 100\) | numeric | -**credentials** | optional | Assumed role credentials | string | `aws credentials` - -#### Action Output -DATA PATH | TYPE | CONTAINS ---------- | ---- | -------- -action\_result\.status | string | -action\_result\.parameter\.limit | numeric | -action\_result\.data\.\*\.ARN | string | -action\_result\.data\.\*\.LockToken | string | -action\_result\.data\.\*\.Description | string | -action\_result\.data\.\*\.Name | string | -action\_result\.data\.\*\.Id | string | -action\_result\.summary\.number\_of\_acls | numeric | -action\_result\.message | string | -summary\.total\_objects | numeric | -summary\.total\_objects\_successful | numeric | -action\_result\.parameter\.credentials | string | `aws credentials` - -## action: 'list ip sets' -List all IP sets - -Type: **investigate** -Read only: **True** - -#### Action Parameters -PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS ---------- | -------- | ----------- | ---- | -------- -**limit** | optional | Maximum number of results \(default\: 100\) | numeric | -**credentials** | optional | Assumed role credentials | string | `aws credentials` - -#### Action Output -DATA PATH | TYPE | CONTAINS ---------- | ---- | -------- -action\_result\.status | string | -action\_result\.parameter\.limit | numeric | -action\_result\.data\.\*\.Id | string | `awswaf ip set id` -action\_result\.data\.\*\.Name | string | `awswaf ip set name` -action\_result\.data\.\*\.ARN | string | -action\_result\.data\.\*\.LockToken | string | -action\_result\.data\.\*\.Description | string | -action\_result\.summary\.number\_of\_ip\_sets | numeric | -action\_result\.message | string | -summary\.total\_objects | numeric | -summary\.total\_objects\_successful | numeric | -action\_result\.parameter\.credentials | string | `aws credentials` \ No newline at end of file diff --git a/release_notes/2.1.8.md b/release_notes/2.1.8.md new file mode 100644 index 0000000..7e8ee83 --- /dev/null +++ b/release_notes/2.1.8.md @@ -0,0 +1 @@ +* Removed requests, six and indirect dependencies from requirements [PAPP-30763] \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 7430508..0302ce8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,2 @@ boto3==1.17.30 botocore==1.20.30 -docutils==0.16 -jmespath==0.10.0 -requests==2.25.0 -s3transfer==0.3.4 -six==1.15.0 diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..c4644ad --- /dev/null +++ b/tox.ini @@ -0,0 +1,7 @@ +[flake8] +max-line-length = 145 +max-complexity = 28 +extend-ignore = F403,E128,E126,E111,E121,E127,E731,E201,E202,F405,E722,D,W292 + +[isort] +line_length = 145 diff --git a/wheels/certifi-2021.10.8-py2.py3-none-any.whl b/wheels/certifi-2021.10.8-py2.py3-none-any.whl deleted file mode 100644 index fbcb86b..0000000 Binary files a/wheels/certifi-2021.10.8-py2.py3-none-any.whl and /dev/null differ diff --git a/wheels/chardet-3.0.4-py2.py3-none-any.whl b/wheels/chardet-3.0.4-py2.py3-none-any.whl deleted file mode 100644 index d276977..0000000 Binary files a/wheels/chardet-3.0.4-py2.py3-none-any.whl and /dev/null differ diff --git a/wheels/docutils-0.16-py2.py3-none-any.whl b/wheels/docutils-0.16-py2.py3-none-any.whl deleted file mode 100644 index 48440f7..0000000 Binary files a/wheels/docutils-0.16-py2.py3-none-any.whl and /dev/null differ diff --git a/wheels/idna-2.10-py2.py3-none-any.whl b/wheels/idna-2.10-py2.py3-none-any.whl deleted file mode 100644 index 41225cb..0000000 Binary files a/wheels/idna-2.10-py2.py3-none-any.whl and /dev/null differ diff --git a/wheels/requests-2.25.0-py2.py3-none-any.whl b/wheels/requests-2.25.0-py2.py3-none-any.whl deleted file mode 100644 index c3f28e5..0000000 Binary files a/wheels/requests-2.25.0-py2.py3-none-any.whl and /dev/null differ diff --git a/wheels/s3transfer-0.3.4-py2.py3-none-any.whl b/wheels/s3transfer-0.3.4-py2.py3-none-any.whl deleted file mode 100644 index 9c30c84..0000000 Binary files a/wheels/s3transfer-0.3.4-py2.py3-none-any.whl and /dev/null differ diff --git a/wheels/boto3-1.17.30-py2.py3-none-any.whl b/wheels/shared/boto3-1.17.30-py2.py3-none-any.whl similarity index 100% rename from wheels/boto3-1.17.30-py2.py3-none-any.whl rename to wheels/shared/boto3-1.17.30-py2.py3-none-any.whl diff --git a/wheels/botocore-1.20.30-py2.py3-none-any.whl b/wheels/shared/botocore-1.20.30-py2.py3-none-any.whl similarity index 100% rename from wheels/botocore-1.20.30-py2.py3-none-any.whl rename to wheels/shared/botocore-1.20.30-py2.py3-none-any.whl diff --git a/wheels/jmespath-0.10.0-py2.py3-none-any.whl b/wheels/shared/jmespath-0.10.0-py2.py3-none-any.whl similarity index 100% rename from wheels/jmespath-0.10.0-py2.py3-none-any.whl rename to wheels/shared/jmespath-0.10.0-py2.py3-none-any.whl diff --git a/wheels/python_dateutil-2.8.2-py2.py3-none-any.whl b/wheels/shared/python_dateutil-2.8.2-py2.py3-none-any.whl similarity index 100% rename from wheels/python_dateutil-2.8.2-py2.py3-none-any.whl rename to wheels/shared/python_dateutil-2.8.2-py2.py3-none-any.whl diff --git a/wheels/shared/s3transfer-0.3.7-py2.py3-none-any.whl b/wheels/shared/s3transfer-0.3.7-py2.py3-none-any.whl new file mode 100644 index 0000000..97eaef6 Binary files /dev/null and b/wheels/shared/s3transfer-0.3.7-py2.py3-none-any.whl differ diff --git a/wheels/shared/six-1.16.0-py2.py3-none-any.whl b/wheels/shared/six-1.16.0-py2.py3-none-any.whl new file mode 100644 index 0000000..fd94265 Binary files /dev/null and b/wheels/shared/six-1.16.0-py2.py3-none-any.whl differ diff --git a/wheels/shared/urllib3-1.26.18-py2.py3-none-any.whl b/wheels/shared/urllib3-1.26.18-py2.py3-none-any.whl new file mode 100644 index 0000000..c7337c7 Binary files /dev/null and b/wheels/shared/urllib3-1.26.18-py2.py3-none-any.whl differ diff --git a/wheels/six-1.15.0-py2.py3-none-any.whl b/wheels/six-1.15.0-py2.py3-none-any.whl deleted file mode 100644 index 89edace..0000000 Binary files a/wheels/six-1.15.0-py2.py3-none-any.whl and /dev/null differ diff --git a/wheels/urllib3-1.26.7-py2.py3-none-any.whl b/wheels/urllib3-1.26.7-py2.py3-none-any.whl deleted file mode 100644 index 62189e6..0000000 Binary files a/wheels/urllib3-1.26.7-py2.py3-none-any.whl and /dev/null differ