Skip to content

Model: node and edge kinds

The graph (vpcatlas-graph/1) has two layers. The network layer (VPCs, subnets, route tables, gateways, endpoints, load balancers, Network Firewall, Resolver, RAM, prefix lists) is described in architecture.md. The service layer sits on top of it: DNS, the edge, APIs, compute, data and the account services. This page documents the kinds of the service layer, their edges and how the registry draws them.

Everything here is data. Which nodes a page draws, and where, is decided by exporters/layout.py and exporters/graphview.py; the registry (exporters/registry.py) only says how a kind looks.

Rules every kind follows

  • One class per kind in model/resources.py, subclassing Resource; RESOURCE_TYPES registers it by its type. The class is also exported from model/__init__.py. model.SERVICE_TYPES lists the types of the service layer.
  • id is the AWS id, or a composed one that never changes between scans (the table says which). account_id is the owner. region is "global" (GLOBAL_REGION) for the global services (model.GLOBAL_SERVICE_TYPES, and a web ACL of the CLOUDFRONT scope), else the region of the object. A CloudFront certificate or web ACL is collected in us-east-1, and a certificate keeps that region.
  • One contains parent per node. A service attached to a VPC is contained by its VPC; a regional service with no VPC by its Region node; a global one by its Account node; an ECS service by its cluster. A subnet is never a parent: a service that runs in subnets lists their ids in subnet_ids and gets an attached_to edge (relation="subnet") to each, as a load balancer does. The diagram code draws the icon inside the subnet from those edges.
  • Relations between services are ids and ARNs in fields (target_group_arns, web_acl_id, vpc_link_id...). The builder turns them into the edges below; the fixture adds the same edges by hand.
  • Lists are sorted and capped by the collector (instance ids, rule names, table names); the matching count field keeps the real number. None on a count or a flag means "not read" (the call was denied or unsupported), never zero or false; the collector also records the gap.
  • Instances that an InstanceGroup lists are the same instances the eni nodes of the subnet already show as workloads (NetworkInterface.instance_id); a page must not draw both.

Node kinds

type Class id Region Parent Main fields
hosted_zone HostedZone zone id without /hostedzone/ global account zone_name, private, vpc_ids, record_count, records (alias records and CNAMEs to known endpoints: name, record_type, alias, target, target_kind (cloudfront, elb, api_gateway, s3, s3_website, lambda_url, mediastore, accelerator, endpoint, other), routing (simple, weighted, latency, failover, geolocation, geoproximity, ip-based, multivalue))
cloudfront CloudFrontDistribution distribution id global account domain_name, aliases, origins (id, domain, kind s3/elb/api_gateway/custom, path, access oac/oai, target), web_acl_id, certificate_arn, price_class, enabled
web_acl WebAcl WAF id global (CLOUDFRONT) or region (REGIONAL) account or region scope, default_action, rule_count, rule_names, managed_rule_groups, associated_arns, logging
certificate Certificate last part of the ARN region of the certificate account (us-east-1) or region domain_name, alt_names, cert_type, in_use_by, not_after, key_algorithm
shield ShieldSubscription shield global account tier standard/advanced, subscribed, protections
api_gateway ApiGatewayApi API id region region api_type REST/HTTP/WEBSOCKET, endpoint_type, stages, custom_domains, certificate_arns, web_acl_arn, integrations (route, kind lambda/elb/vpc_link/http, target, vpc_link_id)
api_vpc_link ApiVpcLink link id region VPC link_kind, vpc_id, subnet_ids, security_group_ids, target_arns
target_group TargetGroup targetgroup/{name}/{hash} region VPC target_type instance/ip/lambda/alb, protocol, port, load_balancer_arns, health_check_path, targets (id, port, zone, health), healthy_count, unhealthy_count
ecs_cluster EcsCluster cluster name region region service_count, running_tasks, capacity_providers
ecs_service EcsService {cluster}/{service} region cluster launch_type, desired_count, running_count, vpc_id, subnet_ids, security_group_ids, assign_public_ip, target_group_arns
eks_cluster EksCluster cluster name region VPC version, vpc_id, subnet_ids, security_group_ids, endpoint_public, endpoint_private, public_access_cidrs, node_groups
instance_group InstanceGroup asg:{name}, name:{Name tag} or subnet:{id} region VPC group_by asg/name/subnet, instance_count, instance_ids, instance_types, subnet_ids, security_group_ids, public_ips, min_size, max_size, desired_capacity, target_group_arns
rds RdsDatabase identifier, or cluster:{identifier} region VPC db_kind instance/cluster, engine, engine_version, instance_class, multi_az, publicly_accessible, subnet_group, subnet_ids, security_group_ids, members; is_aurora
elasticache ElastiCacheCluster replication group id, else cluster id region VPC engine, node_type, node_count, multi_az, subnet_group, subnet_ids, security_group_ids
efs EfsFileSystem fs-... region VPC performance_mode, throughput_mode, encrypted, size_bytes, mount_targets (id, subnet_id, zone, ip_address)
lambda LambdaFunction function name region VPC (with a VPC config) or region runtime, memory_mb, timeout_s, vpc_id, subnet_ids, security_group_ids, invoked_by
s3_bucket S3Bucket bucket name bucket region region website, versioning, public_access_blocked, encryption, used_as (only buckets some diagram needs)
s3 S3Summary s3 global account bucket_count
dynamodb DynamoDbSummary dynamodb region region table_count, table_names
cloudtrail CloudTrailSummary cloudtrail global account trail_count, trails (name, home_region, multi_region, organization, logging)
guardduty GuardDutySummary guardduty region region enabled, detector_id
config_recorder ConfigRecorder config region region enabled, recording, all_resources
cloudwatch CloudWatchSummary cloudwatch region region log_group_count, alarm_count
kms KmsSummary kms region region key_count (customer managed keys)
ecr EcrSummary ecr region region repository_count

HostedZone uses the diagram kind hosted_zone that already exists; the other kinds got theirs in the registry (next section). The summary kinds (s3, dynamodb, cloudtrail, guardduty, config_recorder, cloudwatch, kms, ecr) are one node each so that a denied call leaves one unknown number, not a wrong zero for the others.

Edge kinds

The edge kind is a string; model.EdgeKind lists the values. Direction is source to destination.

Kind From To Attributes Style (never by colour)
serves hosted zone CloudFront, API, load balancer, bucket record, record_type 2 px, dashed 6 3, block head
origin CloudFront load balancer, bucket, API origin_id, origin_kind, path, access 2 px solid, open head
protects web ACL, Shield CloudFront, load balancer, API via web_acl/shield 1 px, dotted 3 3, round head
secures certificate load balancer, CloudFront, API use listener/distribution/domain, port 1 px, dotted 1 3, no head
integrates API; VPC link Lambda, load balancer, VPC link; load balancer route, integration (lambda, vpc_link, elb, http) 2 px, dash-dot 6 2 1 2, block head
targets load balancer; target group target group; instance group, ECS service, Lambda, load balancer port, health (healthy, degraded, unhealthy) 1 px solid, block head
attaches ECS service, Auto Scaling group target group port 1 px, dashed 8 4, open block head
mounts EFS subnet mount_target, ip_address 1 px, dotted 2 2, round tail

attaches is the registration (service side), targets the forwarding (target group side); both are kept because the page draws the first inside the compute row and the second on the load balancer path. The network edges (contains, attached_to, routes_to, peered_with, shared_from) are unchanged.

Registry

exporters/registry.py keeps the service layer in tables of its own, because the style guide (diagram-style.md 2.5) has to list a shape before it can enter KINDS, and lucid_classes.json has to carry its Lucid class. When the diagrams draw them, move the entries into KINDS, EDGE_KINDS and the JSON file and add the shapes to the guide; ALL_KINDS, spec, drawio_style and edge_style already read both tables.

Table Content
SERVICE_KINDS one KindSpec per diagram kind: draw.io resIcon, size, family colour, abbreviation (the caption of the Lucid fallback square) and title (the legend)
SERVICE_TYPE_KINDS model type to the diagram kinds that can draw it (rds or aurora by engine, ecs_service or fargate_service by launch type, instance_group as asg or instance)
service_lucid_classes() Lucid class of each kind (Arch...AWS2024, verified: false until the probe document confirms it)
SERVICE_EDGE_KINDS, SERVICE_EDGE_TITLES, SERVICE_EDGE_TAIL the eight edges, their legend rows and their width, dash and heads
SERVICE_FLOWS, SERVICE_FLOW_COLORS, service_badge_color the numbered flows of the service pages

Colours follow the AWS categories: networking purple (the profile's), compute #ED7100, storage #7AA116, database #C925D1, security #DD344C, management #E7157B.

Diagram kind draw.io icon Category Model type
route53 route_53 networking hosted_zone (service icon for the regional row)
cloudfront cloudfront networking cloudfront
web_acl waf security web_acl
certificate certificate_manager security certificate
shield shield security shield
api_gateway api_gateway networking api_gateway
api_vpc_link endpoints networking api_vpc_link
target_group elastic_load_balancing networking target_group
ecs_cluster, ecs_service ecs compute ecs_cluster, ecs_service
fargate_service fargate compute ecs_service with launch_type FARGATE
eks_cluster eks compute eks_cluster
asg auto_scaling2 compute instance_group with group_by asg
rds, aurora rds, aurora database rds (aurora when is_aurora)
elasticache elasticache database elasticache
efs elastic_file_system storage efs
lambda lambda compute lambda
s3, s3_bucket s3 storage s3, s3_bucket
dynamodb dynamodb database dynamodb
cloudtrail cloudtrail management cloudtrail
guardduty guardduty security guardduty
config_recorder config management config_recorder
cloudwatch cloudwatch_2 management cloudwatch
kms key_management_service security kms
ecr ecr compute ecr

Flows of the service pages

The network flows (1 to 7, FLOW_COLORS) keep their numbers and colours. The service pages number their own three flows from 1, with colours that no network flow uses:

Flow Number Colour Path
ingress 1 #0E7490 users, Route 53, CloudFront, WAF, load balancer, target group
api 2 #7C3AED users, Route 53, API Gateway, VPC link or Lambda
database 3 #BE185D workload to RDS, ElastiCache or EFS

The fixture

tests/fixtures/malz.py gives the Application account the services of one realistic application, so round 5b can render it: the public zone app.example.com with alias records to a CloudFront distribution (origin app-alb, a second origin on an S3 bucket through OAC, a CLOUDFRONT web ACL, a us-east-1 certificate) and api.app.example.com to an HTTP API (a VPC link to app-internal, a Lambda integration, a regional certificate); app-alb with a regional web ACL and two target groups, one for the Auto Scaling group Application Instances (the six instances the subnets already draw) and one for an ECS Fargate service; Aurora PostgreSQL, an ElastiCache replication group and an EFS with a mount target per private subnet; a Lambda in the VPC and one without; Shield Standard; and the account services row. The network counts that test_malz_fixture.py asserts did not change.

Adding a kind

  1. A class in model/resources.py (type: Literal["x"] = "x"), exported in model/__init__.py, added to SERVICE_TYPES (and to GLOBAL_SERVICE_TYPES if it is global).
  2. A row in the table above, and a row in inventory/build.py TYPE_LABELS.
  3. A diagram kind in SERVICE_KINDS and SERVICE_TYPE_KINDS, with its Lucid name in _LUCID_SERVICE_NAMES.
  4. A collector in collectors/ that fills it, registered in DEFAULT_COLLECTORS, and an alias in exporters/graphview.py _ALIAS so that the layout does not read the type as other.
  5. tests/test_model_services.py checks 1 and 3 for every type of SERVICE_TYPES by itself.