266 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			266 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """Unit tests specific to VPC endpoint services."""
 | |
| import pytest
 | |
| 
 | |
| import boto3
 | |
| from botocore.exceptions import ClientError
 | |
| 
 | |
| from moto import mock_ec2, settings
 | |
| from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
 | |
| from unittest import SkipTest
 | |
| 
 | |
| 
 | |
| @mock_ec2
 | |
| def test_describe_vpc_endpoint_services_bad_args():
 | |
|     if settings.TEST_SERVER_MODE:
 | |
|         # Long-running operation - doesn't quite work in ServerMode, with parallel tests
 | |
|         # Probably needs some locking to force the initialization to only occur once
 | |
|         raise SkipTest("Can't run in ServerMode")
 | |
|     """Verify exceptions are raised for bad arguments."""
 | |
|     ec2 = boto3.client("ec2", region_name="us-west-1")
 | |
| 
 | |
|     # Bad service name -- a default service would typically be of the format:
 | |
|     # 'com.amazonaws.<region>.<service_name>'.
 | |
|     with pytest.raises(ClientError) as exc:
 | |
|         ec2.describe_vpc_endpoint_services(ServiceNames=["s3"])
 | |
|     err = exc.value.response["Error"]
 | |
|     assert err["Code"] == "InvalidServiceName"
 | |
|     assert "The Vpc Endpoint Service 's3' does not exist" in err["Message"]
 | |
| 
 | |
|     # Bad filter specification -- the filter name should be "service-type"
 | |
|     # not "ServiceType".
 | |
|     with pytest.raises(ClientError) as exc:
 | |
|         ec2.describe_vpc_endpoint_services(
 | |
|             ServiceNames=["com.amazonaws.us-west-1.s3"],
 | |
|             Filters=[{"Name": "ServiceType", "Values": ["Gateway"]}],
 | |
|         )
 | |
|     err = exc.value.response["Error"]
 | |
|     assert err["Code"] == "InvalidFilter"
 | |
|     assert "The filter 'ServiceType' is invalid" in err["Message"]
 | |
| 
 | |
|     # Bad token -- a token of "foo" has no correlation with this data.
 | |
|     with pytest.raises(ClientError) as exc:
 | |
|         ec2.describe_vpc_endpoint_services(
 | |
|             ServiceNames=["com.amazonaws.us-west-1.s3"],
 | |
|             Filters=[{"Name": "service-type", "Values": ["Gateway"]}],
 | |
|             NextToken="foo",
 | |
|         )
 | |
|     err = exc.value.response["Error"]
 | |
|     assert err["Code"] == "InvalidNextToken"
 | |
|     assert "The token 'foo' is invalid" in err["Message"]
 | |
| 
 | |
| 
 | |
| def fake_endpoint_services():
 | |
|     """Return a dummy list of default VPC endpoint services."""
 | |
|     return [
 | |
|         {
 | |
|             "AcceptanceRequired": False,
 | |
|             "AvailabilityZones": ["us-west-1a", "us-west-1b"],
 | |
|             "BaseEndpointDnsNames": ["access-analyzer.us-west-1.vpce.amazonaws.com"],
 | |
|             "ManagesVpcEndpoints": False,
 | |
|             "Owner": "amazon",
 | |
|             "PrivateDnsName": "access-analyzer.us-west-1.amazonaws.com",
 | |
|             "PrivateDnsNameVerificationState": "verified",
 | |
|             "PrivateDnsNames": [
 | |
|                 {"PrivateDnsName": "access-analyzer.us-west-1.amazonaws.com"},
 | |
|             ],
 | |
|             "ServiceId": "vpce-svc-1",
 | |
|             "ServiceName": "com.amazonaws.us-west-1.access-analyzer",
 | |
|             "ServiceType": [{"ServiceType": "Interface"}],
 | |
|             "Tags": [],
 | |
|             "VpcEndpointPolicySupported": True,
 | |
|         },
 | |
|         {
 | |
|             "AcceptanceRequired": False,
 | |
|             "AvailabilityZones": ["us-west-1a", "us-west-1b"],
 | |
|             "BaseEndpointDnsNames": ["config.us-west-1.vpce.amazonaws.com"],
 | |
|             "ManagesVpcEndpoints": False,
 | |
|             "Owner": "amazon",
 | |
|             "PrivateDnsName": "config.us-west-1.amazonaws.com",
 | |
|             "PrivateDnsNameVerificationState": "verified",
 | |
|             "PrivateDnsNames": [{"PrivateDnsName": "config.us-west-1.amazonaws.com"}],
 | |
|             "ServiceId": "vpce-svc-2",
 | |
|             "ServiceName": "com.amazonaws.us-west-1.config",
 | |
|             "ServiceType": [{"ServiceType": "Interface"}],
 | |
|             "Tags": [],
 | |
|             "VpcEndpointPolicySupported": True,
 | |
|         },
 | |
|         {
 | |
|             "AcceptanceRequired": True,
 | |
|             "AvailabilityZones": ["us-west-1a", "us-west-1b"],
 | |
|             "BaseEndpointDnsNames": ["s3.us-west-1.amazonaws.com"],
 | |
|             "ManagesVpcEndpoints": True,
 | |
|             "Owner": "amazon",
 | |
|             "ServiceId": "vpce-svc-3",
 | |
|             "ServiceName": "com.amazonaws.us-west-1.s3",
 | |
|             "ServiceType": [{"ServiceType": "Gateway"}],
 | |
|             "Tags": [{"Key": "Name", "Value": "s3_gw"}],
 | |
|             "VpcEndpointPolicySupported": False,
 | |
|         },
 | |
|         {
 | |
|             "AcceptanceRequired": False,
 | |
|             "AvailabilityZones": ["us-west-1a", "us-west-1b"],
 | |
|             "BaseEndpointDnsNames": ["s3.us-west-1.vpce.amazonaws.com"],
 | |
|             "ManagesVpcEndpoints": False,
 | |
|             "Owner": "amazon",
 | |
|             "ServiceId": "vpce-svc-4",
 | |
|             "ServiceName": "com.amazonaws.us-west-1.s3",
 | |
|             "ServiceType": [{"ServiceType": "Interface"}],
 | |
|             "Tags": [
 | |
|                 {"Key": "Name", "Value": "s3_if"},
 | |
|                 {"Key": "Environ", "Value": "test"},
 | |
|             ],
 | |
|             "VpcEndpointPolicySupported": True,
 | |
|         },
 | |
|     ]
 | |
| 
 | |
| 
 | |
| def validate_s3_service_endpoint_gateway(details):
 | |
|     """Validate response contains appropriate s3 Gateway service details."""
 | |
|     assert details["AcceptanceRequired"] is True
 | |
|     assert details["AvailabilityZones"] == ["us-west-1a", "us-west-1b"]
 | |
|     assert details["BaseEndpointDnsNames"] == ["s3.us-west-1.amazonaws.com"]
 | |
|     assert details["ManagesVpcEndpoints"] is True
 | |
|     assert details["Owner"] == "amazon"
 | |
|     assert details["ServiceId"] == "vpce-svc-3"
 | |
|     assert details["ServiceName"] == "com.amazonaws.us-west-1.s3"
 | |
|     assert details["ServiceType"] == [{"ServiceType": "Gateway"}]
 | |
|     assert details["VpcEndpointPolicySupported"] is False
 | |
|     assert details["Tags"][0] == {"Key": "Name", "Value": "s3_gw"}
 | |
| 
 | |
| 
 | |
| def validate_s3_service_endpoint_interface(details):
 | |
|     """Validate response contains appropriate s3 Gateway service details."""
 | |
|     assert details["AcceptanceRequired"] is False
 | |
|     assert details["AvailabilityZones"] == ["us-west-1a", "us-west-1b"]
 | |
|     assert details["BaseEndpointDnsNames"] == ["s3.us-west-1.vpce.amazonaws.com"]
 | |
|     assert details["ManagesVpcEndpoints"] is False
 | |
|     assert details["Owner"] == "amazon"
 | |
|     assert details["ServiceId"] == "vpce-svc-4"
 | |
|     assert details["ServiceName"] == "com.amazonaws.us-west-1.s3"
 | |
|     assert details["ServiceType"] == [{"ServiceType": "Interface"}]
 | |
|     assert details["VpcEndpointPolicySupported"] is True
 | |
|     assert details["Tags"][0] == {"Key": "Name", "Value": "s3_if"}
 | |
|     assert details["Tags"][1] == {"Key": "Environ", "Value": "test"}
 | |
| 
 | |
| 
 | |
| @mock_ec2
 | |
| def test_describe_vpc_endpoint_services_filters():
 | |
|     """Verify that different type of filters return the expected results."""
 | |
|     from moto.ec2.models import ec2_backends  # pylint: disable=import-outside-toplevel
 | |
| 
 | |
|     ec2_backend = ec2_backends[ACCOUNT_ID]["us-west-1"]
 | |
|     test_data = fake_endpoint_services()
 | |
| 
 | |
|     # Allow access to _filter_endpoint_services as it provides the best
 | |
|     # means of testing this logic.
 | |
|     # pylint: disable=protected-access
 | |
| 
 | |
|     # Test a service name filter, using s3 as the service name.
 | |
|     filtered_services = ec2_backend._filter_endpoint_services(
 | |
|         ["com.amazonaws.us-west-1.s3"], [], test_data
 | |
|     )
 | |
|     assert len(filtered_services) == 2
 | |
|     validate_s3_service_endpoint_gateway(filtered_services[0])
 | |
|     validate_s3_service_endpoint_interface(filtered_services[1])
 | |
| 
 | |
|     # Test a service type filter.
 | |
|     filtered_services = ec2_backend._filter_endpoint_services(
 | |
|         [], [{"Name": "service-type", "Value": ["Gateway"]}], test_data
 | |
|     )
 | |
|     assert len(filtered_services) == 1
 | |
|     validate_s3_service_endpoint_gateway(filtered_services[0])
 | |
| 
 | |
|     # Test a tag key/value filter.
 | |
|     filtered_services = ec2_backend._filter_endpoint_services(
 | |
|         [], [{"Name": "tag-key", "Value": ["Name"]}], test_data
 | |
|     )
 | |
|     assert len(filtered_services) == 2
 | |
|     validate_s3_service_endpoint_gateway(filtered_services[0])
 | |
|     validate_s3_service_endpoint_interface(filtered_services[1])
 | |
| 
 | |
|     # Test a tag key filter.
 | |
|     filtered_services = ec2_backend._filter_endpoint_services(
 | |
|         [], [{"Name": "tag:Environ", "Value": ["test"]}], test_data
 | |
|     )
 | |
|     assert len(filtered_services) == 1
 | |
|     validate_s3_service_endpoint_interface(filtered_services[0])
 | |
| 
 | |
|     # Test when there are no filters.
 | |
|     filtered_services = ec2_backend._filter_endpoint_services([], [], test_data)
 | |
|     assert len(filtered_services) == 4
 | |
| 
 | |
|     # Test a combo of service name and multiple filters.
 | |
|     filtered_services = ec2_backend._filter_endpoint_services(
 | |
|         ["com.amazonaws.us-west-1.s3"],
 | |
|         [{"Name": "tag:Environ", "Value": ["test"]}],
 | |
|         test_data,
 | |
|     )
 | |
|     assert len(filtered_services) == 1
 | |
|     validate_s3_service_endpoint_interface(filtered_services[0])
 | |
| 
 | |
| 
 | |
| @mock_ec2
 | |
| def test_describe_vpc_default_endpoint_services():
 | |
|     """Test successfull calls as well as the next_token arg."""
 | |
|     ec2 = boto3.client("ec2", region_name="us-west-1")
 | |
| 
 | |
|     # Verify the major components of the response. The unit test for filters
 | |
|     # verifies the contents of some of the ServicesDetails entries, so the
 | |
|     # focus of this unit test will be the larger components of the response.
 | |
|     all_services = ec2.describe_vpc_endpoint_services()
 | |
|     assert set(all_services.keys()) == set(
 | |
|         ["ServiceNames", "ServiceDetails", "ResponseMetadata"]
 | |
|     )
 | |
|     assert len(all_services["ServiceDetails"]) == len(all_services["ServiceNames"])
 | |
|     all_names = [x["ServiceName"] for x in all_services["ServiceDetails"]]
 | |
|     assert set(all_names) == set(all_services["ServiceNames"])
 | |
| 
 | |
|     # Verify the handling of the next token.
 | |
|     partial_services = ec2.describe_vpc_endpoint_services(MaxResults=2)
 | |
|     assert len(partial_services["ServiceDetails"]) == 2
 | |
|     assert len(partial_services["ServiceNames"]) == 2
 | |
|     assert all_names[0] == partial_services["ServiceNames"][0]
 | |
|     assert all_names[1] == partial_services["ServiceNames"][1]
 | |
|     assert all_names[0] == partial_services["ServiceDetails"][0]["ServiceName"]
 | |
|     assert all_names[1] == partial_services["ServiceDetails"][1]["ServiceName"]
 | |
|     assert partial_services["NextToken"] == (
 | |
|         all_services["ServiceDetails"][2]["ServiceId"]
 | |
|     )
 | |
| 
 | |
|     # Use the next token to receive another service.
 | |
|     more_services = ec2.describe_vpc_endpoint_services(
 | |
|         MaxResults=1, NextToken=partial_services["NextToken"]
 | |
|     )
 | |
|     assert len(more_services["ServiceDetails"]) == 1
 | |
|     assert len(more_services["ServiceNames"]) == 1
 | |
|     assert all_names[2] == more_services["ServiceNames"][0]
 | |
|     assert all_names[2] == more_services["ServiceDetails"][0]["ServiceName"]
 | |
|     assert more_services["NextToken"] == all_services["ServiceDetails"][3]["ServiceId"]
 | |
| 
 | |
|     # Use the next token to receive the remaining services.
 | |
|     remaining_services = ec2.describe_vpc_endpoint_services(
 | |
|         NextToken=more_services["NextToken"]
 | |
|     )
 | |
|     assert len(remaining_services["ServiceDetails"]) == len(all_names) - 3
 | |
|     assert "NextToken" not in remaining_services
 | |
| 
 | |
|     # Extract one service and verify all the fields.  This time the data is
 | |
|     # extracted from the actual response.
 | |
|     config_service = ec2.describe_vpc_endpoint_services(
 | |
|         ServiceNames=["com.amazonaws.us-west-1.config"]
 | |
|     )
 | |
|     details = config_service["ServiceDetails"][0]
 | |
|     assert details["AcceptanceRequired"] is False
 | |
|     assert details["AvailabilityZones"] == ["us-west-1a", "us-west-1b"]
 | |
|     assert details["BaseEndpointDnsNames"] == ["config.us-west-1.vpce.amazonaws.com"]
 | |
|     assert details["ManagesVpcEndpoints"] is False
 | |
|     assert details["Owner"] == "amazon"
 | |
|     assert details["PrivateDnsName"] == "config.us-west-1.amazonaws.com"
 | |
|     assert details["PrivateDnsNames"] == [
 | |
|         {"PrivateDnsName": "config.us-west-1.amazonaws.com"}
 | |
|     ]
 | |
|     assert details["PrivateDnsNameVerificationState"] == "verified"
 | |
|     assert details["ServiceName"] == "com.amazonaws.us-west-1.config"
 | |
|     assert details["ServiceType"] == [{"ServiceType": "Interface"}]
 | |
|     assert details["VpcEndpointPolicySupported"] is True
 |