docs / coverage

coverage

What can be pinned to IP ranges, what cannot, and how to build a posture that works either way.

the short version

IP allowlisting works when a vendor operates dedicated address space and publishes it. Most do. Some sit behind a shared CDN, where pinning the addresses would allowlist every other site behind that CDN as well, and others state outright that their addresses are not stable enough to pin.

The catalog classifies every service so this is visible before you build rather than after. Current counts, read live from the feed:

ClassificationCountWhat it means for a rule
dedicated· Vendor-owned space. Pin it.
mixed· Mostly dedicated, with some shared or dynamic parts. Pin it, and read the service page for which purposes are which.
cdn-shared· Shared CDN ranges. Pinning would allowlist the whole CDN, so don't pin it.
not published· The vendor states IP allowlisting is unsupported for the service and recommends something else.

The last two rows are where an IP allowlist stops being the right control. You can check any specific vendor on the services pages or in the catalog before you commit to anything.

why a CDN-fronted service cannot be pinned

When a vendor puts its API behind a shared CDN, the addresses answering for that vendor are the CDN's, and the same addresses answer for every other customer of that CDN. The imprecision cuts both ways. Outbound, a rule allowing them lets your workload reach all of those other sites too. Inbound, it lets anyone who can put traffic through that CDN reach your endpoint, which is a wider opening than it looks. Neither rule has the precision of IP ranges owned directly by a specific vendor.

recommended posture: scope by workload, not by account

The common mistake is treating this as one decision for the whole environment. It is not. Security groups are free and attach per workload, so the service that talks to Stripe does not need the same rules as the one that talks to a CDN-fronted API, and the endpoint that receives webhooks does not need the rules of the one that does not.

Give each workload a security group carrying only what it actually needs:

resource "aws_security_group" "billing" {
  name   = "billing"
  vpc_id = var.vpc_id
}

# This workload talks to Stripe and nothing else on the internet.
resource "aws_vpc_security_group_egress_rule" "billing_stripe" {
  security_group_id = aws_security_group.billing.id
  ip_protocol       = "tcp"
  from_port         = 443
  to_port           = 443
  prefix_list_id    = "pl-0f47b5ca566486dec"  # slash0.stripe.api.v4
  description       = "Stripe API"
}

A workload that needs a service you cannot pin gets its own group, and only that group carries the broader rule. Nothing else in the account inherits it:

resource "aws_security_group" "notifications" {
  name   = "notifications"
  vpc_id = var.vpc_id
}

# This workload calls a CDN-fronted API, so the rule cannot be narrowed by
# address. It is isolated here rather than applied environment-wide, and it
# is the one path worth putting behind a proxy or DNS filtering.
resource "aws_vpc_security_group_egress_rule" "notifications_https" {
  security_group_id = aws_security_group.notifications.id
  ip_protocol       = "tcp"
  from_port         = 443
  to_port           = 443
  cidr_ipv4         = "0.0.0.0/0"
  description       = "CDN-fronted vendor, see /docs/coverage"
}

The result is that the unpinnable dependency costs you one workload's blast radius instead of the whole environment's. An attacker with a foothold in the billing service still cannot reach anything but Stripe. That is the part that matters to an auditor reading req. 1.3.2, and it is achievable today for every dependency in the catalog that publishes ranges.

for the services that publish nothing

Where a vendor states that IP allowlisting is unsupported, they almost always recommend a control that is stronger than an address check would have been. The catalog records the vendor's own position and their recommended alternative for each one, with a link to the page saying it.

The three that come up most often:

None of these are served by IP ranges from the terraform provider or managed prefix lists from slash0.

what is coming

A later phase adds hostname-aware egress enforcement that runs inside your VPC and is built on this same catalog, which is what extends the model to the services that cannot be pinned by address. The classifications above are what that phase is designed around, so nothing you build now is wasted.