---
id: SEC06
pillar: security
title: SEC 6. How do you control network flow and limit exposure?
description: Every reachable endpoint is a decision, including outbound ones. Start from deny, open what the workload needs, and remember that egress is how data leaves.
status: draft
services: [kubernetes-engine]
sidebar:
  order: 15
  label: Network controls
source_url: "https://framework.stackit.cloud/architecture/pillars/security/sec-06-network-controls/"
source_file: "docs/architecture/pillars/security/sec-06-network-controls.mdx"
---

Network controls are the layer that assumes the others have failed. A compromised workload holds
credentials, so identity controls are partly bypassed; what remains is what it can reach over the
network.

Two asymmetries shape the work. Inbound exposure is what everyone counts, and outbound is how data
actually leaves. And rules accumulate, because opening one is a five-minute task while closing one
requires knowing what would break.

## Best practices

- [`SEC 6.1`](/architecture/pillars/security/sec-06-network-controls/#sec-61-start-from-deny-and-open-only-the-flows-the-workload-needs) Start from deny and open only the flows the workload needs
- [`SEC 6.2`](/architecture/pillars/security/sec-06-network-controls/#sec-62-treat-every-publicly-reachable-endpoint-as-a-decision-with-an-owner) Treat every publicly reachable endpoint as a decision with an owner
- [`SEC 6.3`](/architecture/pillars/security/sec-06-network-controls/#sec-63-control-egress-because-that-is-how-data-leaves) Control egress, because that is how data leaves
- [`SEC 6.4`](/architecture/pillars/security/sec-06-network-controls/#sec-64-verify-inside-the-segment-rather-than-trusting-it) Verify inside the segment rather than trusting it

---

## SEC 6.1 Start from deny and open only the flows the workload needs

**Risk if not established:** High

Default-deny and default-allow produce different estates over time. Under default-deny, every open
path was requested by someone for a reason. Under default-allow, the paths that exist are whatever
nobody got round to closing, and nobody can tell the difference between the two kinds.

Specify rules narrowly: source, destination, port and protocol. A rule that permits a whole subnet
on all ports because the specific requirement was unclear is a default-allow inside a default-deny
model.

Document why each rule exists, next to the rule. Rules without a stated reason are never removed,
because removing one means finding out what breaks, and that is a worse job than leaving it.
[`OPS 3.1`](/architecture/pillars/operational-excellence/ops-03-everything-as-code/#ops-31-define-every-production-resource-in-version-control) gives you the place to put the reason.

Review them on a cadence, since the reasons expire faster than the rules. Rules referring to
decommissioned systems are the common find, and they are pure exposure with no remaining benefit.

**On STACKIT.** <LinkChip href="https://docs.stackit.cloud/products/network/core-networking/security-groups/">Security
groups</LinkChip> are the
instance-level control, with
<LinkChip href="https://docs.stackit.cloud/products/network/core-networking/security-groups/basics/concepts/">concepts</LinkChip>
describing the model and a
<LinkChip href="https://docs.stackit.cloud/products/network/core-networking/security-groups/how-tos/create-and-manage-security-groups-and-rules/">how-to</LinkChip>
for managing rules.

For centralized management across an environment, <LinkChip href="https://docs.stackit.cloud/products/network/network-security/">network
security</LinkChip> provides the <LinkChip href="https://docs.stackit.cloud/products/network/network-security/unified-firewall/">Unified
Firewall</LinkChip>, with
its own <LinkChip href="https://docs.stackit.cloud/products/network/network-security/unified-firewall/how-tos/create-and-manage-firewall-rules/">rule
management</LinkChip>.
The two are complementary: per-instance groups for workload-specific flows, central firewall for
policy that should not depend on every team getting it right.

Define both in code under [`OPS 3.1`](/architecture/pillars/operational-excellence/ops-03-everything-as-code/#ops-31-define-every-production-resource-in-version-control). Network rules edited by hand are the classic source of drift,
and a rule nobody can explain is one nobody will remove.

**Tradeoffs.** **Reliability.** A missing rule is an outage whose symptom looks like an
application timeout, which makes it slow to diagnose. **Operational Excellence.** Every new
integration needs a rule, which is friction proportional to how often the architecture changes.

**Verify.** Take one workload. List every inbound rule that applies to it and the reason for each.
How many reasons can you find written down?

---

## SEC 6.2 Treat every publicly reachable endpoint as a decision with an owner

**Risk if not established:** High

Public exposure is the attack surface an attacker does not need a foothold to reach. It should be
a short list, and in most estates it is longer than anyone expects.

The ones that surprise people: management interfaces exposed for convenience, database ports open
from a migration, a load balancer created with a public address by default, a storage bucket made
readable to share one file, and staging environments that were never meant to be reachable.

Enumerate rather than remember. Ask what is reachable from the internet and answer it by
measurement, since the mental model and the reality diverge in exactly the places that matter.

For each, record why it is public and who owns it. Endpoints without an owner are the ones that
stay exposed after the reason has gone.

Public and unauthenticated are different questions. A public endpoint behind strong authentication
is a different risk from an open one, and both belong on the list.

**On STACKIT.**
<LinkChip href="https://docs.stackit.cloud/products/security/cspm/">CSPM</LinkChip> checks for exactly this class of
problem, and publicly readable object storage buckets are named in its documentation as an example
finding. That makes the enumeration something you receive rather than something you have to build,
which is a meaningful head start on the hardest part of this best practice.

For Kubernetes, <LinkChip href="https://docs.stackit.cloud/products/runtime/kubernetes-engine/how-tos/enable-private-clusters/">private
clusters</LinkChip>
remove the public endpoint of the control plane, which is worth deciding at cluster creation since
it shapes how administrators and pipelines reach it.

The <LinkChip href="https://docs.stackit.cloud/products/security/security-hardening/security-in-networks/">security hardening guidance for
networks</LinkChip>
covers platform-specific practice and is a reasonable starting point rather than a substitute for
your own analysis.

**Tradeoffs.** **Operational Excellence.** Removing public access means administrators and
pipelines need another route, usually a private network path or a bastion, which is infrastructure
to build and operate.

**Verify.** List every endpoint in your environment reachable from the internet. For each, who
owns it, why is it public, and is it authenticated?

---

## SEC 6.3 Control egress, because that is how data leaves

**Risk if not established:** High

Inbound controls stop attackers getting in. Outbound controls stop data getting out, and they are
the ones almost nobody configures.

Unrestricted egress means a compromised workload can reach any destination on the internet: to
exfiltrate data, to fetch tooling, or to receive instructions. Restricting it turns a successful
compromise into a contained one.

The practical version is an allowlist of destinations each workload genuinely needs, which is a
short list for most workloads and an awkward one for anything that fetches dependencies at
runtime. Where a full allowlist is impractical, restricting the workloads that hold sensitive data
is the subset that matters most.

Egress control also surfaces dependencies you did not know you had, which is useful independently.
A workload that unexpectedly calls a third-party service is a finding for [`SOV 6`](/architecture/pillars/sovereignty/sov-06-jurisdictional-chain/) as much as for
security.

**On STACKIT.** Egress rules are expressed in the same places as ingress:
<LinkChip href="https://docs.stackit.cloud/products/network/core-networking/security-groups/">security groups</LinkChip> at
instance level and the
<LinkChip href="https://docs.stackit.cloud/products/network/network-security/unified-firewall/">Unified Firewall</LinkChip>
centrally.

Filtering outbound traffic is not available today, by name or by address. The Unified Firewall
presents and edits the security groups and rules that already exist, centrally and in one view; the
filtering itself is a property of those rules and egress is not among what they express. Plan the
control somewhere you own, which for most workloads means an outbound proxy that resolves and
enforces the allowlist, with the platform boundary carrying only what it can.

Inside Kubernetes, egress restriction between and out of workloads is network policy, which you
configure in the cluster rather than at the platform boundary.

**Tradeoffs.** **Operational Excellence.** Egress allowlists break when a dependency changes its
addresses, and the failure looks like an application error rather than a policy one. Start with
the sensitive workloads rather than everything.

**Verify.** From a workload holding your most sensitive data, which external destinations can it
reach? Is that a list somebody chose?

---

## SEC 6.4 Verify inside the segment rather than trusting it

**Risk if not established:** Medium

Network position is not an identity. A request arriving from inside the network proves only that
something inside the network sent it, and under assume breach that is exactly what you are
defending against.

Internal service calls should authenticate and be authorized on the same evidence as external
ones. That is what turns a compromised workload into a workload that can reach its own data and
nothing else, rather than one that can call every internal service that trusts the network.

Encrypt internal traffic too, which is [`SEC 7.1`](/architecture/pillars/security/sec-07-encryption/#sec-71-encrypt-all-traffic-including-internal-service-to-service-calls). Network segmentation limits who can observe
traffic; it does not make observation impossible, and internal networks are not a trusted medium
under assume breach.

This is the most expensive best practice in the question, because it constrains application design
rather than configuration. Apply it by classification: services handling sensitive data first,
using the mapping from [`SEC 3.2`](/architecture/pillars/security/sec-03-data-classification/#sec-32-let-the-classification-drive-the-controls-mechanically).

**On STACKIT.** Service-to-service authentication is application design.
<LinkChip href="https://docs.stackit.cloud/platform/access-and-identity/service-accounts/">Service accounts</LinkChip> give
each workload an identity to authenticate as when calling platform services, which is [`SEC 4.2`](/architecture/pillars/security/sec-04-identity/#sec-42-give-workloads-their-own-identities-rather-than-sharing-human-credentials);
authenticating calls between your own services is yours to implement.

There is no managed service mesh, so mutual TLS between your services on
<LinkChip href="https://docs.stackit.cloud/products/runtime/kubernetes-engine/">Kubernetes Engine</LinkChip> is either
implemented in your applications or provided by a mesh you install and operate. Both are
legitimate, and the second is a real operational commitment that belongs in [`OPS 10`](/architecture/pillars/operational-excellence/ops-10-toil-elimination/) rather than
being adopted by default.

**Tradeoffs.** **Performance Efficiency.** Per-request authentication adds a lookup, addressed by
caching, which lengthens the window in which a revoked permission still works. **Operational
Excellence.** A mesh is significant infrastructure, and certificate lifecycle between services
becomes something that can fail.

**Verify.** If an attacker controlled one workload in your network, which internal services would
accept its requests without further authentication?

---

## Related

- [`SEC 2.5`](/architecture/pillars/security/sec-02-segmentation/#sec-25-segment-the-network-as-well-as-the-identity-boundary) Segmentation, which this question implements in detail
- [`SEC 7.1`](/architecture/pillars/security/sec-07-encryption/#sec-71-encrypt-all-traffic-including-internal-service-to-service-calls) Encryption in transit, which internal traffic also needs
- [`SEC 1`](/architecture/pillars/security/sec-01-security-baseline/) Security baseline, which should state the exposure rules
- [`SOV 6`](/architecture/pillars/sovereignty/sov-06-jurisdictional-chain/) Jurisdictional chain, which egress findings feed into
- [`REL 5`](/architecture/pillars/reliability/rel-05-resilient-interactions/) Resilient interactions, whose timeouts interact with network controls
