aws-tgw-route-table-routes-to-subnet
match (record)
{
"field": "Routes",
"resource_type": "AWS::EC2::TransitGatewayRouteTable"
}
where
route.State != 'blackhole' # attachment is active, not deleted/failed
route.TransitGatewayAttachments[].ResourceType in ['vpc', 'vpn', 'direct-connect-gateway', 'tgw-peering']
route.DestinationCidrBlock is resoluble to one or more
Subnet nodes
emit
| source type | Route |
|---|---|
| target type | Subnet |
| source | <Route node for the TGW Route Table (TransitGatewayRouteTableId)> |
| target | <Subnet node(s) within the CIDR destination resolved from route.DestinationCidrBlock> |
| conditions | network_reachability |
| state logic | ACTIVE when route.State == 'active' and the referenced attachment is 'available'. CONDITIONAL(network_reachability) because this is an L3 routing fact — destination SGs gate L4. CONDITIONAL(service_state) if the attachment State is 'pendingAcceptance'. Omit for route.State == 'blackhole' (no valid attachment, traffic dropped). |
Narrative
TGW route table {route_table.name} has a route for {cidr} (type: {route.type}) pointing to attachment {attachment.name} ({resource_type}), routing toward subnet(s) within {cidr}. This is an L3 routing fact; L4 reachability requires security group evaluation at the destination.
Raw rule rules/explicit/aws-tgw.yaml
id: aws-tgw-route-table-routes-to-subnet
emits: RoutesTo
applies_to:
- aws
match_record:
resource_type: AWS::EC2::TransitGatewayRouteTable
field: Routes
where:
- 'route.State != ''blackhole'' # attachment is active, not deleted/failed'
- route.TransitGatewayAttachments[].ResourceType in ['vpc', 'vpn', 'direct-connect-gateway', 'tgw-peering']
- route.DestinationCidrBlock is resoluble to one or more Subnet nodes
emit:
source_type: Route
target_type: Subnet
source: <Route node for the TGW Route Table (TransitGatewayRouteTableId)>
target: <Subnet node(s) within the CIDR destination resolved from route.DestinationCidrBlock>
api_source: ec2:SearchTransitGatewayRoutes (filter State != blackhole)
evidence_field: TransitGatewayRoute.DestinationCidrBlock + TransitGatewayAttachments[].ResourceId
conditions:
- network_reachability
state_logic: "ACTIVE when route.State == 'active' and the referenced attachment is 'available'. CONDITIONAL(network_reachability)\
\ because this is an L3 routing fact \u2014 destination SGs gate L4. CONDITIONAL(service_state) if\
\ the attachment State is 'pendingAcceptance'. Omit for route.State == 'blackhole' (no valid attachment,\
\ traffic dropped)."
false_positive_note: '''blackhole'' routes (State == ''blackhole'') MUST NOT generate RoutesTo edges.
CIDR-to-subnet resolution requires the VPC CIDR/subnet ranges collected from ec2:DescribeSubnets;
only emit when the CIDR match is confirmed. A route pointing to a VPN or Direct Connect attachment
targets on-premises CIDR space; model the target as a Subnet node only when a matching on-premises
subnet record exists in the graph. If no subnet node exists for the destination CIDR, use the VPC
node (VirtualNetwork) as the target instead. Preserve the distinction between static (type=static)
and propagated (type=propagated) routes in evidence but treat them identically for edge emission.'
narrative: 'TGW route table {route_table.name} has a route for {cidr} (type: {route.type}) pointing
to attachment {attachment.name} ({resource_type}), routing toward subnet(s) within {cidr}. This is
an L3 routing fact; L4 reachability requires security group evaluation at the destination.'