Learning to Drive on the Edge of a Cliff: Why the VPC Is the Wrong Object for Financial Services

Learning to Drive on the Edge of a Cliff: Why the VPC Is the Wrong Object for Financial Services

👁62views

Focusing on the VPC as the primary cloud object forces financial services firms to replicate datacenter thinking rather than designing for cloud native escape and recovery. This approach prioritizes forward motion over the critical need to understand reverse gear, leaving institutions unprepared for the agility and safety required at the edge of cloud migration.

CloudScale AI SEO: Article Summary
  • 1.
    What it is
    Learn why the VPC is the wrong security object for financial services cloud migration and why banks should start with disablement instead of enablement.
  • 2.
    Why it matters
    Starting with disablement prevents a bank from unintentionally exposing services like Lambda to the internet and ensures network policy inheritance, avoiding reliance on detective controls that only act after the fact.
  • 3.
    Key takeaway
    For a mature bank, the first phase of an AWS migration should be disablement not enablement: reverse before accelerating because the VPC gives you a set of parts, not a prebuilt security boundary.
~22 min read
🎧 Listen to this article

Most financial services firms start their cloud migration the way a learner driver would start a lesson on the edge of a cliff face. The car is already nose out over the drop, the engine is running, and the instructor’s first words are not “let’s talk about steering” or “here’s how the indicators work.” The first question that matters is whether this car even has a reverse gear, and whether the person behind the wheel knows how to find it before touching the accelerator.

That is roughly the position a bank is in on day one of an AWS migration, whether it realises it or not. Decades of datacenter thinking put it right at the edge, AWS hands it a car with far more capability than it has ever driven before, and the instinct everyone arrives with is to press forward and start exploring the pedals.

That is how I think a mature bank should start on AWS, hoping first that reverse actually works, and then using it before anything else.

Most cloud adoption programmes do roughly the opposite. They start with enablement: which services should we approve, how fast can we migrate, how do we teach developers serverless, how do we remove the friction that came with the old datacenter. For a bank, insurer or any highly regulated institution, I think the first phase should be disablement instead. AWS hands you an extraordinary amount of capability, and before you use any of it, you need to reverse away from the cliff.

1. The mismatch

Traditional banks did not grow up thinking about individual compute services. They thought about datacenters. The datacenter itself was the security object. Traffic entered through known places, traffic left through known places, firewalls sat between zones, and putting something in a private network carried an intuitive, load bearing meaning.

When those banks arrive on AWS, they expect something analogous, an object into which they can drop services, databases and compute, whose boundary behaves like the boundary they have spent decades learning to secure.

AWS does not really sell them that object. AWS gives them a VPC, a logically isolated virtual network built from subnets, routing, security groups, gateways and connectivity primitives. That is a genuinely excellent primitive, and startups and sophisticated infrastructure teams can build almost anything on top of it. But a mature bank is not primarily asking for freedom at the foundational layer. It wants some things to be impossible, and a VPC does not give you that. It gives you the parts and expects you to assemble the invariant yourself, which becomes obvious the moment you look past EC2.

2. Lambda is the example that makes network architects sit up

A normal Lambda function is not created inside your VPC. Every Lambda runs inside a Lambda managed VPC, and by default that function has access to the public internet. If you want its traffic governed by your controls, you have to attach it to your own subnets and security groups.

That is a rational design for a serverless platform, but for a bank that has spent months building private subnets and controlled egress into what everyone calls “the AWS datacenter,” it is fairly alarming. Someone ships a few lines of Lambda with no VPC configuration, and unless another control catches it, that function now has internet connectivity through AWS’s managed environment. Nobody hacked anything, and nobody defeated a firewall. The developer simply used the product as designed.

AWS gives you a good control for this in the form of IAM condition keys (lambda:VpcIds, lambda:SubnetIds, lambda:SecurityGroupIds) that let you deny function creation or updates unless a valid VPC is attached.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "EnforceVPCFunction",
    "Effect": "Deny",
    "Action": ["lambda:CreateFunction", "lambda:UpdateFunctionConfiguration"],
    "Resource": "*",
    "Condition": { "Null": { "lambda:VpcIds": "true" } }
  }]
}

That policy works, but my question is more basic than that. Why does a mature bank have to go and discover it needs this in the first place? In the object I actually want, Lambda should inherit the enclosing network’s egress policy by default, and escaping it should be the deliberate act rather than the default one.

3. S3 shows the gap between “not public” and “private”

S3 has improved a great deal here. New buckets are private by default, Block Public Access is on by default, and you can now enforce it at bucket, account and Organization level. That is real progress, but “not public” is still not the same claim as “private in the datacenter sense.”

Access to an S3 object can be shaped by IAM policy, bucket policy, ACLs, access point policy and VPC endpoint policy, all at once. The stronger statement, that this data is only reachable from inside your network, needs bucket policy conditions such as aws:SourceVpc or aws:SourceVpce as well, since Block Public Access alone will not give it to you. Even the endpoint you are relying on has its own default, since an S3 gateway endpoint’s default policy is effectively full access, and where a service does not support endpoint policies, AWS simply allows full access through it.

“Not public” also says nothing about cross account sharing, and that matters for a bank because Block Public Access was never designed to stop it. A bucket policy or an access point can grant read or write access to any other AWS account by account ID, and there is nothing about that grant that requires the other account to sit inside your Organization, your OU, or even under the same payer. Block Public Access will happily stay green while a bucket is shared with a vendor’s account, a former subsidiary’s account, or an account nobody in the bank recognises anymore. Stopping that requires a different control again, typically a resource control policy or an explicit data perimeter built from organisation condition keys such as aws:PrincipalOrgID, layered on top of everything else already in play.

Answering the question “can this bucket only be reached from inside my bank” requires knowing about Block Public Access at three organisational layers, Object Ownership, ACL behaviour, access points, the endpoint type and policy, IAM, cross account and cross organisation permissions and a couple of source condition keys. Every one of those mechanisms exists for a good reason, but together they are a lot to hold in your head just to answer one sentence. That is an abstraction problem rather than a knowledge problem.

4. Detective controls are not a wall

At this point someone usually says that this is what Trusted Advisor, Security Hub and Config are for. Use them, absolutely, but detection is not a boundary. Trusted Advisor and Security Hub are dashboards that tell you, sometimes on a delay, that you have already built the dangerous thing. Config has moved a little further, since it can now proactively evaluate some resource configurations before they are deployed, but AWS is explicit that proactive evaluation does not itself prevent a noncompliant resource from being deployed. Even at its best, that is still a dashboard. It just reaches you a little earlier.

If your model is to build whatever you want and let a control tell you later that it was dangerous, you are still driving toward the cliff and trusting the dashboard to flash before the wheels go over. A bank wants the other model, where you cannot create the dangerous thing in the first place. SCPs, RCPs and declarative policies get you there, and the fact that you need this many of them stacked together is itself the argument for a better object.

Trusted Advisor can tell me that my bucket is not public. It cannot turn that statement into the stronger architectural invariant I actually care about, which is that this bucket is reachable only through the bank’s approved private boundary. That is the more useful criticism to make of a detective control. It is not that it gets the answer wrong. It is that it is answering a different, weaker question than the one the bank is actually asking. A bank ultimately wants controls where the unsafe state is unrepresentable, not controls that have simply gotten better at noticing it.

5. PrivateLink, peering and Direct Connect all have the same trap

PrivateLink is genuinely private in the sense that traffic never touches the internet gateway or a public IP, but “PrivateLink” is not shorthand for “safely inside my perimeter.” An endpoint service is unavailable to consumers by default on the provider side, which is good, but that only covers who is allowed to connect. It says nothing about what they can do once connected, and that is governed separately by the consumer’s own VPC endpoint policy. AWS itself warns that if a provider grants broad connection permission and auto accepts requests, a load balancer sitting behind PrivateLink can end up effectively public despite having no public IP address. Read that again: public, with no public IP address. That single sentence is why old datacenter intuition keeps failing in AWS. And the default endpoint policy layer starts permissive too, allowing every principal every action over that endpoint by default, even though the service’s own IAM and resource policies still apply underneath it and are the thing actually holding the line until you tighten the endpoint policy yourself.

VPC peering has the same shape. A handful of control plane operations, requesting the peering connection, accepting it, and adding the routes on both sides, can join networks that were deliberately kept apart, and two previously isolated VPCs end up with private IP connectivity across accounts and regions. The point is not that peering is a single click. The point is that a control plane exists that is capable of redefining the network boundary at all, which is exactly why AWS itself publishes an SCP pattern to deny peering creation and acceptance at the organisation level, alongside internet gateway operations.

Direct Connect is my favourite version of this trap. A bank buys a dedicated physical circuit and everyone relaxes, because the traffic is now “private.” Then someone provisions a public VIF. A public virtual interface reaches AWS’s public service endpoints, including S3, service APIs and public EC2 addresses, over that same dedicated circuit. To be fair to AWS, this is not a backdoor to the general internet, since a public VIF can only reach Amazon’s own public prefixes, but try explaining that distinction to whoever signed off the bank’s network risk architecture. They were told this circuit was private, and now there is a documented, sanctioned path from the supposedly private circuit to publicly addressed AWS service endpoints. If your policy is that Direct Connect should carry only private or transit traffic, restrict public VIF creation to a controlled network account.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "DenyPublicDirectConnectVIFs",
    "Effect": "Deny",
    "Action": [
      "directconnect:CreatePublicVirtualInterface",
      "directconnect:AllocatePublicVirtualInterface",
      "directconnect:ConfirmPublicVirtualInterface"
    ],
    "Resource": "*"
  }]
}

Again, why am I the one writing this policy? It is because AWS sold me primitives and left the assembly of the security object to me.

6. The list of escape hatches gets long fast

Looked at through the eyes of a legacy bank, the number of independent ways “private” can quietly stop meaning private is uncomfortable.

CapabilityWhy it mattersTypical guardrail
Internet routing primitives (IGW, public NAT, egress only IGW)Can create a direct or outbound internet path once combined with routing and addressingVPC Block Public Access plus SCP or declarative policy
Lambda default networkingPublic internet unless attached to your VPClambda:VpcIds condition policy
VPC peering or Transit GatewaySilently joins networks that were meant to stay apartSCP restricting create and accept, central network account
PrivateLinkDefault endpoint policy is full accessMandatory custom endpoint and principal restrictions
S3“Not public” isn’t “only reachable from my VPC”Org level Block Public Access plus aws:SourceVpc and SourceVpce
Direct Connect public VIFPrivate circuit, public AWS prefixesRestrict the VIF creation APIs
Cross account resource policiesResources shared outside the account boundaryRCPs and SCPs plus org condition keys

None of these capabilities is inherently unsafe, and whether each one defaults open or closed is not actually the point. S3 no longer defaults open. A PrivateLink endpoint service does not either. Some of these start closed, some start permissive, and some sit entirely outside the VPC’s own boundary in the first place, and the institution has to know all of that and continuously preserve the intended boundary across every one of them. That is real progress on the defaults, and it is also beside the point I am making. Every one of these capabilities still exists. Someone in the account still has the permission to create the internet gateway, accept the peering connection, publish the PrivateLink service or provision the public VIF, and using that permission safely depends entirely on that person understanding what flipping the switch actually means. A setting that is correctly configured today is a promise that has to be kept every day, by everyone, forever, including the engineer who joins next year having never heard of your control and the automation script written by someone who left two years ago. It can drift, be copied into a new account without the guardrail, or be reversed by someone who does not know why it was there in the first place. That is a completely different risk profile from a boundary where the capability has been removed rather than merely configured. An account whose only permitted path out is back to the bank’s own datacenter, with the capability to create anything else designed out rather than merely denied, is not a promise that someone has to keep. It is a fact about what the infrastructure is capable of doing, and there is no other state for it to quietly drift into.

7. AWS is already building the parts

The encouraging part is that AWS clearly sees the problem. VPC Block Public Access lets you centrally kill internet ingress and egress through gateways at scale. Declarative policies in Organizations let you enforce foundational settings without trusting every account to configure itself correctly, and AWS is explicit that they work differently from SCPs and RCPs: they are enforced in the service’s own control plane rather than at the API authorization layer, the configuration is meant to stay in place even as the service grows new features and APIs, and if you ever detach the policy the setting rolls back to whatever it was before. That is a genuinely better mechanism than one more Deny statement, and it deserves credit for being closer to a platform guarantee than an SCP is. S3 has org level Block Public Access, Lambda has its VPC condition keys, AWS publishes SCP patterns for gateways and peering, endpoint policies can lock down PrivateLink, and organisation condition keys can build a real data perimeter.

It is also, structurally, yet another framework being bolted onto an already overloaded animal. SCPs over here, RCPs over there, declarative policies stacked on top of both, each with its own console, its own policy language, its own inheritance rules and its own thing to remember never to detach. AWS keeps building better and better shovels for the same pile. It has not yet asked out loud whether the pile needs to exist in the first place, and it is worth actually laying the pile out once, because seeing all of it in one place is more persuasive than describing it.

LayerWhat it actually isRole in propping up the VPC boundary
Preventative guardrailsService control policies, resource control policies, declarative policies, IAM permission boundariesDeny or structurally remove specific API actions across accounts
Network specific guardrailsVPC Block Public Access, S3 Block Public Access at bucket, account and org level, endpoint policies, data perimeter condition keysClose specific network and storage escape paths
Account factory guardrailsControl Tower preventive and proactive controls, Landing Zone Accelerator regulated industry guardrailsWire the above together once, at account vending time
Traffic and firewall controlsAWS Network Firewall, Firewall Manager policies, security groups, network ACLsInspect or restrict traffic once it is already flowing
Detective and posture servicesAWS Config plus Config Rules and Conformance Packs, Security Hub and its CIS, NIST and PCI standards, Trusted Advisor, GuardDutyNotice, after the fact, that something violates the intended posture
Access and exposure analysisIAM Access Analyzer for external and unused access, Access Analyzer for S3, VPC Reachability Analyzer, Network Access Analyzer, InspectorAnswer narrower questions such as what can reach this resource from where
Data sensitivityMacieFind sensitive data sitting behind whatever the network controls turned out to allow
Investigation and auditDetective, Audit ManagerReconstruct what happened once the other layers already missed it
Telemetry and evidenceVPC Flow Logs, CloudTrail plus CloudTrail Lake and Insights, CloudWatch Logs, Alarms and Contributor Insights, Systems Manager compliance and inventoryGenerate the raw evidence that every other layer above depends on
Organisation wide rollupsSecurity Hub cross account aggregation, Config aggregator, Control Tower’s account level compliance dashboard, the Organizations account status report for declarative policiesGive someone at OU or organisation level a single screen that summarises everything above

That is roughly thirty separate dials, dashboards, policy languages and reports, built up over more than a decade, all pointed at one underlying question that a physical datacenter answered by construction: what is this network actually allowed to touch. A VPC did not ship with an answer to that question. Everything in that table is AWS’s running attempt to bolt one on after the fact, one more service at a time.

AWS’s actual answer to this today is Control Tower and the Landing Zone Accelerator, with its regulated industry guardrails baked into an account vending template. A lot of banks, quite plausibly including mine, already run something close to a VPD through exactly that mechanism, and it deserves to be named as prior art rather than left out. But an account factory is still a deployment pattern, not a property of the account itself. It sets up the right SCPs, the right RCPs and the right network structure at vending time, and from that point on it is only as good as the discipline that keeps every subsequent change inside the same guardrails. Nothing stops a later change, a manual exception, an urgent break glass role or a template update from quietly widening what the account can do. That is a very good starting position. It is not yet the invariant.

Put together, that is close to evidence for the whole argument. AWS’s own product direction has been to move control upward, away from individual resources and toward inherited organisational invariants, again and again: VPC Block Public Access, declarative policies, S3 organisation policies, SCPs, RCPs and now landing zone guardrails are all attempts at exactly that. AWS is effectively admitting that a VPC plus IAM plus asking every team to configure things correctly was never going to be enough. What it has not done is collapse those attempts into something that is guaranteed by the platform rather than assembled and re-verified by the customer. They remain separate control planes that a bank has to know about, wire together and keep aligned, and an account vending template is a very good way to wire them together once. It is not the same as a guarantee that they stay wired together. My argument is that the invariant itself, not another control plane or template pointed at the existing ones, should become the product.

8. What I’d actually call for: a Virtual Private Datacenter

I would call it a VPD, short for Virtual Private Datacenter. It sits above VPCs, accounts and individual services, and it represents an invariant rather than a network. A VPC tells you where something is. A VPD tells you what must always be true about everything inside it, and that is a much more profound distinction than it sounds. Creating a VPD should mean that nothing enters, leaves or crosses this boundary unless the VPD explicitly permits it, and that permission should be a structural property of the workload account rather than a setting inside it. A workload account in a VPD that is only ever meant to talk back to the bank’s own datacenter should not have the capability to create an internet gateway at all. It should not be that nobody has done it yet, or that a control would catch it if someone tried. The capability itself should not exist in that account, in the same way an EC2 instance in a private subnet does not have a spare network cable it could plug into the internet if it wanted to.

I should be honest about how big a claim that is. A well written SCP that denies ec2:CreateInternetGateway account wide, with no exception path, no break glass override and no delegated admin escape hatch, achieves functionally the same outcome for that account. I am not claiming structural removal uses some mechanism SCPs cannot reach. The distinction I actually care about is who owns the guarantee and for how long. An SCP is something the bank wrote, has to remember never to weaken, has to re-verify after every reorganisation and every account migration, and has to trust nobody quietly punches a hole through with a new exception statement two years from now. A platform level guarantee is something AWS owns, the same way it already owns the fact that a Lambda function cannot reach into another customer’s account no matter what IAM policy you write against it. The gap between a disciplined SCP and a platform guarantee is entirely closable with enough process. It is also exactly the gap that produces incidents, because process is the one control that does not scale indefinitely.

That is a materially different guarantee from the same list enforced purely as policy that the bank wrote and must maintain forever: no internet gateways in workload accounts by default, no uncontrolled NAT, no public VIFs, no arbitrary peering, no Lambda outside approved networking, no storage or endpoints publicly reachable by accident, no PrivateLink service published outside approved principals. Policy has to be checked, monitored and kept correct by someone, indefinitely. A platform level guarantee does not, because there is nothing left for that someone to get wrong.

A VPD does not have to be one shape either. A bank might define several: one that can only ever route back to its own datacenter over Direct Connect, one that can only ever reach an approved Transit Gateway and nothing beyond it, one that permits controlled internet egress through a central inspection point, and perhaps one that allows PrivateLink to a short, approved list of partners. Each of those is a legitimate VPD, and a bank will need more than one of them. What makes any of them a VPD rather than just another configuration profile is that once a workload account is placed inside one, its routing behaviour is fixed for the life of that account. Moving a workload from an on-premises-only VPD to a Transit-Gateway VPD should be a deliberate act of re-platforming the account into a different template, carried out and audited from outside the account. It should not be something a change inside the account can bring about on its own.

Most importantly, those properties should be inherited rather than memorised. A developer should not need to know that Lambda’s default egress model differs from EC2’s, or that S3 Block Public Access and “only reachable through my endpoint” are two different claims, or that a Direct Connect public VIF can reach AWS’s public prefixes without being a general internet path. Those distinctions stay important to the network engineers running the VPD. They should not be a prerequisite for safely shipping application code.

I can already hear the obvious AWS rebuttal: you can build all of this today with Organizations, Control Tower, SCPs, RCPs, declarative policies, VPC Block Public Access, S3 Block Public Access, endpoint policies and a properly designed data perimeter. Exactly. If assembling one security invariant takes that many separate services, each with its own console, its own policy language and its own failure mode, then AWS has proved my point rather than answered it. A VPC is a network object. A bank needs a security inheritance object, and today it has to build that object itself out of a dozen unrelated parts. The invariant is the missing abstraction, not another control plane pointed at the ones we already have.

9. Just don’t build a bunker

There is an obvious way to get this wrong, which is to build a Virtual Private Bunker instead. It would be fantastically secure, because nothing gets in and nothing gets out, and as a result nothing useful happens inside it either.

Banks need connectivity to identity providers, payment networks, card schemes, fraud services, credit bureaus, SaaS tools, customer facing ingress and governed egress. So the VPD should not remove doors. It should make every door a first class, deliberate object, so that internet egress is an explicit, centrally inspected capability, a PrivateLink connection to a partner is an explicit capability, a VPC to VPC link is an explicit capability, and a public Direct Connect VIF is an explicit, conscious decision. What I object to is not connectivity. It is accidental connectivity. A datacenter has walls and doors, while a bunker only has walls.

10. Reverse first, then accelerate

Until AWS ships something like a VPD, a mature bank should build its own, and Control Tower or the Landing Zone Accelerator’s regulated industry guardrails are the right scaffold to start from rather than a reason to skip the work. Start at the Organization rather than the application. Lock down regions, turn on VPC and S3 Block Public Access centrally, deny arbitrary internet gateways, NAT, peering and public VIFs by default, require Lambda to run inside approved networking, and define your data perimeter before you define your first workload. Then add permissions back deliberately, with controlled egress where it is needed, an approved PrivateLink service where it is needed, and a conscious public VIF exception where it is genuinely needed.

Deny first. Understand deeply. Enable deliberately. That is not a brake on innovation. It is reversing the car until all four wheels are back on the road.

Conclusion

AWS is not insecure because all this capability exists. If anything the opposite is closer to true, and it is extraordinarily powerful precisely because it exists. The mistake is expecting a mature bank to consume the same lowest level abstraction as a five person startup, and assuming that enough configuration and governance will eventually turn that abstraction into the thing the bank actually asked for.

A VPC is an excellent virtual network. It is not a virtual datacenter. Give a startup a VPC and let them build. Give a bank a VPD, let AWS hold the boundary, and then let the bank deliberately cut doors into it.

And whatever you do, please do not give me a bunker.