# Declare platform intents for non-Kix-managed pods

Use a platform intent when pods installed outside Kix need explicit network
access. An intent identifies those pods and describes their required ingress or
egress without adding them to a Kix package.

This guide assumes [generated network policy is
enabled](/docs/v0.1/how-to/platform-capabilities/enable-generated-network-policy/)
and the cluster has a network policy enforcer.

## Find a stable pod selector

Inspect the labels on the externally managed pods:

<Command commands={["kubectl get pods -n observability --show-labels"]} />

Choose labels maintained by the system that installs the workload. Avoid pod
names and rollout-specific labels.

## Add the platform intent

Add an entry under `networkPolicy.platformIntents`:

<Snippet {...externalWorkloadIntent} />

This intent selects Pods labelled `app.kubernetes.io/name=metrics-agent` in
the `observability` namespace. It allows DNS lookups and outbound HTTPS.

:::caution[An intent restricts as well as permits]
In Cilium, selecting an endpoint with an egress policy puts that endpoint into
default-deny for egress. After this intent is applied, the selected Pods can
reach DNS and TCP port 443 on the internet, but no other destinations. Existing
traffic, such as scraping an in-cluster target, will be blocked unless you add
a rule for it.

List every destination the workload needs, not just the destination that
prompted the intent. In this example, `observability` contains no Kix
instances, so no generated policy restricted these Pods beforehand.

Omitted directions remain unchanged. This intent declares no `ingress`, so it
does not affect incoming traffic to these Pods.
:::

`to` and `from` accept fixed values rather than arbitrary selectors. `to`
accepts `dns`, `world`, and `apiserver`; `from` accepts `all-pods` and `world`.
Anything else fails evaluation with `unknown egress intent target` or
`unknown ingress intent source`.

`scope = "clusterwide"` creates a cluster-wide policy. The
`targetNamespace` label constraint keeps it scoped to the intended namespace.

## Check the generated policy

Evaluate the cluster:

<Command {...check} />

Inspect the policy generated for the intent:

<Command {...intent} />

The generated endpoint selector contains both the workload label and the
namespace. Its egress rules allow UDP and TCP DNS traffic, plus TCP port 443
to destinations outside the cluster.

Deploy the cluster and inspect the installed policy:

<Command
  commands={[
  "kix deploy how-to-platform-network-policy",
  "kubectl get ciliumclusterwidenetworkpolicy metrics-agent -o yaml",
]}
  cwd="kix-examples/"
/>

If the policy does not select the expected pods, compare its
`endpointSelector.matchLabels` with the labels reported by `kubectl`. All
selector labels must match the same pod.