Wafv2 initial Implementation
This commit is contained in:
		
							parent
							
								
									bc369679f2
								
							
						
					
					
						commit
						1b7e015e19
					
				| @ -128,6 +128,7 @@ mock_mediastore = lazy_load(".mediastore", "mock_mediastore") | ||||
| mock_eks = lazy_load(".eks", "mock_eks") | ||||
| mock_mediastoredata = lazy_load(".mediastoredata", "mock_mediastoredata") | ||||
| mock_efs = lazy_load(".efs", "mock_efs") | ||||
| mock_wafv2 = lazy_load(".wafv2", "mock_wafv2") | ||||
| 
 | ||||
| # import logging | ||||
| # logging.getLogger('boto').setLevel(logging.CRITICAL) | ||||
|  | ||||
| @ -85,6 +85,7 @@ BACKENDS = { | ||||
|     "mediastore-data": ("mediastoredata", "mediastoredata_backends"), | ||||
|     "eks": ("eks", "eks_backends"), | ||||
|     "efs": ("efs", "efs_backends"), | ||||
|     "wafv2": ("wafv2", "wafv2_backends"), | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										7
									
								
								moto/wafv2/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								moto/wafv2/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| from __future__ import unicode_literals | ||||
| 
 | ||||
| from .models import wafv2_backends | ||||
| from ..core.models import base_decorator | ||||
| 
 | ||||
| wafv2_backend = wafv2_backends["us-east-1"] | ||||
| mock_wafv2 = base_decorator(wafv2_backends) | ||||
							
								
								
									
										14
									
								
								moto/wafv2/exceptions.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								moto/wafv2/exceptions.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| from __future__ import unicode_literals | ||||
| from moto.core.exceptions import RESTError | ||||
| 
 | ||||
| 
 | ||||
| class WAFv2ClientError(RESTError): | ||||
|     code = 400 | ||||
| 
 | ||||
| 
 | ||||
| class WAFV2DuplicateItemException(WAFv2ClientError): | ||||
|     def __init__(self): | ||||
|         super(WAFV2DuplicateItemException, self).__init__( | ||||
|             "WafV2DuplicateItem", | ||||
|             "AWS WAF could not perform the operation because some resource in your request is a duplicate of an existing one.", | ||||
|         ) | ||||
							
								
								
									
										130
									
								
								moto/wafv2/models.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								moto/wafv2/models.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,130 @@ | ||||
| from __future__ import unicode_literals | ||||
| from uuid import uuid4 | ||||
| from boto3 import Session | ||||
| from moto.core import BaseBackend, BaseModel | ||||
| from moto.wafv2 import utils | ||||
| 
 | ||||
| # from moto.ec2.models import elbv2_backends | ||||
| from .utils import make_arn_for_wacl, pascal_to_underscores_dict | ||||
| from .exceptions import WAFV2DuplicateItemException | ||||
| from moto.core.utils import iso_8601_datetime_with_milliseconds | ||||
| import datetime | ||||
| from collections import OrderedDict | ||||
| 
 | ||||
| 
 | ||||
| US_EAST_1_REGION = "us-east-1" | ||||
| GLOBAL_REGION = "global" | ||||
| 
 | ||||
| 
 | ||||
| class VisibilityConfig(BaseModel): | ||||
|     """ | ||||
|     https://docs.aws.amazon.com/waf/latest/APIReference/API_VisibilityConfig.html | ||||
|     """ | ||||
| 
 | ||||
|     def __init__( | ||||
|         self, metric_name, sampled_requests_enabled, cloud_watch_metrics_enabled | ||||
|     ): | ||||
|         self.cloud_watch_metrics_enabled = cloud_watch_metrics_enabled | ||||
|         self.metric_name = metric_name | ||||
|         self.sampled_requests_enabled = sampled_requests_enabled | ||||
| 
 | ||||
| 
 | ||||
| class DefaultAction(BaseModel): | ||||
|     """ | ||||
|     https://docs.aws.amazon.com/waf/latest/APIReference/API_DefaultAction.html | ||||
|     """ | ||||
| 
 | ||||
|     def __init__(self, allow={}, block={}): | ||||
|         self.allow = allow | ||||
|         self.block = block | ||||
| 
 | ||||
| 
 | ||||
| # TODO: Add remaining properties | ||||
| class FakeWebACL(BaseModel): | ||||
|     """ | ||||
|     https://docs.aws.amazon.com/waf/latest/APIReference/API_WebACL.html | ||||
|     """ | ||||
| 
 | ||||
|     def __init__(self, name, arn, id, visibility_config, default_action): | ||||
|         self.name = name if name else utils.create_test_name("Mock-WebACL-name") | ||||
|         self.created_time = iso_8601_datetime_with_milliseconds(datetime.datetime.now()) | ||||
|         self.id = id | ||||
|         self.arn = arn | ||||
|         self.description = "Mock WebACL named {0}".format(self.name) | ||||
|         self.capacity = 3 | ||||
|         self.visibility_config = VisibilityConfig( | ||||
|             **pascal_to_underscores_dict(visibility_config) | ||||
|         ) | ||||
|         self.default_action = DefaultAction( | ||||
|             **pascal_to_underscores_dict(default_action) | ||||
|         ) | ||||
| 
 | ||||
|     def to_dict(self): | ||||
|         # Format for summary https://docs.aws.amazon.com/waf/latest/APIReference/API_CreateWebACL.html (response syntax section) | ||||
|         return { | ||||
|             "ARN": self.arn, | ||||
|             "Description": self.description, | ||||
|             "Id": self.id, | ||||
|             "LockToken": "Not Implemented", | ||||
|             "Name": self.name, | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
| class WAFV2Backend(BaseBackend): | ||||
|     """ | ||||
|     https://docs.aws.amazon.com/waf/latest/APIReference/API_Operations_AWS_WAFV2.html | ||||
|     """ | ||||
| 
 | ||||
|     def __init__(self, region_name=None): | ||||
|         super(WAFV2Backend, self).__init__() | ||||
|         self.region_name = region_name | ||||
|         self.wacls = OrderedDict()  # self.wacls[ARN] = FakeWacl | ||||
|         # TODO: self.load_balancers = OrderedDict() | ||||
| 
 | ||||
|     def reset(self): | ||||
|         region_name = self.region_name | ||||
|         self.__dict__ = {} | ||||
|         self.__init__(region_name) | ||||
| 
 | ||||
|     def create_web_acl(self, name, visibility_config, default_action, scope): | ||||
|         wacl_id = str(uuid4()) | ||||
|         arn = make_arn_for_wacl( | ||||
|             name=name, region_name=self.region_name, id=wacl_id, scope=scope | ||||
|         ) | ||||
|         if arn in self.wacls or self._is_duplicate_name(name): | ||||
|             raise WAFV2DuplicateItemException() | ||||
|         new_wacl = FakeWebACL(name, arn, wacl_id, visibility_config, default_action) | ||||
|         self.wacls[arn] = new_wacl | ||||
|         return new_wacl | ||||
| 
 | ||||
|     def list_web_acls(self): | ||||
|         return [wacl.to_dict() for wacl in self.wacls.values()] | ||||
| 
 | ||||
|     def _is_duplicate_name(self, name): | ||||
|         allWaclNames = set(wacl.name for wacl in self.wacls.values()) | ||||
|         return name in allWaclNames | ||||
| 
 | ||||
|     # TODO: This is how you link wacl to ALB | ||||
|     # @property | ||||
|     # def elbv2_backend(self): | ||||
|     #     """ | ||||
|     #     EC2 backend | ||||
| 
 | ||||
|     #     :return: EC2 Backend | ||||
|     #     :rtype: moto.ec2.models.EC2Backend | ||||
|     #     """ | ||||
|     #     return ec2_backends[self.region_name] | ||||
| 
 | ||||
| 
 | ||||
| wafv2_backends = {} | ||||
| wafv2_backends[GLOBAL_REGION] = WAFV2Backend( | ||||
|     GLOBAL_REGION | ||||
| )  # never used? cloudfront is global and uses us-east-1 | ||||
| for region in Session().get_available_regions("waf-regional"): | ||||
|     wafv2_backends[region] = WAFV2Backend(region) | ||||
| for region in Session().get_available_regions( | ||||
|     "waf-regional", partition_name="aws-us-gov" | ||||
| ): | ||||
|     wafv2_backends[region] = WAFV2Backend(region) | ||||
| for region in Session().get_available_regions("waf-regional", partition_name="aws-cn"): | ||||
|     wafv2_backends[region] = WAFV2Backend(region) | ||||
							
								
								
									
										49
									
								
								moto/wafv2/responses.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								moto/wafv2/responses.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | ||||
| from __future__ import unicode_literals | ||||
| import json | ||||
| from moto.core.utils import amzn_request_id | ||||
| 
 | ||||
| from moto.core.responses import BaseResponse | ||||
| from .models import GLOBAL_REGION, wafv2_backends | ||||
| 
 | ||||
| 
 | ||||
| class WAFV2Response(BaseResponse): | ||||
|     @property | ||||
|     def wafv2_backend(self): | ||||
|         return wafv2_backends[self.region]  # default region is "us-east-1" | ||||
| 
 | ||||
|     @amzn_request_id | ||||
|     def create_web_acl(self): | ||||
|         """  https://docs.aws.amazon.com/waf/latest/APIReference/API_CreateWebACL.html (response syntax section) """ | ||||
| 
 | ||||
|         scope = self._get_param("Scope") | ||||
|         if scope == "CLOUDFRONT": | ||||
|             self.region = GLOBAL_REGION | ||||
|         name = self._get_param("Name") | ||||
|         body = json.loads(self.body) | ||||
|         web_acl = self.wafv2_backend.create_web_acl( | ||||
|             name, body["VisibilityConfig"], body["DefaultAction"], scope | ||||
|         ) | ||||
|         response = { | ||||
|             "Summary": web_acl.to_dict(), | ||||
|         } | ||||
|         response_headers = {"Content-Type": "application/json"} | ||||
|         return 200, response_headers, json.dumps(response) | ||||
| 
 | ||||
|     @amzn_request_id | ||||
|     def list_web_ac_ls(self): | ||||
|         """  https://docs.aws.amazon.com/waf/latest/APIReference/API_ListWebACLs.html (response syntax section) """ | ||||
| 
 | ||||
|         scope = self._get_param("Scope") | ||||
|         if scope == "CLOUDFRONT": | ||||
|             self.region = GLOBAL_REGION | ||||
|         all_web_acls = self.wafv2_backend.list_web_acls() | ||||
|         response = {"NextMarker": "Not Implemented", "WebACLs": all_web_acls} | ||||
|         response_headers = {"Content-Type": "application/json"} | ||||
|         return 200, response_headers, json.dumps(response) | ||||
| 
 | ||||
| 
 | ||||
| # notes about region and scope | ||||
| # --scope = CLOUDFRONT is ALWAYS us-east-1 (but we use "global" instead to differentiate between REGIONAL us-east-1) | ||||
| # --scope = REGIONAL defaults to us-east-1, but could be anything if specified with --region=<anyRegion> | ||||
| # region is grabbed from the auth header, NOT from the body - even with --region flag | ||||
| # The CLOUDFRONT wacls in aws console are located in us-east-1 but the us-east-1 REGIONAL wacls are not included | ||||
							
								
								
									
										11
									
								
								moto/wafv2/urls.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								moto/wafv2/urls.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| from __future__ import unicode_literals | ||||
| 
 | ||||
| from .responses import WAFV2Response | ||||
| 
 | ||||
| url_bases = [ | ||||
|     "https?://wafv2.(.+).amazonaws.com", | ||||
| ] | ||||
| 
 | ||||
| url_paths = { | ||||
|     "{0}/": WAFV2Response.dispatch, | ||||
| } | ||||
							
								
								
									
										21
									
								
								moto/wafv2/utils.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								moto/wafv2/utils.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| from moto.core import ACCOUNT_ID | ||||
| from moto.core.utils import pascal_to_camelcase, camelcase_to_underscores | ||||
| 
 | ||||
| 
 | ||||
| def make_arn_for_wacl(name, region_name, id, scope): | ||||
|     """https://docs.aws.amazon.com/waf/latest/developerguide/how-aws-waf-works.html - explains --scope (cloudfront vs regional)""" | ||||
| 
 | ||||
|     if scope == "REGIONAL": | ||||
|         scope = "regional" | ||||
|     elif scope == "CLOUDFRONT": | ||||
|         scope = "global" | ||||
|     return "arn:aws:wafv2:{}:{}:{}/webacl/{}/{}".format( | ||||
|         region_name, ACCOUNT_ID, scope, name, id | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| def pascal_to_underscores_dict(original_dict): | ||||
|     outdict = {} | ||||
|     for k, v in original_dict.items(): | ||||
|         outdict[camelcase_to_underscores(pascal_to_camelcase(k))] = v | ||||
|     return outdict | ||||
							
								
								
									
										0
									
								
								tests/test_wafv2/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								tests/test_wafv2/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										15
									
								
								tests/test_wafv2/test_helper_functions.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								tests/test_wafv2/test_helper_functions.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| def CREATE_WEB_ACL_BODY(name: str, scope: str) -> dict: | ||||
|     return { | ||||
|         "Scope": scope, | ||||
|         "Name": name, | ||||
|         "DefaultAction": {"Allow": {}}, | ||||
|         "VisibilityConfig": { | ||||
|             "SampledRequestsEnabled": False, | ||||
|             "CloudWatchMetricsEnabled": False, | ||||
|             "MetricName": "idk", | ||||
|         }, | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| def LIST_WEB_ACL_BODY(scope: str) -> dict: | ||||
|     return {"Scope": scope} | ||||
							
								
								
									
										105
									
								
								tests/test_wafv2/test_server.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								tests/test_wafv2/test_server.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,105 @@ | ||||
| from __future__ import unicode_literals | ||||
| import json | ||||
| import pytest | ||||
| 
 | ||||
| import sure  # noqa | ||||
| 
 | ||||
| import boto3 | ||||
| import botocore | ||||
| from botocore.exceptions import ClientError | ||||
| import moto.server as server | ||||
| from moto import mock_wafv2 | ||||
| from .test_helper_functions import CREATE_WEB_ACL_BODY, LIST_WEB_ACL_BODY | ||||
| from moto.core import ACCOUNT_ID | ||||
| 
 | ||||
| CREATE_WEB_ACL_HEADERS = { | ||||
|     "X-Amz-Target": "AWSWAF_20190729.CreateWebACL", | ||||
|     "Content-Type": "application/json", | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| LIST_WEB_ACL_HEADERS = { | ||||
|     "X-Amz-Target": "AWSWAF_20190729.ListWebACLs", | ||||
|     "Content-Type": "application/json", | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @mock_wafv2 | ||||
| def test_create_web_acl(): | ||||
|     backend = server.create_backend_app("wafv2") | ||||
|     test_client = backend.test_client() | ||||
| 
 | ||||
|     res = test_client.post( | ||||
|         "/", | ||||
|         headers=CREATE_WEB_ACL_HEADERS, | ||||
|         json=CREATE_WEB_ACL_BODY("John", "REGIONAL"), | ||||
|     ) | ||||
|     assert res.status_code == 200 | ||||
| 
 | ||||
|     web_acl = res.json["Summary"] | ||||
|     assert web_acl.get("Name") == "John" | ||||
|     assert web_acl.get("ARN").startswith( | ||||
|         "arn:aws:wafv2:us-east-1:{}:regional/webacl/John/".format(ACCOUNT_ID) | ||||
|     ) | ||||
| 
 | ||||
|     # Duplicate name - should raise error | ||||
|     res = test_client.post( | ||||
|         "/", | ||||
|         headers=CREATE_WEB_ACL_HEADERS, | ||||
|         json=CREATE_WEB_ACL_BODY("John", "REGIONAL"), | ||||
|     ) | ||||
|     assert res.status_code == 400 | ||||
|     assert ( | ||||
|         b"AWS WAF could not perform the operation because some resource in your request is a duplicate of an existing one." | ||||
|         in res.data | ||||
|     ) | ||||
|     assert b"WafV2DuplicateItem" in res.data | ||||
| 
 | ||||
|     res = test_client.post( | ||||
|         "/", | ||||
|         headers=CREATE_WEB_ACL_HEADERS, | ||||
|         json=CREATE_WEB_ACL_BODY("Carl", "CLOUDFRONT"), | ||||
|     ) | ||||
|     web_acl = res.json["Summary"] | ||||
|     assert web_acl.get("ARN").startswith( | ||||
|         "arn:aws:wafv2:global:{}:global/webacl/Carl/".format(ACCOUNT_ID) | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| @mock_wafv2 | ||||
| def test_list_web_ac_ls(): | ||||
|     backend = server.create_backend_app("wafv2") | ||||
|     test_client = backend.test_client() | ||||
| 
 | ||||
|     test_client.post( | ||||
|         "/", | ||||
|         headers=CREATE_WEB_ACL_HEADERS, | ||||
|         json=CREATE_WEB_ACL_BODY("John", "REGIONAL"), | ||||
|     ) | ||||
|     test_client.post( | ||||
|         "/", | ||||
|         headers=CREATE_WEB_ACL_HEADERS, | ||||
|         json=CREATE_WEB_ACL_BODY("JohnSon", "REGIONAL"), | ||||
|     ) | ||||
|     test_client.post( | ||||
|         "/", | ||||
|         headers=CREATE_WEB_ACL_HEADERS, | ||||
|         json=CREATE_WEB_ACL_BODY("Sarah", "CLOUDFRONT"), | ||||
|     ) | ||||
|     res = test_client.post( | ||||
|         "/", headers=LIST_WEB_ACL_HEADERS, json=LIST_WEB_ACL_BODY("REGIONAL") | ||||
|     ) | ||||
|     assert res.status_code == 200 | ||||
| 
 | ||||
|     web_acls = res.json["WebACLs"] | ||||
|     assert len(web_acls) == 2 | ||||
|     assert web_acls[0]["Name"] == "John" | ||||
|     assert web_acls[1]["Name"] == "JohnSon" | ||||
| 
 | ||||
|     res = test_client.post( | ||||
|         "/", headers=LIST_WEB_ACL_HEADERS, json=LIST_WEB_ACL_BODY("CLOUDFRONT") | ||||
|     ) | ||||
|     assert res.status_code == 200 | ||||
|     web_acls = res.json["WebACLs"] | ||||
|     assert len(web_acls) == 1 | ||||
|     assert web_acls[0]["Name"] == "Sarah" | ||||
							
								
								
									
										24
									
								
								tests/test_wafv2/test_utils.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								tests/test_wafv2/test_utils.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| import random | ||||
| import string | ||||
| import uuid | ||||
| 
 | ||||
| from moto.wafv2 import utils | ||||
| from moto.wafv2.utils import make_arn_for_wacl | ||||
| from moto.core import ACCOUNT_ID | ||||
| 
 | ||||
| 
 | ||||
| def test_make_arn_for_wacl(): | ||||
|     uniqueID = str(uuid.uuid4()) | ||||
|     region = "us-east-1" | ||||
|     name = "testName" | ||||
|     scope = "REGIONAL" | ||||
|     arn = make_arn_for_wacl(name, region, uniqueID, scope) | ||||
|     assert arn == "arn:aws:wafv2:{}:{}:regional/webacl/{}/{}".format( | ||||
|         region, ACCOUNT_ID, name, uniqueID | ||||
|     ) | ||||
| 
 | ||||
|     scope = "CLOUDFRONT" | ||||
|     arn = make_arn_for_wacl(name, region, uniqueID, scope) | ||||
|     assert arn == "arn:aws:wafv2:{}:{}:global/webacl/{}/{}".format( | ||||
|         region, ACCOUNT_ID, name, uniqueID | ||||
|     ) | ||||
							
								
								
									
										55
									
								
								tests/test_wafv2/test_wafv2.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								tests/test_wafv2/test_wafv2.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | ||||
| from __future__ import unicode_literals | ||||
| import json | ||||
| import pytest | ||||
| 
 | ||||
| import sure  # noqa | ||||
| import boto3 | ||||
| from botocore.exceptions import ClientError | ||||
| from moto import mock_wafv2 | ||||
| from .test_helper_functions import CREATE_WEB_ACL_BODY, LIST_WEB_ACL_BODY | ||||
| from moto.core import ACCOUNT_ID | ||||
| 
 | ||||
| 
 | ||||
| @mock_wafv2 | ||||
| def test_create_web_acl(): | ||||
| 
 | ||||
|     conn = boto3.client("wafv2", region_name="us-east-1") | ||||
|     res = conn.create_web_acl(**CREATE_WEB_ACL_BODY("John", "REGIONAL")) | ||||
|     web_acl = res["Summary"] | ||||
|     assert web_acl.get("Name") == "John" | ||||
|     assert web_acl.get("ARN").startswith( | ||||
|         "arn:aws:wafv2:us-east-1:{}:regional/webacl/John/".format(ACCOUNT_ID) | ||||
|     ) | ||||
|     # Duplicate name - should raise error | ||||
|     with pytest.raises(ClientError) as ex: | ||||
|         conn.create_web_acl(**CREATE_WEB_ACL_BODY("John", "REGIONAL")) | ||||
|     err = ex.value.response["Error"] | ||||
|     err["Message"].should.contain( | ||||
|         "AWS WAF could not perform the operation because some resource in your request is a duplicate of an existing one." | ||||
|     ) | ||||
|     err["Code"].should.equal("400") | ||||
| 
 | ||||
|     res = conn.create_web_acl(**CREATE_WEB_ACL_BODY("Carl", "CLOUDFRONT")) | ||||
|     web_acl = res["Summary"] | ||||
|     assert web_acl.get("ARN").startswith( | ||||
|         "arn:aws:wafv2:global:{}:global/webacl/Carl/".format(ACCOUNT_ID) | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| @mock_wafv2 | ||||
| def test_list_web_acl(): | ||||
| 
 | ||||
|     conn = boto3.client("wafv2", region_name="us-east-1") | ||||
|     conn.create_web_acl(**CREATE_WEB_ACL_BODY("Daphne", "REGIONAL")) | ||||
|     conn.create_web_acl(**CREATE_WEB_ACL_BODY("Penelope", "CLOUDFRONT")) | ||||
|     conn.create_web_acl(**CREATE_WEB_ACL_BODY("Sarah", "REGIONAL")) | ||||
|     res = conn.list_web_acls(**LIST_WEB_ACL_BODY("REGIONAL")) | ||||
|     web_acls = res["WebACLs"] | ||||
|     assert len(web_acls) == 2 | ||||
|     assert web_acls[0]["Name"] == "Daphne" | ||||
|     assert web_acls[1]["Name"] == "Sarah" | ||||
| 
 | ||||
|     res = conn.list_web_acls(**LIST_WEB_ACL_BODY("CLOUDFRONT")) | ||||
|     web_acls = res["WebACLs"] | ||||
|     assert len(web_acls) == 1 | ||||
|     assert web_acls[0]["Name"] == "Penelope" | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user