Skip to content
kix /docs
Install the CLI

How-to guide Platform capabilities

Enable generated network policy

Generate default-deny and service-allow policies from Kix dependency wiring.

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.

In the calling package, use an address from the dependency’s out API:

how-to/platform/network-policy-client.nix
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;
};

View source on GitHub ↗

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 network policy in the cluster definition:

how-to/platform/network-policy-cluster.nix
networkPolicy = {
enable = true;
defaultDeny = true;
directions = "both";
};

View source on GitHub ↗

defaultDeny = true creates a policy for each managed workload namespace. directions = "both" denies ingress and egress unless another generated rule allows it.

Add the destination and caller instances. For a cross-namespace connection, wire the dependency explicitly:

how-to/platform/network-policy-cluster.nix
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;
};

View source on GitHub ↗

The client runs in apps; the backend Service and its pods run in services.

Evaluate the cluster:

kix-examples/
❱ kix check how-to-platform-network-policy
 TOOL       RESULT  DETAILS                       
 eval       pass    50 manifests evaluated        
 scorecard  pass    0 errors, 44 warnings, 5 info

Inspect the policies produced by the build:

kix-examples/ output excerpt offline capture
❱ kix build how-to-platform-network-policy --output json
Show outputHide output · 138 lines
[
  {
    "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-examples/
❱ kix deploy how-to-platform-network-policy
❱ kubectl get ciliumnetworkpolicies --all-namespaces