diff --git a/moto/ec2/exceptions.py b/moto/ec2/exceptions.py
index 780ed933c041..9163cca1fdab 100644
--- a/moto/ec2/exceptions.py
+++ b/moto/ec2/exceptions.py
@@ -632,21 +632,23 @@ def __init__(self, cidr_block: str):
super().__init__("InvalidVpc.Range", f"The CIDR '{cidr_block}' is invalid.")
-# accept exception
+# Raised when attempting to accept a VPC peering connection request in own account but in the requester region
class OperationNotPermitted2(EC2ClientError):
def __init__(self, client_region: str, pcx_id: str, acceptor_region: str):
super().__init__(
"OperationNotPermitted",
- f"Incorrect region ({client_region}) specified for this request.VPC peering connection {pcx_id} must be accepted in region {acceptor_region}",
+ f"Incorrect region ({client_region}) specified for this request. "
+ f"VPC peering connection {pcx_id} must be accepted in region {acceptor_region}",
)
-# reject exception
+# Raised when attempting to reject a VPC peering connection request in own account but in the requester region
class OperationNotPermitted3(EC2ClientError):
def __init__(self, client_region: str, pcx_id: str, acceptor_region: str):
super().__init__(
"OperationNotPermitted",
- f"Incorrect region ({client_region}) specified for this request.VPC peering connection {pcx_id} must be accepted or rejected in region {acceptor_region}",
+ f"Incorrect region ({client_region}) specified for this request. "
+ f"VPC peering connection {pcx_id} must be accepted or rejected in region {acceptor_region}",
)
@@ -658,6 +660,15 @@ def __init__(self, instance_id: str):
)
+# Raised when attempting to accept or reject a VPC peering connection request for a VPC not belonging to self
+class OperationNotPermitted5(EC2ClientError):
+ def __init__(self, account_id: str, pcx_id: str, operation: str):
+ super().__init__(
+ "OperationNotPermitted",
+ f"User ({account_id}) cannot {operation} peering {pcx_id}",
+ )
+
+
class InvalidLaunchTemplateNameAlreadyExistsError(EC2ClientError):
def __init__(self) -> None:
super().__init__(
diff --git a/moto/ec2/models/transit_gateway_attachments.py b/moto/ec2/models/transit_gateway_attachments.py
index 2ed80b05d880..0bc535085e47 100644
--- a/moto/ec2/models/transit_gateway_attachments.py
+++ b/moto/ec2/models/transit_gateway_attachments.py
@@ -95,7 +95,7 @@ def __init__(
"region": region_name,
"transitGatewayId": transit_gateway_id,
}
- self.status = PeeringConnectionStatus()
+ self.status = PeeringConnectionStatus(accepter_id=peer_account_id)
class TransitGatewayAttachmentBackend:
@@ -342,5 +342,5 @@ def delete_transit_gateway_peering_attachment(
transit_gateway_attachment_id
]
transit_gateway_attachment.state = "deleted"
- transit_gateway_attachment.status.deleted() # type: ignore[attr-defined]
+ transit_gateway_attachment.status.deleted(deleter_id=self.account_id) # type: ignore[attr-defined]
return transit_gateway_attachment
diff --git a/moto/ec2/models/vpc_peering_connections.py b/moto/ec2/models/vpc_peering_connections.py
index 0498080fdd27..075f526fe9ae 100644
--- a/moto/ec2/models/vpc_peering_connections.py
+++ b/moto/ec2/models/vpc_peering_connections.py
@@ -7,6 +7,7 @@
InvalidVPCPeeringConnectionStateTransitionError,
OperationNotPermitted2,
OperationNotPermitted3,
+ OperationNotPermitted5,
)
from .core import TaggedEC2Resource
from .vpcs import VPC
@@ -14,21 +15,24 @@
class PeeringConnectionStatus:
- def __init__(self, code: str = "initiating-request", message: str = ""):
+ def __init__(
+ self, accepter_id: str, code: str = "initiating-request", message: str = ""
+ ):
+ self.accepter_id = accepter_id
self.code = code
self.message = message
- def deleted(self) -> None:
+ def deleted(self, deleter_id: str) -> None:
self.code = "deleted"
- self.message = "Deleted by {deleter ID}"
+ self.message = f"Deleted by {deleter_id}"
def initiating(self) -> None:
self.code = "initiating-request"
- self.message = "Initiating Request to {accepter ID}"
+ self.message = f"Initiating Request to {self.accepter_id}"
def pending(self) -> None:
self.code = "pending-acceptance"
- self.message = "Pending Acceptance by {accepter ID}"
+ self.message = f"Pending Acceptance by {self.accepter_id}"
def accept(self) -> None:
self.code = "active"
@@ -61,7 +65,7 @@ def __init__(
self.requester_options = self.DEFAULT_OPTIONS.copy()
self.accepter_options = self.DEFAULT_OPTIONS.copy()
self.add_tags(tags or {})
- self._status = PeeringConnectionStatus()
+ self._status = PeeringConnectionStatus(accepter_id=peer_vpc.owner_id)
@staticmethod
def cloudformation_name_type() -> str:
@@ -79,7 +83,7 @@ def create_from_cloudformation_json( # type: ignore[misc]
cloudformation_json: Any,
account_id: str,
region_name: str,
- **kwargs: Any
+ **kwargs: Any,
) -> "VPCPeeringConnection":
from ..models import ec2_backends
@@ -120,11 +124,15 @@ def create_vpc_peering_connection(
vpc_pcx = VPCPeeringConnection(self, vpc_pcx_id, vpc, peer_vpc, tags)
vpc_pcx._status.pending()
self.vpc_pcxs[vpc_pcx_id] = vpc_pcx
- # insert cross region peering info
- if vpc.ec2_backend.region_name != peer_vpc.ec2_backend.region_name:
- for vpc_pcx_cx in peer_vpc.ec2_backend.get_vpc_pcx_refs():
- if vpc_pcx_cx.region_name == peer_vpc.ec2_backend.region_name:
- vpc_pcx_cx.vpc_pcxs[vpc_pcx_id] = vpc_pcx
+ # insert cross-account/cross-region peering info
+ if vpc.owner_id != peer_vpc.owner_id or vpc.region != peer_vpc.region:
+ for backend in peer_vpc.ec2_backend.get_vpc_pcx_refs():
+ if (
+ backend.account_id == peer_vpc.owner_id
+ and backend.region_name == peer_vpc.region
+ ):
+ backend.vpc_pcxs[vpc_pcx_id] = vpc_pcx
+
return vpc_pcx
def describe_vpc_peering_connections(
@@ -142,16 +150,24 @@ def get_vpc_peering_connection(self, vpc_pcx_id: str) -> VPCPeeringConnection:
def delete_vpc_peering_connection(self, vpc_pcx_id: str) -> VPCPeeringConnection:
deleted = self.get_vpc_peering_connection(vpc_pcx_id)
- deleted._status.deleted()
+ deleted._status.deleted(deleter_id=self.account_id) # type: ignore[attr-defined]
return deleted
def accept_vpc_peering_connection(self, vpc_pcx_id: str) -> VPCPeeringConnection:
vpc_pcx = self.get_vpc_peering_connection(vpc_pcx_id)
- # if cross region need accepter from another region
- pcx_req_region = vpc_pcx.vpc.ec2_backend.region_name
- pcx_acp_region = vpc_pcx.peer_vpc.ec2_backend.region_name
+
+ # validate cross-account acceptance
+ req_account_id = vpc_pcx.vpc.owner_id
+ acp_account_id = vpc_pcx.peer_vpc.owner_id
+ if req_account_id != acp_account_id and self.account_id != acp_account_id: # type: ignore[attr-defined]
+ raise OperationNotPermitted5(self.account_id, vpc_pcx_id, "accept") # type: ignore[attr-defined]
+
+ # validate cross-region acceptance
+ pcx_req_region = vpc_pcx.vpc.region
+ pcx_acp_region = vpc_pcx.peer_vpc.region
if pcx_req_region != pcx_acp_region and self.region_name == pcx_req_region: # type: ignore[attr-defined]
raise OperationNotPermitted2(self.region_name, vpc_pcx.id, pcx_acp_region) # type: ignore[attr-defined]
+
if vpc_pcx._status.code != "pending-acceptance":
raise InvalidVPCPeeringConnectionStateTransitionError(vpc_pcx.id)
vpc_pcx._status.accept()
@@ -159,11 +175,19 @@ def accept_vpc_peering_connection(self, vpc_pcx_id: str) -> VPCPeeringConnection
def reject_vpc_peering_connection(self, vpc_pcx_id: str) -> VPCPeeringConnection:
vpc_pcx = self.get_vpc_peering_connection(vpc_pcx_id)
- # if cross region need accepter from another region
- pcx_req_region = vpc_pcx.vpc.ec2_backend.region_name
- pcx_acp_region = vpc_pcx.peer_vpc.ec2_backend.region_name
+
+ # validate cross-account rejection
+ req_account_id = vpc_pcx.vpc.owner_id
+ acp_account_id = vpc_pcx.peer_vpc.owner_id
+ if req_account_id != acp_account_id and self.account_id != acp_account_id: # type: ignore[attr-defined]
+ raise OperationNotPermitted5(self.account_id, vpc_pcx_id, "reject") # type: ignore[attr-defined]
+
+ # validate cross-region acceptance
+ pcx_req_region = vpc_pcx.vpc.region
+ pcx_acp_region = vpc_pcx.peer_vpc.region
if pcx_req_region != pcx_acp_region and self.region_name == pcx_req_region: # type: ignore[attr-defined]
raise OperationNotPermitted3(self.region_name, vpc_pcx.id, pcx_acp_region) # type: ignore[attr-defined]
+
if vpc_pcx._status.code != "pending-acceptance":
raise InvalidVPCPeeringConnectionStateTransitionError(vpc_pcx.id)
vpc_pcx._status.reject()
diff --git a/moto/ec2/models/vpcs.py b/moto/ec2/models/vpcs.py
index badb85b196ad..73ae96e8b2f7 100644
--- a/moto/ec2/models/vpcs.py
+++ b/moto/ec2/models/vpcs.py
@@ -205,6 +205,10 @@ def __init__(
def owner_id(self) -> str:
return self.ec2_backend.account_id
+ @property
+ def region(self) -> str:
+ return self.ec2_backend.region_name
+
@staticmethod
def cloudformation_name_type() -> str:
return ""
diff --git a/moto/ec2/responses/vpc_peering_connections.py b/moto/ec2/responses/vpc_peering_connections.py
index a85b5fffce42..cae1f7df3569 100644
--- a/moto/ec2/responses/vpc_peering_connections.py
+++ b/moto/ec2/responses/vpc_peering_connections.py
@@ -3,21 +3,23 @@
class VPCPeeringConnections(EC2BaseResponse):
def create_vpc_peering_connection(self) -> str:
- peer_region = self._get_param("PeerRegion")
tags = self._parse_tag_specification().get("vpc-peering-connection", {})
- if peer_region == self.region or peer_region is None:
- peer_vpc = self.ec2_backend.get_vpc(self._get_param("PeerVpcId"))
- else:
- from moto.ec2.models import ec2_backends
+ account_id = self._get_param("PeerOwnerId") or self.current_account
+ region_name = self._get_param("PeerRegion") or self.region
- peer_vpc = ec2_backends[self.current_account][peer_region].get_vpc(
- self._get_param("PeerVpcId")
- )
vpc = self.ec2_backend.get_vpc(self._get_param("VpcId"))
+
+ # Peer VPC could belong to another account or region
+ from moto.ec2.models import ec2_backends
+
+ peer_vpc = ec2_backends[account_id][region_name].get_vpc(
+ self._get_param("PeerVpcId")
+ )
+
vpc_pcx = self.ec2_backend.create_vpc_peering_connection(vpc, peer_vpc, tags)
template = self.response_template(CREATE_VPC_PEERING_CONNECTION_RESPONSE)
- return template.render(account_id=self.current_account, vpc_pcx=vpc_pcx)
+ return template.render(vpc_pcx=vpc_pcx)
def delete_vpc_peering_connection(self) -> str:
vpc_pcx_id = self._get_param("VpcPeeringConnectionId")
@@ -31,13 +33,13 @@ def describe_vpc_peering_connections(self) -> str:
vpc_peering_ids=ids
)
template = self.response_template(DESCRIBE_VPC_PEERING_CONNECTIONS_RESPONSE)
- return template.render(account_id=self.current_account, vpc_pcxs=vpc_pcxs)
+ return template.render(vpc_pcxs=vpc_pcxs)
def accept_vpc_peering_connection(self) -> str:
vpc_pcx_id = self._get_param("VpcPeeringConnectionId")
vpc_pcx = self.ec2_backend.accept_vpc_peering_connection(vpc_pcx_id)
template = self.response_template(ACCEPT_VPC_PEERING_CONNECTION_RESPONSE)
- return template.render(account_id=self.current_account, vpc_pcx=vpc_pcx)
+ return template.render(vpc_pcx=vpc_pcx)
def reject_vpc_peering_connection(self) -> str:
vpc_pcx_id = self._get_param("VpcPeeringConnectionId")
@@ -68,39 +70,46 @@ def modify_vpc_peering_connection_options(self) -> str:
7a62c49f-347e-4fc4-9331-6e8eEXAMPLE
- {{ vpc_pcx.id }}
-
- {{ account_id }}
+ {{ vpc_pcx.id }}
+
+ {{ vpc_pcx.vpc.owner_id }}
+ {{ vpc_pcx.vpc.region }}
{{ vpc_pcx.vpc.id }}
{{ vpc_pcx.vpc.cidr_block }}
+
+
{{ vpc_pcx.requester_options.AllowEgressFromLocalClassicLinkToRemoteVpc or '' }}
{{ vpc_pcx.requester_options.AllowEgressFromLocalVpcToRemoteClassicLink or '' }}
{{ vpc_pcx.requester_options.AllowDnsResolutionFromRemoteVpc or '' }}
-
-
- {{ account_id }}
- {{ vpc_pcx.peer_vpc.id }}
-
- {{ vpc_pcx.accepter_options.AllowEgressFromLocalClassicLinkToRemoteVpc or '' }}
- {{ vpc_pcx.accepter_options.AllowEgressFromLocalVpcToRemoteClassicLink or '' }}
- {{ vpc_pcx.accepter_options.AllowDnsResolutionFromRemoteVpc or '' }}
-
-
-
+
+
+ {{ vpc_pcx.peer_vpc.owner_id }}
+ {{ vpc_pcx.peer_vpc.region }}
+ {{ vpc_pcx.peer_vpc.id }}
+ {{ vpc_pcx.peer_vpc.cidr_block }}
+
+
+
+ {{ vpc_pcx.accepter_options.AllowEgressFromLocalClassicLinkToRemoteVpc or '' }}
+ {{ vpc_pcx.accepter_options.AllowEgressFromLocalVpcToRemoteClassicLink or '' }}
+ {{ vpc_pcx.accepter_options.AllowDnsResolutionFromRemoteVpc or '' }}
+
+
+
initiating-request
- Initiating Request to {accepter ID}
-
- 2014-02-18T14:37:25.000Z
-
- {% for tag in vpc_pcx.get_tags() %}
- -
- {{ tag.key }}
- {{ tag.value }}
-
- {% endfor %}
-
+ Initiating Request to {{ vpc_pcx.peer_vpc.owner_id }}
+
+ 2014-02-18T14:37:25.000Z
+
+ {% for tag in vpc_pcx.get_tags() %}
+ -
+ {{ tag.key }}
+ {{ tag.value }}
+
+ {% endfor %}
+
"""
@@ -113,10 +122,12 @@ def modify_vpc_peering_connection_options(self) -> str:
-
{{ vpc_pcx.id }}
- {{ account_id }}
+ {{ vpc_pcx.vpc.owner_id }}
+ {{ vpc_pcx.vpc.region }}
{{ vpc_pcx.vpc.id }}
{{ vpc_pcx.vpc.cidr_block }}
- {{ vpc_pcx.vpc.ec2_backend.region_name }}
+
+
{{ vpc_pcx.requester_options.AllowEgressFromLocalClassicLinkToRemoteVpc or '' }}
{{ vpc_pcx.requester_options.AllowEgressFromLocalVpcToRemoteClassicLink or '' }}
@@ -124,10 +135,12 @@ def modify_vpc_peering_connection_options(self) -> str:
- {{ account_id }}
+ {{ vpc_pcx.peer_vpc.owner_id }}
+ {{ vpc_pcx.peer_vpc.region }}
{{ vpc_pcx.peer_vpc.id }}
{{ vpc_pcx.peer_vpc.cidr_block }}
- {{ vpc_pcx.peer_vpc.ec2_backend.region_name }}
+
+
{{ vpc_pcx.accepter_options.AllowEgressFromLocalClassicLinkToRemoteVpc or '' }}
{{ vpc_pcx.accepter_options.AllowEgressFromLocalVpcToRemoteClassicLink or '' }}
@@ -165,21 +178,30 @@ def modify_vpc_peering_connection_options(self) -> str:
{{ vpc_pcx.id }}
- {{ account_id }}
- {{ vpc_pcx.vpc.id }}
- {{ vpc_pcx.vpc.cidr_block }}
- {{ vpc_pcx.vpc.ec2_backend.region_name }}
+ {{ vpc_pcx.vpc.owner_id }}
+ {{ vpc_pcx.vpc.region }}
+ {{ vpc_pcx.vpc.id }}
+ {{ vpc_pcx.vpc.cidr_block }}
+
+
+
+ {{ vpc_pcx.requester_options.AllowEgressFromLocalClassicLinkToRemoteVpc or '' }}
+ {{ vpc_pcx.requester_options.AllowEgressFromLocalVpcToRemoteClassicLink or '' }}
+ {{ vpc_pcx.requester_options.AllowDnsResolutionFromRemoteVpc or '' }}
+
- {{ account_id }}
+ {{ vpc_pcx.peer_vpc.owner_id }}
+ {{ vpc_pcx.peer_vpc.region }}
{{ vpc_pcx.peer_vpc.id }}
{{ vpc_pcx.peer_vpc.cidr_block }}
+
+
{{ vpc_pcx.accepter_options.AllowEgressFromLocalClassicLinkToRemoteVpc or '' }}
{{ vpc_pcx.accepter_options.AllowEgressFromLocalVpcToRemoteClassicLink or '' }}
{{ vpc_pcx.accepter_options.AllowDnsResolutionFromRemoteVpc or '' }}
- {{ vpc_pcx.peer_vpc.ec2_backend.region_name }}
{{ vpc_pcx._status.code }}
diff --git a/tests/test_ec2/test_vpc_peering.py b/tests/test_ec2/test_vpc_peering.py
index 36da5588917d..4bf4bc0d23c8 100644
--- a/tests/test_ec2/test_vpc_peering.py
+++ b/tests/test_ec2/test_vpc_peering.py
@@ -1,9 +1,12 @@
+import os
+from unittest import mock
+
import boto3
import pytest
from botocore.exceptions import ClientError
-from moto import mock_ec2
+from moto import mock_ec2, settings
def create_vpx_pcx(ec2, client):
@@ -40,6 +43,7 @@ def test_vpc_peering_connections_get_all_boto3():
if vpc_pcx["VpcPeeringConnectionId"] == vpc_pcx_id
][0]
assert my_vpc_pcx["Status"]["Code"] == "pending-acceptance"
+ assert my_vpc_pcx["Status"]["Message"] == "Pending Acceptance by 123456789012"
@mock_ec2
@@ -115,24 +119,84 @@ def test_vpc_peering_connections_delete_boto3():
@mock_ec2
-def test_vpc_peering_connections_cross_region():
+@pytest.mark.parametrize(
+ "account1,account2",
+ [
+ pytest.param("111111111111", "111111111111", id="within account"),
+ pytest.param("111111111111", "222222222222", id="across accounts"),
+ ],
+)
+@pytest.mark.skipif(
+ settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
+)
+def test_vpc_peering_connections_cross_region(account1, account2):
# create vpc in us-west-1 and ap-northeast-1
- ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
- vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
- ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
- vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
+ vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
+
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
+ ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
+ vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+
# create peering
- vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
- VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
+ vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
+ VpcId=vpc_usw1.id,
+ PeerVpcId=vpc_apn1.id,
+ PeerRegion="ap-northeast-1",
+ PeerOwnerId=account2,
+ )
+
+ assert (
+ vpc_pcx_usw1["VpcPeeringConnection"]["Status"]["Code"] == "initiating-request"
+ )
+ assert (
+ vpc_pcx_usw1["VpcPeeringConnection"]["Status"]["Message"]
+ == f"Initiating Request to {account2}"
+ )
+ assert (
+ vpc_pcx_usw1["VpcPeeringConnection"]["RequesterVpcInfo"]["VpcId"] == vpc_usw1.id
+ )
+ assert (
+ vpc_pcx_usw1["VpcPeeringConnection"]["RequesterVpcInfo"]["CidrBlock"]
+ == "10.90.0.0/16"
+ )
+ assert (
+ vpc_pcx_usw1["VpcPeeringConnection"]["RequesterVpcInfo"]["OwnerId"] == account1
+ )
+ assert (
+ vpc_pcx_usw1["VpcPeeringConnection"]["RequesterVpcInfo"]["Region"]
+ == "us-west-1"
+ )
+ assert (
+ vpc_pcx_usw1["VpcPeeringConnection"]["AccepterVpcInfo"]["VpcId"] == vpc_apn1.id
+ )
+ assert (
+ vpc_pcx_usw1["VpcPeeringConnection"]["AccepterVpcInfo"]["CidrBlock"]
+ == "10.20.0.0/16"
+ )
+ assert (
+ vpc_pcx_usw1["VpcPeeringConnection"]["AccepterVpcInfo"]["OwnerId"] == account2
+ )
+ assert (
+ vpc_pcx_usw1["VpcPeeringConnection"]["AccepterVpcInfo"]["Region"]
+ == "ap-northeast-1"
)
- assert vpc_pcx_usw1.status["Code"] == "initiating-request"
- assert vpc_pcx_usw1.requester_vpc.id == vpc_usw1.id
- assert vpc_pcx_usw1.accepter_vpc.id == vpc_apn1.id
+
# test cross region vpc peering connection exist
- vpc_pcx_apn1 = ec2_apn1.VpcPeeringConnection(vpc_pcx_usw1.id)
- assert vpc_pcx_apn1.id == vpc_pcx_usw1.id
- assert vpc_pcx_apn1.requester_vpc.id == vpc_usw1.id
- assert vpc_pcx_apn1.accepter_vpc.id == vpc_apn1.id
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
+ vpc_pcx_apn1 = ec2_apn1.VpcPeeringConnection(
+ vpc_pcx_usw1["VpcPeeringConnection"]["VpcPeeringConnectionId"]
+ )
+ assert (
+ vpc_pcx_apn1.id
+ == vpc_pcx_usw1["VpcPeeringConnection"]["VpcPeeringConnectionId"]
+ )
+ assert vpc_pcx_apn1.requester_vpc.id == vpc_usw1.id
+ assert vpc_pcx_apn1.accepter_vpc.id == vpc_apn1.id
+
# Quick check to verify the options have a default value
accepter_options = vpc_pcx_apn1.accepter_vpc_info["PeeringOptions"]
assert accepter_options["AllowDnsResolutionFromRemoteVpc"] is False
@@ -145,28 +209,50 @@ def test_vpc_peering_connections_cross_region():
@mock_ec2
-def test_modify_vpc_peering_connections_accepter_only():
+@pytest.mark.parametrize(
+ "account1,account2",
+ [
+ pytest.param("111111111111", "111111111111", id="within account"),
+ pytest.param("111111111111", "222222222222", id="across accounts"),
+ ],
+)
+@pytest.mark.skipif(
+ settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
+)
+def test_modify_vpc_peering_connections_accepter_only(account1, account2):
# create vpc in us-west-1 and ap-northeast-1
- ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
- client = boto3.client("ec2", region_name="us-west-1")
- vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
- ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
- vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
+ client = boto3.client("ec2", region_name="us-west-1")
+ vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
+
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
+ ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
+ vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+
# create peering
- vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
- VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
- )
- #
- client.modify_vpc_peering_connection_options(
- VpcPeeringConnectionId=vpc_pcx_usw1.id,
- AccepterPeeringConnectionOptions={"AllowDnsResolutionFromRemoteVpc": True},
- )
- # Accepter options are different
- vpc_pcx_usw1.reload()
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
+ VpcId=vpc_usw1.id,
+ PeerVpcId=vpc_apn1.id,
+ PeerRegion="ap-northeast-1",
+ PeerOwnerId=account2,
+ )
+
+ # modify peering connection options
+ client.modify_vpc_peering_connection_options(
+ VpcPeeringConnectionId=vpc_pcx_usw1.id,
+ AccepterPeeringConnectionOptions={"AllowDnsResolutionFromRemoteVpc": True},
+ )
+
+ # Accepter options are different
+ vpc_pcx_usw1.reload()
+
accepter_options = vpc_pcx_usw1.accepter_vpc_info["PeeringOptions"]
assert accepter_options["AllowDnsResolutionFromRemoteVpc"] is True
assert accepter_options["AllowEgressFromLocalClassicLinkToRemoteVpc"] is False
assert accepter_options["AllowEgressFromLocalVpcToRemoteClassicLink"] is False
+
# Requester options are untouched
requester_options = vpc_pcx_usw1.requester_vpc_info["PeeringOptions"]
assert requester_options["AllowDnsResolutionFromRemoteVpc"] is False
@@ -175,30 +261,50 @@ def test_modify_vpc_peering_connections_accepter_only():
@mock_ec2
-def test_modify_vpc_peering_connections_requester_only():
+@pytest.mark.parametrize(
+ "account1,account2",
+ [
+ pytest.param("111111111111", "111111111111", id="within account"),
+ pytest.param("111111111111", "222222222222", id="across accounts"),
+ ],
+)
+@pytest.mark.skipif(
+ settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
+)
+def test_modify_vpc_peering_connections_requester_only(account1, account2):
# create vpc in us-west-1 and ap-northeast-1
- ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
- client = boto3.client("ec2", region_name="us-west-1")
- vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
- ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
- vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
+ client = boto3.client("ec2", region_name="us-west-1")
+ vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
+
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
+ ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
+ vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+
# create peering
- vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
- VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
- )
- #
- client.modify_vpc_peering_connection_options(
- VpcPeeringConnectionId=vpc_pcx_usw1.id,
- RequesterPeeringConnectionOptions={
- "AllowEgressFromLocalVpcToRemoteClassicLink": True,
- },
- )
- # Requester options are different
- vpc_pcx_usw1.reload()
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
+ VpcId=vpc_usw1.id,
+ PeerVpcId=vpc_apn1.id,
+ PeerRegion="ap-northeast-1",
+ PeerOwnerId=account2,
+ )
+ #
+ client.modify_vpc_peering_connection_options(
+ VpcPeeringConnectionId=vpc_pcx_usw1.id,
+ RequesterPeeringConnectionOptions={
+ "AllowEgressFromLocalVpcToRemoteClassicLink": True,
+ },
+ )
+ # Requester options are different
+ vpc_pcx_usw1.reload()
+
requester_options = vpc_pcx_usw1.requester_vpc_info["PeeringOptions"]
assert requester_options["AllowDnsResolutionFromRemoteVpc"] is False
assert requester_options["AllowEgressFromLocalClassicLinkToRemoteVpc"] is False
assert requester_options["AllowEgressFromLocalVpcToRemoteClassicLink"] is True
+
# Accepter options are untouched
accepter_options = vpc_pcx_usw1.accepter_vpc_info["PeeringOptions"]
assert accepter_options["AllowDnsResolutionFromRemoteVpc"] is False
@@ -207,97 +313,180 @@ def test_modify_vpc_peering_connections_requester_only():
@mock_ec2
-def test_modify_vpc_peering_connections_unknown_vpc():
+@pytest.mark.parametrize(
+ "account1,account2",
+ [
+ pytest.param("111111111111", "111111111111", id="within account"),
+ pytest.param("111111111111", "222222222222", id="across accounts"),
+ ],
+)
+@pytest.mark.skipif(
+ settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
+)
+def test_modify_vpc_peering_connections_unknown_vpc(account1, account2):
# create vpc in us-west-1 and ap-northeast-1
- ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
- client = boto3.client("ec2", region_name="us-west-1")
- vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
- ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
- vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
+ client = boto3.client("ec2", region_name="us-west-1")
+ vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
+
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
+ ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
+ vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+
# create peering
- ec2_usw1.create_vpc_peering_connection(
- VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
- )
- #
- with pytest.raises(ClientError) as ex:
- client.modify_vpc_peering_connection_options(
- VpcPeeringConnectionId="vpx-unknown", RequesterPeeringConnectionOptions={}
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ ec2_usw1.create_vpc_peering_connection(
+ VpcId=vpc_usw1.id,
+ PeerVpcId=vpc_apn1.id,
+ PeerRegion="ap-northeast-1",
+ PeerOwnerId=account2,
)
+
+ with pytest.raises(ClientError) as ex:
+ client.modify_vpc_peering_connection_options(
+ VpcPeeringConnectionId="vpx-unknown",
+ RequesterPeeringConnectionOptions={},
+ )
err = ex.value.response["Error"]
assert err["Code"] == "InvalidVpcPeeringConnectionId.NotFound"
assert err["Message"] == "VpcPeeringConnectionID vpx-unknown does not exist."
@mock_ec2
-def test_vpc_peering_connections_cross_region_fail():
+@pytest.mark.parametrize(
+ "account1,account2",
+ [
+ pytest.param("111111111111", "111111111111", id="within account"),
+ pytest.param("111111111111", "222222222222", id="across accounts"),
+ ],
+)
+@pytest.mark.skipif(
+ settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
+)
+def test_vpc_peering_connections_cross_region_fail(account1, account2):
# create vpc in us-west-1 and ap-northeast-1
- ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
- vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
- ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
- vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
+ vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
+
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
+ ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
+ vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+
# create peering wrong region with no vpc
with pytest.raises(ClientError) as cm:
- ec2_usw1.create_vpc_peering_connection(
- VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-2"
- )
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ ec2_usw1.create_vpc_peering_connection(
+ VpcId=vpc_usw1.id,
+ PeerVpcId=vpc_apn1.id,
+ PeerRegion="ap-northeast-2",
+ PeerOwnerId=account2,
+ )
assert cm.value.response["Error"]["Code"] == "InvalidVpcID.NotFound"
@mock_ec2
-def test_describe_vpc_peering_connections_only_returns_requested_id():
+@pytest.mark.parametrize(
+ "account1,account2",
+ [
+ pytest.param("111111111111", "111111111111", id="within account"),
+ pytest.param("111111111111", "222222222222", id="across accounts"),
+ ],
+)
+@pytest.mark.skipif(
+ settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
+)
+def test_describe_vpc_peering_connections_only_returns_requested_id(account1, account2):
# create vpc in us-west-1 and ap-northeast-1
- ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
- vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
- ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
- vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
+ vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
+
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
+ ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
+ vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+
# create peering
- vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
- VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
- )
- vpc_pcx_usw2 = ec2_usw1.create_vpc_peering_connection(
- VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
- )
- # describe peering
- ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
- our_vpcx = [vpcx["VpcPeeringConnectionId"] for vpcx in retrieve_all(ec2_usw1)]
- assert vpc_pcx_usw1.id in our_vpcx
- assert vpc_pcx_usw2.id in our_vpcx
- assert vpc_apn1.id not in our_vpcx
-
- both_pcx = ec2_usw1.describe_vpc_peering_connections(
- VpcPeeringConnectionIds=[vpc_pcx_usw1.id, vpc_pcx_usw2.id]
- )["VpcPeeringConnections"]
- assert len(both_pcx) == 2
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
+ VpcId=vpc_usw1.id,
+ PeerVpcId=vpc_apn1.id,
+ PeerRegion="ap-northeast-1",
+ PeerOwnerId=account2,
+ )
+ vpc_pcx_usw2 = ec2_usw1.create_vpc_peering_connection(
+ VpcId=vpc_usw1.id,
+ PeerVpcId=vpc_apn1.id,
+ PeerRegion="ap-northeast-1",
+ PeerOwnerId=account2,
+ )
- one_pcx = ec2_usw1.describe_vpc_peering_connections(
- VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
- )["VpcPeeringConnections"]
- assert len(one_pcx) == 1
+ # describe peering
+ ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
+ our_vpcx = [vpcx["VpcPeeringConnectionId"] for vpcx in retrieve_all(ec2_usw1)]
+
+ assert vpc_pcx_usw1.id in our_vpcx
+ assert vpc_pcx_usw2.id in our_vpcx
+ assert vpc_apn1.id not in our_vpcx
+
+ both_pcx = ec2_usw1.describe_vpc_peering_connections(
+ VpcPeeringConnectionIds=[vpc_pcx_usw1.id, vpc_pcx_usw2.id]
+ )["VpcPeeringConnections"]
+ assert len(both_pcx) == 2
+
+ one_pcx = ec2_usw1.describe_vpc_peering_connections(
+ VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
+ )["VpcPeeringConnections"]
+ assert len(one_pcx) == 1
@mock_ec2
-def test_vpc_peering_connections_cross_region_accept():
+@pytest.mark.parametrize(
+ "account1,account2",
+ [
+ pytest.param("111111111111", "111111111111", id="within account"),
+ pytest.param("111111111111", "222222222222", id="across accounts"),
+ ],
+)
+@pytest.mark.skipif(
+ settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
+)
+def test_vpc_peering_connections_cross_region_accept(account1, account2):
# create vpc in us-west-1 and ap-northeast-1
- ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
- vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
- ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
- vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
+ vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
+
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
+ ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
+ vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+
# create peering
- vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
- VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
- )
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
+ VpcId=vpc_usw1.id,
+ PeerVpcId=vpc_apn1.id,
+ PeerRegion="ap-northeast-1",
+ PeerOwnerId=account2,
+ )
+
# accept peering from ap-northeast-1
- ec2_apn1 = boto3.client("ec2", region_name="ap-northeast-1")
- ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
- acp_pcx_apn1 = ec2_apn1.accept_vpc_peering_connection(
- VpcPeeringConnectionId=vpc_pcx_usw1.id
- )
- des_pcx_apn1 = ec2_usw1.describe_vpc_peering_connections(
- VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
- )
- des_pcx_usw1 = ec2_usw1.describe_vpc_peering_connections(
- VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
- )
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
+ ec2_apn1 = boto3.client("ec2", region_name="ap-northeast-1")
+ acp_pcx_apn1 = ec2_apn1.accept_vpc_peering_connection(
+ VpcPeeringConnectionId=vpc_pcx_usw1.id
+ )
+
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
+ des_pcx_apn1 = ec2_usw1.describe_vpc_peering_connections(
+ VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
+ )
+ des_pcx_usw1 = ec2_usw1.describe_vpc_peering_connections(
+ VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
+ )
+
assert acp_pcx_apn1["VpcPeeringConnection"]["Status"]["Code"] == "active"
assert (
acp_pcx_apn1["VpcPeeringConnection"]["AccepterVpcInfo"]["Region"]
@@ -328,102 +517,231 @@ def test_vpc_peering_connections_cross_region_accept():
@mock_ec2
-def test_vpc_peering_connections_cross_region_reject():
+@pytest.mark.parametrize(
+ "account1,account2",
+ [
+ pytest.param("111111111111", "111111111111", id="within account"),
+ pytest.param("111111111111", "222222222222", id="across accounts"),
+ ],
+)
+@pytest.mark.skipif(
+ settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
+)
+def test_vpc_peering_connections_cross_region_reject(account1, account2):
# create vpc in us-west-1 and ap-northeast-1
- ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
- vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
- ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
- vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
+ vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
+
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
+ ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
+ vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+
# create peering
- vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
- VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
- )
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
+ VpcId=vpc_usw1.id,
+ PeerVpcId=vpc_apn1.id,
+ PeerRegion="ap-northeast-1",
+ PeerOwnerId=account2,
+ )
+
# reject peering from ap-northeast-1
- ec2_apn1 = boto3.client("ec2", region_name="ap-northeast-1")
- ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
- rej_pcx_apn1 = ec2_apn1.reject_vpc_peering_connection(
- VpcPeeringConnectionId=vpc_pcx_usw1.id
- )
- des_pcx_apn1 = ec2_usw1.describe_vpc_peering_connections(
- VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
- )
- des_pcx_usw1 = ec2_usw1.describe_vpc_peering_connections(
- VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
- )
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
+ ec2_apn1 = boto3.client("ec2", region_name="ap-northeast-1")
+ rej_pcx_apn1 = ec2_apn1.reject_vpc_peering_connection(
+ VpcPeeringConnectionId=vpc_pcx_usw1.id
+ )
+
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
+ des_pcx_apn1 = ec2_usw1.describe_vpc_peering_connections(
+ VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
+ )
+ des_pcx_usw1 = ec2_usw1.describe_vpc_peering_connections(
+ VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
+ )
assert rej_pcx_apn1["Return"] is True
assert des_pcx_apn1["VpcPeeringConnections"][0]["Status"]["Code"] == "rejected"
assert des_pcx_usw1["VpcPeeringConnections"][0]["Status"]["Code"] == "rejected"
@mock_ec2
-def test_vpc_peering_connections_cross_region_delete():
+@pytest.mark.parametrize(
+ "account1,account2",
+ [
+ pytest.param("111111111111", "111111111111", id="within account"),
+ pytest.param("111111111111", "222222222222", id="across accounts"),
+ ],
+)
+@pytest.mark.skipif(
+ settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
+)
+def test_vpc_peering_connections_cross_region_delete(account1, account2):
# create vpc in us-west-1 and ap-northeast-1
- ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
- vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
- ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
- vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
+ vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
+
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
+ ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
+ vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+
# create peering
- vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
- VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
- )
- # reject peering from ap-northeast-1
- ec2_apn1 = boto3.client("ec2", region_name="ap-northeast-1")
- ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
- del_pcx_apn1 = ec2_apn1.delete_vpc_peering_connection(
- VpcPeeringConnectionId=vpc_pcx_usw1.id
- )
- des_pcx_apn1 = ec2_usw1.describe_vpc_peering_connections(
- VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
- )
- des_pcx_usw1 = ec2_usw1.describe_vpc_peering_connections(
- VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
- )
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
+ VpcId=vpc_usw1.id,
+ PeerVpcId=vpc_apn1.id,
+ PeerRegion="ap-northeast-1",
+ PeerOwnerId=account2,
+ )
+
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
+ # reject peering from ap-northeast-1
+ ec2_apn1 = boto3.client("ec2", region_name="ap-northeast-1")
+ del_pcx_apn1 = ec2_apn1.delete_vpc_peering_connection(
+ VpcPeeringConnectionId=vpc_pcx_usw1.id
+ )
+
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
+ des_pcx_apn1 = ec2_usw1.describe_vpc_peering_connections(
+ VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
+ )
+ des_pcx_usw1 = ec2_usw1.describe_vpc_peering_connections(
+ VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
+ )
+
assert del_pcx_apn1["Return"] is True
assert des_pcx_apn1["VpcPeeringConnections"][0]["Status"]["Code"] == "deleted"
+ assert (
+ des_pcx_apn1["VpcPeeringConnections"][0]["Status"]["Message"]
+ == f"Deleted by {account2}"
+ )
+
assert des_pcx_usw1["VpcPeeringConnections"][0]["Status"]["Code"] == "deleted"
+ assert (
+ des_pcx_usw1["VpcPeeringConnections"][0]["Status"]["Message"]
+ == f"Deleted by {account2}"
+ )
@mock_ec2
-def test_vpc_peering_connections_cross_region_accept_wrong_region():
+@pytest.mark.parametrize(
+ "account1,account2",
+ [
+ pytest.param("111111111111", "111111111111", id="within account"),
+ pytest.param("111111111111", "222222222222", id="across accounts"),
+ ],
+)
+@pytest.mark.skipif(
+ settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
+)
+def test_vpc_peering_connections_cross_region_accept_wrong_region(account1, account2):
# create vpc in us-west-1 and ap-northeast-1
- ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
- vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
- ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
- vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
+ vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
+
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
+ ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
+ vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+
# create peering
- vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
- VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
- )
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
+ VpcId=vpc_usw1.id,
+ PeerVpcId=vpc_apn1.id,
+ PeerRegion="ap-northeast-1",
+ PeerOwnerId=account2,
+ )
# accept wrong peering from us-west-1 which will raise error
- ec2_apn1 = boto3.client("ec2", region_name="ap-northeast-1")
- ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
- with pytest.raises(ClientError) as cm:
- ec2_usw1.accept_vpc_peering_connection(VpcPeeringConnectionId=vpc_pcx_usw1.id)
- assert cm.value.response["Error"]["Code"] == "OperationNotPermitted"
- exp_msg = f"Incorrect region (us-west-1) specified for this request.VPC peering connection {vpc_pcx_usw1.id} must be accepted in region ap-northeast-1"
- assert cm.value.response["Error"]["Message"] == exp_msg
+ # only applicable for cross-region intra-account peering.
+ if account1 == account2:
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
+ with pytest.raises(ClientError) as cm:
+ ec2_usw1.accept_vpc_peering_connection(
+ VpcPeeringConnectionId=vpc_pcx_usw1.id
+ )
+
+ assert cm.value.response["Error"]["Code"] == "OperationNotPermitted"
+ exp_msg = f"Incorrect region (us-west-1) specified for this request. VPC peering connection {vpc_pcx_usw1.id} must be accepted in region ap-northeast-1"
+ assert cm.value.response["Error"]["Message"] == exp_msg
+
+ # Ensure accepting peering from requester account raises
+ # only applicable for cross-region inter-account peering.
+ if account1 != account2:
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
+ with pytest.raises(ClientError) as cm:
+ ec2_usw1.accept_vpc_peering_connection(
+ VpcPeeringConnectionId=vpc_pcx_usw1.id
+ )
+
+ assert cm.value.response["Error"]["Code"] == "OperationNotPermitted"
+ exp_msg = f"User ({account1}) cannot accept peering {vpc_pcx_usw1.id}"
+ assert cm.value.response["Error"]["Message"] == exp_msg
@mock_ec2
-def test_vpc_peering_connections_cross_region_reject_wrong_region():
+@pytest.mark.parametrize(
+ "account1,account2",
+ [
+ pytest.param("111111111111", "111111111111", id="within account"),
+ pytest.param("111111111111", "222222222222", id="across accounts"),
+ ],
+)
+@pytest.mark.skipif(
+ settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
+)
+def test_vpc_peering_connections_cross_region_reject_wrong_region(account1, account2):
# create vpc in us-west-1 and ap-northeast-1
- ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
- vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
- ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
- vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
+ vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
+
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
+ ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
+ vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
+
# create peering
- vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
- VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
- )
- # reject wrong peering from us-west-1 which will raise error
- ec2_apn1 = boto3.client("ec2", region_name="ap-northeast-1")
- ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
- with pytest.raises(ClientError) as cm:
- ec2_usw1.reject_vpc_peering_connection(VpcPeeringConnectionId=vpc_pcx_usw1.id)
- assert cm.value.response["Error"]["Code"] == "OperationNotPermitted"
- exp_msg = f"Incorrect region (us-west-1) specified for this request.VPC peering connection {vpc_pcx_usw1.id} must be accepted or rejected in region ap-northeast-1"
- assert cm.value.response["Error"]["Message"] == exp_msg
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
+ VpcId=vpc_usw1.id,
+ PeerVpcId=vpc_apn1.id,
+ PeerRegion="ap-northeast-1",
+ PeerOwnerId=account2,
+ )
+
+ # reject wrong peering from us-west-1 which will raise error.
+ # only applicable for cross-region intra-account peering.
+ if account1 == account2:
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
+ with pytest.raises(ClientError) as cm:
+ ec2_usw1.reject_vpc_peering_connection(
+ VpcPeeringConnectionId=vpc_pcx_usw1.id
+ )
+
+ assert cm.value.response["Error"]["Code"] == "OperationNotPermitted"
+ exp_msg = f"Incorrect region (us-west-1) specified for this request. VPC peering connection {vpc_pcx_usw1.id} must be accepted or rejected in region ap-northeast-1"
+ assert cm.value.response["Error"]["Message"] == exp_msg
+
+ # Ensure rejecting peering from requester account raises
+ # only applicable for cross-region inter-account peering.
+ if account1 != account2:
+ with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
+ ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
+ with pytest.raises(ClientError) as cm:
+ ec2_usw1.reject_vpc_peering_connection(
+ VpcPeeringConnectionId=vpc_pcx_usw1.id
+ )
+
+ assert cm.value.response["Error"]["Code"] == "OperationNotPermitted"
+ exp_msg = f"User ({account1}) cannot reject peering {vpc_pcx_usw1.id}"
+ assert cm.value.response["Error"]["Message"] == exp_msg
def retrieve_all(client):