Enable generated network policy
Enable generated network policy when you want Kix to restrict workloads using the Service relationships already present in the deployment graph. Kix creates default-deny policies and the allowances each workload needs.
This guide assumes the cluster has a package that provides the
network-policy-enforcer role. Follow Install Cilium / network policy
support
first if the cluster does not have one.
Use a tracked Service endpoint
Section titled “Use a tracked Service endpoint”In the calling package, use an address from the dependency’s out API:
build = { self, scope, backend, ... }: { deployment = scope.mkDeployment { name = scope.instanceName; spec = { replicas = 1; selector.matchLabels = scope.selectorLabels; template.spec.containers = [ { name = "client"; image = "docker.io/library/nginx:1.27-alpine"; env = [ { name = "BACKEND_URL"; value = backend.out.url { }; } ]; } ]; }; };
root = self.deployment; };backend.out.url { } supplies the application with the Service URL and gives
Kix the destination, port, and protocol needed for policy generation. Keep the
endpoint connected to the workload that makes the request.
Not every out field provides enough information for policy generation.
out.fqdn, out.url, and address outputs declared by a package identify the
Service being reached, so Kix can derive an egress rule. Structural values such
as out.name and out.selector create a dependency edge but no network-policy
rule. Using one as an address can therefore pass kix check and still produce
a blocked connection at runtime.
When a workload references a Service without using one of its addresses, Kix
emits a no netpol edge derived trace with the Service name and a suggestion
to use out.fqdn or out.url. This is a warning, not a check failure. If the
reference is intentionally structural, such as a label or display value, mark
it with facts.refOnly to suppress the warning.
Enable policy generation
Section titled “Enable policy generation”Enable network policy in the cluster definition:
networkPolicy = { enable = true; defaultDeny = true; directions = "both"; };defaultDeny = true creates a policy for each managed workload namespace.
directions = "both" denies ingress and egress unless another generated rule
allows it.
Wire the dependency
Section titled “Wire the dependency”Add the destination and caller instances. For a cross-namespace connection, wire the dependency explicitly:
instances.services.backend = { package = packages.echo-server; config.message = "Hello across a generated network policy!"; };
instances.apps.client = { package = clientPackage; deps.backend = ref.services.backend; };The client runs in apps; the backend Service and its pods run in services.
Check the generated policies
Section titled “Check the generated policies”Evaluate the cluster:
❱ kix check how-to-platform-network-policy
TOOL RESULT DETAILS
eval pass 48 manifests evaluated
kubeconform pass skipped (this validation tool is not yet integrated with Kix)
pluto pass skipped (this validation tool is not yet integrated with Kix)
kyverno pass skipped (this validation tool is not yet integrated with Kix)
scorecard pass 0 errors, 45 warnings, 6 info Inspect the policies produced by the build:
❱ kix build how-to-platform-network-policy --output json Show output
[
{
"apiVersion": "cilium.io/v2",
"kind": "CiliumNetworkPolicy",
"metadata": {
"name": "apps-default-deny",
"namespace": "apps"
},
"spec": {
"egress": [
{}
],
"endpointSelector": {},
"ingress": [
{}
]
}
},
{
"apiVersion": "cilium.io/v2",
"kind": "CiliumNetworkPolicy",
"metadata": {
"name": "client-deployment-client-egress",
"namespace": "apps"
},
"spec": {
"egress": [
{
"toEndpoints": [
{
"matchLabels": {
"k8s-app": "kube-dns",
"k8s:io.kubernetes.pod.namespace": "kube-system"
}
}
],
"toPorts": [
{
"ports": [
{
"port": "53",
"protocol": "UDP"
},
{
"port": "53",
"protocol": "TCP"
}
]
}
]
},
{
"toEndpoints": [
{
"matchLabels": {
"app.kubernetes.io/instance": "backend",
"app.kubernetes.io/name": "backend",
"k8s:io.kubernetes.pod.namespace": "services"
}
}
],
"toPorts": [
{
"ports": [
{
"port": "8080",
"protocol": "TCP"
}
]
}
]
}
],
"endpointSelector": {
"matchLabels": {
"app.kubernetes.io/instance": "client",
"app.kubernetes.io/name": "client"
}
}
}
},
{
"apiVersion": "cilium.io/v2",
"kind": "CiliumNetworkPolicy",
"metadata": {
"name": "client-deployment-client-to-backend-ingress",
"namespace": "services"
},
"spec": {
"endpointSelector": {
"matchLabels": {
"app.kubernetes.io/instance": "backend",
"app.kubernetes.io/name": "backend"
}
},
"ingress": [
{
"fromEndpoints": [
{
"matchLabels": {
"app.kubernetes.io/instance": "client",
"app.kubernetes.io/name": "client",
"k8s:io.kubernetes.pod.namespace": "apps"
}
}
],
"toPorts": [
{
"ports": [
{
"port": "8080",
"protocol": "TCP"
}
]
}
]
}
]
}
},
{
"apiVersion": "cilium.io/v2",
"kind": "CiliumNetworkPolicy",
"metadata": {
"name": "services-default-deny",
"namespace": "services"
},
"spec": {
"egress": [
{}
],
"endpointSelector": {},
"ingress": [
{}
]
}
}
] The client egress policy permits DNS and traffic to the backend’s http port.
Kix also places a matching ingress policy in services, scoped to the backend
pods and the client pods in apps. The two namespace default-deny policies
make those allowances effective.
Deploy the cluster, then list the policies installed by Cilium:
❱ kix deploy how-to-platform-network-policy❱ kubectl get ciliumnetworkpolicies --all-namespaces