Implementing Common Security Patterns

Understanding the NetworkPolicy structure and the rule logic allows us to implement various security postures. Let's look at some common patterns and how you would construct the relevant parts of the networkingv1.NetworkPolicySpec in Go. Remember, these policies need a CNI plugin that enforces them (like Calico, Cilium, etc.) to be effective.

Pattern 1: Default Deny All (Namespace Isolation)

  • Goal: Block all ingress and all egress traffic for every Pod in a specific namespace. This creates a "zero-trust" starting point for the namespace.

  • Strategy: Create a NetworkPolicy that selects all Pods in the namespace (podSelector: {}) and specifies policyTypes: [Ingress, Egress] but provides no ingress or egress rules.

  • YAML Equivalent:

    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: default-deny-all
      namespace: my-secure-namespace
    spec:
      podSelector: {} # Selects all pods
      policyTypes:
      - Ingress
      - Egress
      # No ingress rules defined -> Deny all ingress
      # No egress rules defined -> Deny all egress
  • Go spec Construction:

    import (
        networkingv1 "k8s.io/api/networking/v1"
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    )
    
    policySpec := networkingv1.NetworkPolicySpec{
        // Select all pods in the namespace
        PodSelector: metav1.LabelSelector{}, // Empty LabelSelector selects everything
        // Apply policy to both ingress and egress directions
        PolicyTypes: []networkingv1.PolicyType{
            networkingv1.PolicyTypeIngress,
            networkingv1.PolicyTypeEgress,
        },
        // Ingress rules list is nil/empty - blocks all ingress
        Ingress: []networkingv1.NetworkPolicyIngressRule{}, // Or simply omit
        // Egress rules list is nil/empty - blocks all egress
        Egress: []networkingv1.NetworkPolicyEgressRule{}, // Or simply omit
    }
    
    // Create NetworkPolicy object with this spec...
    // clientset.NetworkingV1().NetworkPolicies(namespace).Create(...)

Pattern 2: Allow All Within Namespace (After Default Deny)

  • Goal: After implementing a default deny, explicitly allow all Pods within the same namespace to communicate freely with each other on any port, while still blocking traffic to/from other namespaces or external IPs.

  • Strategy: Create a policy selecting all Pods (podSelector: {}). Define an ingress rule allowing traffic from any Pod in the same namespace (podSelector: {}). Define an egress rule allowing traffic to any Pod in the same namespace (podSelector: {}). Omit ports to allow all ports.

  • YAML Equivalent:

  • Go spec Construction:

Pattern 3: Allow Specific Ingress (e.g., Frontend to Backend)

  • Goal: Allow ingress traffic only from Pods labeled app=frontend to Pods labeled app=backend on TCP port 8080. Deny all other ingress to the backend Pods.

  • Strategy: Create a policy selecting the backend Pods. Set policyTypes: [Ingress]. Define one ingress rule allowing traffic from Pods matching app=frontend (podSelector) to the specific port (TCP 8080).

  • YAML Equivalent:

  • Go spec Construction:

Pattern 4: Allow Specific Egress (e.g., Backend to Database + DNS)

  • Goal: Allow Pods labeled app=backend to initiate connections only to Pods labeled app=database on TCP port 5432, and also allow them to make DNS queries (to any Pod on UDP/TCP port 53). Deny all other egress.

  • Strategy: Create a policy selecting backend Pods. Set policyTypes: [Egress]. Define two egress rules (remember, rules within the list are ORed):

    • Rule 1: Allows traffic to Pods matching app=database (podSelector) on port TCP 5432.

    • Rule 2: Allows traffic to any destination (omit to or use podSelector: {}) but only on ports UDP 53 and TCP 53.

  • YAML Equivalent:

  • Go spec Construction:

    Note: Allowing DNS is crucial. If you implement default egress deny, you must explicitly allow DNS traffic, otherwise, Pods won't be able to resolve Service names or external hostnames.

Pattern 5: Allow Ingress from Outside Cluster (IP Block)

  • Goal: Allow ingress traffic from a specific external IP range (e.g., 198.51.100.0/24, maybe a corporate network or monitoring service) to Pods labeled role=ingress-gateway on TCP port 443.

  • Strategy: Create a policy selecting the ingress-gateway Pods. policyTypes: [Ingress]. Define one ingress rule allowing traffic from an ipBlock specifying the CIDR, to the specific port (TCP 443).

  • YAML Equivalent:

  • Go spec Construction:

These patterns provide a starting point. By combining these techniques – default deny, specific allows based on pod/namespace selectors or IP blocks, and careful port/protocol specification – you can construct sophisticated Network Policies using client-go to enforce least-privilege network access for your Kubernetes applications.

Last updated

Was this helpful?