aws-tgw-peering-routes-to-peer
match (record)
{
"field": "State",
"resource_type": "AWS::EC2::TransitGatewayPeeringAttachment"
}
where
peering_attachment.State == 'available'
emit
| source type | TransitGateway |
|---|---|
| target type | Network |
| source | <local TransitGateway node (RequesterTgwInfo.TransitGatewayId)> |
| target | <peer VirtualNetwork (AccepterTgwInfo.TransitGatewayId's attached VPCs — modeled as a Network placeholder until peer account facts are available)> |
| conditions | network_reachability |
| state logic | ACTIVE when peering_attachment.State == 'available' (both TGW owners have accepted). CONDITIONAL(service_state) when State == 'pendingAcceptance' (peer TGW owner has not yet accepted). Omit for State in [rejected, failed, deleted]. Routes across the peering are ONLY present if the respective TGW route tables have been updated to include the peer CIDR — annotate CONDITIONAL(network_reachability) for the linchpin to evaluate. |
Narrative
TGW {local_tgw.name} (account {requester_account}) has an active peering attachment to TGW {peer_tgw_id} (account {accepter_account}). This is a routing topology fact - routes must be added to each TGW's route tables for traffic to flow across the peering (CONDITIONAL(network_reachability)).
Raw rule rules/explicit/aws-tgw.yaml
id: aws-tgw-peering-routes-to-peer
emits: RoutesTo
applies_to:
- aws
match_record:
resource_type: AWS::EC2::TransitGatewayPeeringAttachment
field: State
where:
- peering_attachment.State == 'available'
emit:
source_type: TransitGateway
target_type: Network
source: <local TransitGateway node (RequesterTgwInfo.TransitGatewayId)>
target: "<peer VirtualNetwork (AccepterTgwInfo.TransitGatewayId's attached VPCs \u2014 modeled as a\
\ Network placeholder until peer account facts are available)>"
api_source: ec2:DescribeTransitGatewayPeeringAttachments
evidence_field: TransitGatewayPeeringAttachment.AccepterTgwInfo + RequesterTgwInfo + State
conditions:
- network_reachability
state_logic: "ACTIVE when peering_attachment.State == 'available' (both TGW owners have accepted). CONDITIONAL(service_state)\
\ when State == 'pendingAcceptance' (peer TGW owner has not yet accepted). Omit for State in [rejected,\
\ failed, deleted]. Routes across the peering are ONLY present if the respective TGW route tables\
\ have been updated to include the peer CIDR \u2014 annotate CONDITIONAL(network_reachability) for\
\ the linchpin to evaluate."
false_positive_note: Peering attachment creation (ec2:CreateTransitGatewayPeeringAttachment) does NOT
automatically add routes between the peer TGWs; static routes must be added to each TGW's route table
after the peering is established. Without those route table entries, the peering does not create reachability.
Emit CONDITIONAL(network_reachability) and note that route table entries are required. Cross-account
peering (AccepterTgwInfo.OwnerId != RequesterTgwInfo.OwnerId) is an additional cross-account reachability
fact; the CrossAccountTrust for the RAM share (if used) is separate (see /rules/explicit/aws-ram.yaml).
narrative: "TGW {local_tgw.name} (account {requester_account}) has an active peering attachment to TGW\
\ {peer_tgw_id} (account {accepter_account}). This is a routing topology fact \u2014 routes must be\
\ added to each TGW's route tables for traffic to flow across the peering (CONDITIONAL(network_reachability))."