Private paths: PrivateLink and VPC endpoints

Lesson 2 of 3 in Protecting Data in Transit.

TLS protects the contents of a connection. It does not change where the connection goes, and “the traffic must never traverse the public internet” is a separate requirement with a separate answer.

By default, a call from an EC2 instance to s3.eu-west-1.amazonaws.com resolves to a public IP address and leaves your VPC through an internet gateway or NAT gateway. It is encrypted, authenticated and fine for most workloads — but it is an internet path, and in a subnet with no internet route it does not work at all. AWS PrivateLink is the family of mechanisms that keeps that traffic on the AWS network, and it comes in two shapes you must not confuse.

A gateway endpoint exists for exactly two services — Amazon S3 and DynamoDB — and is not a device at all: it is a route table entry pointing a prefix list at the endpoint. Nothing is deployed into a subnet, there is no ENI, no private IP address, and it is free. Because it works by routing, it only serves traffic that originates inside the VPC — it cannot be reached from on premises over Direct Connect or VPN.

An interface endpoint is the general mechanism: an elastic network interface with a private IP address in each subnet you choose, for a specific service. It is reached through DNS — enable private DNS and the service’s normal hostname resolves to the endpoint’s private addresses, so no code changes — it is protected by a security group like any ENI, it works for on-premises traffic arriving over Direct Connect or VPN, and it is charged hourly plus per gigabyte. Hundreds of AWS services offer one, and PrivateLink also lets you expose your own service behind a Network Load Balancer so consumers in other VPCs or accounts reach it through their own interface endpoints without any peering or route sharing.

The reason this lesson sits in Domain 5 rather than Domain 3: an endpoint is not merely a network convenience. It is an identity you can require in a policy, and that turns a private path into an enforceable data-protection boundary.

Three authorization surfaces exist around an endpoint, and keeping them straight is most of what the exam asks.

The endpoint policy is attached to the endpoint and limits what can be reached through it. Its default is full access, and tightening it is one of the most effective anti-exfiltration controls available: an endpoint policy that allows only your own buckets, or only resources belonging to aws:PrincipalOrgID, means a principal inside your VPC cannot copy data to a bucket in an attacker’s account through your endpoint. The endpoint policy cannot grant anything — the resource policy and identity policy still have to allow the call.

The resource policy on the far side can require the endpoint. aws:SourceVpce matches a specific endpoint id; aws:SourceVpc matches any traffic from a named VPC. Both are only present when the request actually arrived through a VPC endpoint, which is why a deny on their absence is such a strong statement: it makes network position part of authorization. Write it as a deny with Null or StringNotEquals, and remember to exempt the principals that must work from outside — the console session of an administrator, a replication role, your own CI — or you will lock yourself out of the bucket you were protecting.

And for an interface endpoint only, the security group on the ENI decides which instances may even open a connection. Gateway endpoints have no security group, which is a difference worth remembering when a question asks how to restrict who in the VPC can use the S3 endpoint — for gateway endpoints that control lives in route tables, endpoint policies and IAM, not in a security group.

Bucket policy: require the endpoint

“This bucket is readable only from our VPC endpoint.” The Null form denies requests where the key is absent, which is what a public-endpoint request looks like.

{
  "Sid": "RequireVpcEndpoint",
  "Effect": "Deny",
  "Principal": "*",
  "Action": "s3:*",
  "Resource": [
    "arn:aws:s3:::clinical-records",
    "arn:aws:s3:::clinical-records/*"
  ],
  "Condition": {
    "StringNotEquals": { "aws:SourceVpce": "vpce-0abc1234exampleid" },
    "ArnNotLike": {
      "aws:PrincipalArn": "arn:aws:iam::111122223333:role/BreakGlassAudit"
    }
  }
}

Both conditions must be true for the deny to apply, so the break-glass role keeps working from outside. Leaving that exemption out is the classic self-inflicted outage.

Endpoint policy: stop exfiltration

Attached to the endpoint, this limits what may be reached through it regardless of what the far-side policies allow.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": "*",
    "Action": ["s3:GetObject", "s3:PutObject", "s3:ListBucket"],
    "Resource": [
      "arn:aws:s3:::clinical-records",
      "arn:aws:s3:::clinical-records/*"
    ],
    "Condition": {
      "StringEquals": { "aws:PrincipalOrgID": "o-exampleorgid" }
    }
  }]
}

A compromised instance can now reach exactly one bucket, as a principal from your organization, through this path. Data cannot be pushed to a bucket the attacker controls.

Which endpoint type, again

Gateway endpoint Interface endpoint
Services S3 and DynamoDB only hundreds, plus your own via PrivateLink
Mechanism route table prefix list ENI with private IPs
DNS unchanged (routing-based) private DNS makes the normal name resolve locally
Security group none yes, on the ENI
Reachable from on premises no yes, over Direct Connect or VPN
Cost free hourly per AZ plus per GB

The row that decides most questions is the on-premises one. “Branch offices must reach S3 without internet egress” is an interface endpoint question even though S3 has a gateway option.

Two services extend private access to people rather than workloads, and the exam names both beside PrivateLink and VPC endpoints.

AWS Client VPN is a managed OpenVPN-compatible endpoint: users run a client, authenticate with certificates, Active Directory or a SAML identity provider, and receive an encrypted tunnel into your VPC with authorization rules per network CIDR. It is the right answer when access is network-shaped — the user needs to reach a subnet, an IP, a non-HTTP protocol, a database port.

AWS Verified Access is the zero-trust alternative for application-shaped access: no tunnel at all. Each request to a published internal application is evaluated against policies written over identity (from IAM Identity Center or an OIDC provider) and device posture (from a trust provider such as a third-party endpoint-management product), so a user on a non-compliant laptop is refused even with valid credentials. Every request is evaluated and logged, rather than one authentication granting a network position for hours. Choose Verified Access when the requirement mentions device trust, per-application access, or removing VPN from the user experience; choose Client VPN when the requirement is raw network reachability.

Key terms: AWS PrivateLink, Gateway endpoint, Interface endpoint, VPC endpoint policy, AWS Client VPN, AWS Verified Access

Interactive checkpoint quiz (2 questions) — open this page in a browser to take it.