<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Azure Governance on Brewed in the Cloud by Chris Hailes</title><link>https://blog.brewedinthecloud.com/tags/azure-governance/</link><description>Recent content in Azure Governance on Brewed in the Cloud by Chris Hailes</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Tue, 09 Jun 2026 00:00:00 +1000</lastBuildDate><atom:link href="https://blog.brewedinthecloud.com/tags/azure-governance/rss.xml" rel="self" type="application/rss+xml"/><item><title>Private Endpoint Control Planes: Private Reachability Isn’t Trusted Reachability</title><link>https://blog.brewedinthecloud.com/p/pe-attacks-control-plane-risks/</link><pubDate>Tue, 09 Jun 2026 00:00:00 +1000</pubDate><guid>https://blog.brewedinthecloud.com/p/pe-attacks-control-plane-risks/</guid><description>&lt;p&gt;You can take a sensitive service off the public internet, pin it behind a Private Endpoint, and come away feeling like the trust problem is mostly solved.&lt;/p&gt;
&lt;p&gt;That feeling is exactly where the trouble starts.&lt;/p&gt;
&lt;p&gt;Private Endpoints can reduce exposure. They can narrow the network paths that reach a service. But they do not prove that the environments consuming that service privately are legitimate, or that the administrative chain which created that private path deserves trust.&lt;/p&gt;
&lt;p&gt;The real design error is not exposing a service privately. It is assuming that any environment able to consume it privately has therefore earned trust.&lt;/p&gt;
&lt;p&gt;That is a control-plane problem, not a networking success story.&lt;/p&gt;
&lt;h2 id="the-mental-model"&gt;The Mental Model
&lt;/h2&gt;&lt;p&gt;The common assumption is simple:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If a service is only reachable through a Private Endpoint, then access is effectively trusted because it is no longer public.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That assumption compresses two different questions into one:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;how traffic reaches the service;&lt;/li&gt;
&lt;li&gt;whether the thing reaching it should be trusted.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Private Endpoints only answer the first one.&lt;/p&gt;
&lt;p&gt;They change the path. They do not validate the consumer, the administrators who created the path, or the approval decisions that allowed it to exist. The private IP is not the trust boundary. It is the output of a series of management decisions.&lt;/p&gt;
&lt;p&gt;So the useful shift in mental model is this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;private connectivity is a routing property&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;trusted connectivity is an authority decision&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Private Endpoints affect the first one, not the second&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The moment a team treats private reachability as evidence that a consumer environment has been legitimately trusted, they stop inspecting the layer where trust was actually granted.&lt;/p&gt;
&lt;h2 id="how-it-really-works"&gt;How It Really Works
&lt;/h2&gt;&lt;p&gt;Private Endpoint is usually discussed as if it were a networking feature with some management overhead attached.&lt;/p&gt;
&lt;p&gt;That framing is backwards.&lt;/p&gt;
&lt;p&gt;It is a control-plane object that creates a private data-plane path.&lt;/p&gt;
&lt;p&gt;That path exists only because a chain of administrative decisions makes it exist:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a Private Endpoint resource is created;&lt;/li&gt;
&lt;li&gt;it is placed in a subnet within a virtual network;&lt;/li&gt;
&lt;li&gt;it references a specific Private Link-capable subresource;&lt;/li&gt;
&lt;li&gt;a connection request is raised and allowed through the target service’s approval model;&lt;/li&gt;
&lt;li&gt;DNS then enables clients to use that private path.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By the time packets flow, the trust decisions have already happened.&lt;/p&gt;
&lt;h3 id="approval-is-a-trust-decision"&gt;Approval is a trust decision
&lt;/h3&gt;&lt;p&gt;Approval is often treated as a minor workflow event. It is not. It is the point at which a service owner, delegated operator, or service-specific approval path allows a particular consumer environment to establish private reachability.&lt;/p&gt;
&lt;p&gt;That is a trust decision.&lt;/p&gt;
&lt;p&gt;It is also one of the reasons Private Endpoint can be over-trusted architecturally. The assurance conveyed by a successful private connection is not perfectly uniform across Azure services or ownership models. Teams generalise from one service pattern to another, see a working private path, and assume it carries the same trust meaning everywhere. It does not.&lt;/p&gt;
&lt;p&gt;If your architecture treats “connected privately” as if it implied a consistent trust posture across services, you are relying on a certainty the platform does not actually provide.&lt;/p&gt;
&lt;h3 id="the-endpoint-and-the-service-do-not-share-the-same-ownership-story"&gt;The endpoint and the service do not share the same ownership story
&lt;/h3&gt;&lt;p&gt;A Private Endpoint is a separate Azure resource. It can live in a different resource group, subscription, or operating domain from the service it connects to.&lt;/p&gt;
&lt;p&gt;That is not just an implementation detail. It means the protected service and the private path to it can have different lifecycle owners, different administrative scopes, and different review habits.&lt;/p&gt;
&lt;p&gt;This is the point many reviews miss: hardening the service does not tell you enough if someone else can still instantiate and retain private reachability to it.&lt;/p&gt;
&lt;h3 id="administrative-separation-is-not-trusted-separation"&gt;Administrative separation is not trusted separation
&lt;/h3&gt;&lt;p&gt;Subscriptions and resource groups are useful operational boundaries. They are not evidence of trustworthy separation by themselves.&lt;/p&gt;
&lt;p&gt;If the same administrators, inherited permissions, or approval practices can still bridge those scopes through management actions, then the boundary is structural, not trustworthy.&lt;/p&gt;
&lt;p&gt;This is the design mistake that shows up repeatedly in Azure estates: teams see separate subscriptions and infer separate trust. In reality, they have reviewed layout, not authority.&lt;/p&gt;
&lt;h2 id="trust-flow-not-just-packet-flow"&gt;Trust Flow, Not Just Packet Flow
&lt;/h2&gt;&lt;p&gt;The control-plane risk is easier to see when the trust relationships are explicit.&lt;/p&gt;
&lt;div class="mermaid"&gt;flowchart LR
A[Identity with Private Endpoint management access] --&gt; B[Create or modify Private Endpoint]
B --&gt; C[Consumer VNet and subnet placement]
B --&gt; D[Connection request to target resource]
D --&gt; E[Service-specific approval path]
E --&gt; F[Private connectivity established]
F --&gt; G[Private DNS mapping]
G --&gt; H[Client workload uses private path]
I[Platform admin] --&gt; C
J[DNS admin] --&gt; G
&lt;/div&gt;
&lt;p&gt;The interesting part is not where the packets flow. It is where trust gets asserted:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the identity allowed to create the endpoint;&lt;/li&gt;
&lt;li&gt;the team controlling the subnet where it lands;&lt;/li&gt;
&lt;li&gt;the approval path for the target resource;&lt;/li&gt;
&lt;li&gt;the DNS authority that makes the path usable.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If those actors sit in different places, with different review standards, then “internal-only access” is really the product of several loosely connected trust decisions.&lt;/p&gt;
&lt;h2 id="real-world-impact"&gt;Real-World Impact
&lt;/h2&gt;&lt;p&gt;This changes how you should interpret private connectivity in production.&lt;/p&gt;
&lt;h3 id="private-access-does-not-prove-the-consumer-was-ever-properly-vouched-for"&gt;Private access does not prove the consumer was ever properly vouched for
&lt;/h3&gt;&lt;p&gt;A service may be reachable only over Private Endpoint and still be exposed to environments that were never meaningfully validated as legitimate consumers.&lt;/p&gt;
&lt;p&gt;That is the central operational mistake: teams use private reachability as a proxy for consumer legitimacy.&lt;/p&gt;
&lt;p&gt;The path is private. The trust judgement behind it may be weak, inherited, stale, or simply assumed.&lt;/p&gt;
&lt;h3 id="service-owners-can-lose-control-of-access-without-changing-the-service"&gt;Service owners can lose control of access without changing the service
&lt;/h3&gt;&lt;p&gt;If endpoint creation, subnet placement, approval, and DNS are controlled by different operating groups, then access can expand without the target service configuration changing in any obvious way.&lt;/p&gt;
&lt;p&gt;That means a service can look hardened while the practical conditions of who can reach it are being altered elsewhere.&lt;/p&gt;
&lt;h3 id="drift-preserves-trust-long-after-intent-disappears"&gt;Drift preserves trust long after intent disappears
&lt;/h3&gt;&lt;p&gt;A stale Private Endpoint is not just a clean-up problem. It can preserve private access from an environment that has been retired, repurposed, handed to another team, or no longer deserves the implied trust of a live private path.&lt;/p&gt;
&lt;p&gt;Most control-plane risk does not arrive dramatically. It lingers.&lt;/p&gt;
&lt;h3 id="how-would-this-change-something-i-design-deploy-or-operate"&gt;How would this change something I design, deploy, or operate?
&lt;/h3&gt;&lt;p&gt;It should change your review posture.&lt;/p&gt;
&lt;p&gt;Do not stop at “is this service private?” Ask which identities, teams, and approval paths can create or preserve private reachability to it. If the answer depends on administrative sprawl, inherited control, or assumptions about what “internal” means, then the architecture is trusting more than it intends.&lt;/p&gt;
&lt;h2 id="abuse-scenarios-that-matter"&gt;Abuse Scenarios That Matter
&lt;/h2&gt;&lt;p&gt;The risk is not endpoint creation in isolation. The risk appears when endpoint creation, placement into a reachable network, service approval, and usable name resolution combine into a private path that looks legitimate simply because it works.&lt;/p&gt;
&lt;h3 id="a-consumer-environment-gains-a-private-path-it-was-never-meant-to-have"&gt;A consumer environment gains a private path it was never meant to have
&lt;/h3&gt;&lt;p&gt;An operator creates a Private Endpoint into a subnet already reachable by workloads they control. The target service connection is then approved through a weak or overly routine process, and the necessary DNS conditions are in place for those workloads to resolve the service privately.&lt;/p&gt;
&lt;p&gt;Nothing has become public. But a new trusted-looking path now exists from an environment nobody properly vouched for.&lt;/p&gt;
&lt;h3 id="approval-becomes-habit-instead-of-judgement"&gt;Approval becomes habit instead of judgement
&lt;/h3&gt;&lt;p&gt;A team responsible for approving Private Endpoint connections sees requests from “internal” subscriptions and treats them as normal by default. The endpoint is private, the naming looks familiar, and the approval goes through without a real question being asked about whether that consumer environment should have reachability at all.&lt;/p&gt;
&lt;p&gt;That is not a tooling problem. It is trust being inferred from private placement.&lt;/p&gt;
&lt;h3 id="old-environments-retain-private-access-by-inertia"&gt;Old environments retain private access by inertia
&lt;/h3&gt;&lt;p&gt;An application is migrated or retired, but the Private Endpoint remains, DNS still resolves, and the consumer network is still reachable. The original service owner assumes the old path was cleaned up. The platform team assumes the service owner still needs it.&lt;/p&gt;
&lt;p&gt;No one is actively deciding to trust the path. The trust simply never got revoked.&lt;/p&gt;
&lt;h2 id="implementation-example"&gt;Implementation Example
&lt;/h2&gt;&lt;p&gt;This is not a deployment guide, but the resource shape is useful because it exposes where the control-plane split actually lives.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bicep" data-lang="bicep"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;resource&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Microsoft.Network/privateEndpoints@2023-09-01&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;pe-app-sql-prod&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;resourceGroup&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nv"&gt;location&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;subnet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-network-prod/providers/Microsoft.Network/virtualNetworks/vnet-hub-prod/subnets/snet-private-endpoints&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;privateLinkServiceConnections&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;sqlConnection&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;privateLinkServiceId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;/subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/rg-data-prod/providers/Microsoft.Sql/servers/sql-prod-01&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;groupIds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;sqlServer&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;requestMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Prod application connectivity&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The useful part is not the syntax. It is what the object tells you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the endpoint lives in its own management scope;&lt;/li&gt;
&lt;li&gt;the subnet is controlled separately;&lt;/li&gt;
&lt;li&gt;the target service may sit under different ownership;&lt;/li&gt;
&lt;li&gt;the connection request is a trust event before it is a traffic path.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is why “the service is private” is not enough. The service may be private while the authority to create private reachability sits in a different part of the estate entirely.&lt;/p&gt;
&lt;p&gt;You can also inspect Private Endpoint connection state directly:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;az network private-endpoint-connection list &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="se"&gt;&lt;/span&gt; --id &lt;span class="s2"&gt;&amp;#34;/subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/rg-data-prod/providers/Microsoft.Sql/servers/sql-prod-01&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="se"&gt;&lt;/span&gt; --query &lt;span class="s2"&gt;&amp;#34;[].{name:name,status:properties.privateLinkServiceConnectionState.status,description:properties.privateLinkServiceConnectionState.description}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The command matters less than the discipline behind it. If you are not looking at which consumers have private connectivity to a service, you are trusting historical approvals more than current intent.&lt;/p&gt;
&lt;h2 id="gotchas--edge-cases"&gt;Gotchas &amp;amp; Edge Cases
&lt;/h2&gt;&lt;h3 id="working-connectivity-can-disguise-poor-trust-decisions"&gt;Working connectivity can disguise poor trust decisions
&lt;/h3&gt;&lt;p&gt;Once a name resolves privately and the application works, the path starts to feel legitimate by default. But functional connectivity is not proof that the consumer environment was ever supposed to be trusted.&lt;/p&gt;
&lt;h3 id="inconsistent-service-behaviour-creates-false-assumptions"&gt;Inconsistent service behaviour creates false assumptions
&lt;/h3&gt;&lt;p&gt;Private Endpoint approval and ownership patterns vary across Azure services. The risk is not just operational complexity. It is that teams assume a consistent trust model where none exists.&lt;/p&gt;
&lt;h3 id="persistence-is-often-the-bigger-problem-than-deletion"&gt;Persistence is often the bigger problem than deletion
&lt;/h3&gt;&lt;p&gt;Accidental deletion creates incidents, so it gets attention. Quietly persistent connectivity is often more dangerous because it preserves trust without forcing anyone to rejustify it.&lt;/p&gt;
&lt;h2 id="best-practices"&gt;Best Practices
&lt;/h2&gt;&lt;p&gt;This is not a role design or privileged workflow post, so I will stay out of RBAC mechanics. The practical design implications are still clear.&lt;/p&gt;
&lt;h3 id="treat-private-endpoint-creation-as-a-security-relevant-action"&gt;Treat Private Endpoint creation as a security-relevant action
&lt;/h3&gt;&lt;p&gt;Creating a Private Endpoint can extend private reachability to a sensitive service without changing the service configuration itself. That alone makes it worth treating as more than routine network plumbing.&lt;/p&gt;
&lt;h3 id="review-private-consumers-not-just-protected-services"&gt;Review private consumers, not just protected services
&lt;/h3&gt;&lt;p&gt;A service review is incomplete if it asks only how the service is protected and never asks who can privately attach to it.&lt;/p&gt;
&lt;h3 id="treat-subscription-boundaries-as-operational-structure-not-proof-of-trust"&gt;Treat subscription boundaries as operational structure, not proof of trust
&lt;/h3&gt;&lt;p&gt;If the same management actors can still bridge those boundaries, then the separation may be useful administratively while meaningless from a trust perspective.&lt;/p&gt;
&lt;h3 id="make-one-question-unavoidable-in-design-review"&gt;Make one question unavoidable in design review
&lt;/h3&gt;&lt;p&gt;For any sensitive service exposed through Private Endpoint, ask:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Which identities, teams, and approval paths can create, approve, or preserve private reachability to this service, and why should that imply trust in the consuming environment?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If that question is difficult to answer, the trust model is weaker than the network diagram suggests.&lt;/p&gt;
&lt;h3 id="design-lifecycle-ownership-into-the-path-itself"&gt;Design lifecycle ownership into the path itself
&lt;/h3&gt;&lt;p&gt;Private connectivity should have a clear owner, reason for existence, and review trigger. Otherwise, it becomes part of the environment’s inherited internal attack surface.&lt;/p&gt;
&lt;div class="insight"&gt;
&lt;div class="insight-icon"&gt;🍺&lt;/div&gt;
&lt;div class="insight-content"&gt;
&lt;strong&gt;Brewed Insight:&lt;/strong&gt; Private Endpoints are good at making traffic private. They are useless as proof that the private consumer has earned trust. Once private reachability gets mistaken for trusted reachability, the control plane becomes the part of the attack surface nobody is watching.
&lt;/div&gt;
&lt;/div&gt;
&lt;style&gt;
.insight {
display: flex;
align-items: center;
background-color: #0089e41c;
border-left: 10px solid #D69A2D;
padding: 10px;
margin: 20px 0;
border-radius: 4px;
}
.insight-icon {
font-size: 24px;
margin-right: 10px;
}
.insight-content {
flex: 1;
}
&lt;/style&gt;&lt;h2 id="learn-more"&gt;Learn More
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/azure/private-link/private-endpoint-overview" target="_blank" rel="noopener"
&gt;Azure Private Endpoint documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/azure/private-link/private-link-overview" target="_blank" rel="noopener"
&gt;What is Azure Private Link?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/azure/private-link/manage-private-endpoint" target="_blank" rel="noopener"
&gt;Manage a private endpoint connection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/azure/azure-resource-manager/management/overview" target="_blank" rel="noopener"
&gt;Azure resource management overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/azure/private-link/security-considerations" target="_blank" rel="noopener"
&gt;Private Link security considerations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>