nais / fqdn-policy

FQDNNetworkPolicies let you create Kubernetes Network Policies based on Fully Qualified Domain Names(FQDNs) in addition to the standard functionality that only allows IP address ranges (CIDR ranges).
Apache License 2.0
2 stars 1 forks source link

Maintained by NAIS

NAIS, is currently actively managing a fork of the project found at the following GitHub repository. The primary reason for maintaining this forked repository is that the alternative solution provided by Google Cloud Platform has not yet been officially priced or made available. Therefore, NAIS has opted to take control of the project and adapt it to suit other requirements and needs.

By managing this forked repository, NAIS ensures that they can tailor the project to align with objectives and operational requirements effectively. This proactive approach allows NAIS to address needs and maintain control over the project's development, rather than waiting for a solution that may not be readily available or suitable.

A publicly available image is pushed with every commit to main for now, and can be found at fqdn-policy image.

SBOM is generated with cyclonedx, image is signed and attested using cosign.

You can validate the image attestations by executing the following commands:

echo IDENTITY=https://github.com/nais/fqdn-policy/.github/workflows/main.yaml@refs/heads/main
echo ISSUER=https://token.actions.githubusercontent.com
cosign verify-attestation --type=cyclonedx --certificate-oidc-issuer=$ISSUER --certificate-identity=$IDENTITY ghcr.io/nais/fqdn-policy@sha256:xxx

🚨 Warning 🚨

This project is now archived. There is a new official preview feature for FQDN Network Policies built into Google Kubernetes Engine: Control Pod egress traffic using FQDN network policies. While it has the same apiVersion and kind as the API of this project, it is NOT the same thing as this project (which is not an official Google product). We don't guarantee any compatibility between this project and the official GKE feature.

We strongly encourage you to migrate to the new official feature. This project remains available if you want to use it as-is, or fork it.

FQDNNetworkPolicies

FQDNNetworkPolicies let you create Kubernetes Network Policies based on Fully Qualified Domain Names(FQDNs) in addition to the standard functionality that only allows IP address ranges (CIDR ranges). This implementation uses a custom resource definition (CRD) and a controller inside the Kubernetes cluster that periodically polls the DNS service and emits a NetworkPolicy object for every FQDNNetworkPolicy object.

How does it work?

A FQDNNetworkPolicy looks a lot like a NetworkPolicy, but you can configure hostnames in the "to" field:

apiVersion: networking.gke.io/v1alpha3
kind: FQDNNetworkPolicy
metadata:
  name: example
spec:
  podSelector:
    matchLabels:
      role: example
  egress:
    - to:
      - fqdns:
        - example.com
      ports:
      - port: 443
        protocol: TCP

When you create this FQDNNetworkPolicy, the controller will in turn create a corresponding NetworkPolicy with the same name, in the same namespace, that has the same podSelector, the same ports, but replacing the hostnames with corresponding IP addresss it received by polling.

We recommend the use of NodeLocal DNSCache to improve stability of records and reduce the number of DNS requests sent outside of the cluster.

Note: Just like with normal network policies, once specific pods are selected, all not explicitly allowed traffic is denied. Since FQDNNetworkPolicies are egress policies, we recommend to explicitly allow DNS traffic to allow name resolution. See Kubernetes Network Policy Recipes

Annotations

There are 2 annotations to know when working with FQDNNetworkPolicies.

If a NetworkPolicy has been created by a FQDNNetworkPolicy, it has the fqdnnetworkpolicies.networking.gke.io/owned-by set to the name of the FQDNNetworkPolicy. If, when you create a FQDNNetworkPolicy, a NetworkPolicy with the same name already exists, then the FQDNNetworkPolicy will not do anything. You can have the FQDNNetworkPolicy "adopt" the NetworkPolicy by manually setting the fqdnnetworkpolicies.networking.gke.io/owned-by to the right value on the NetworkPolicy.

By default, the NetworkPolicy associated with a FQDNNetworkPolicy gets deleted when you delete the FQDNNetworkPolicy. To prevent this behavior, set the fqdnnetworkpolicies.networking.gke.io/delete-policy annotation to abandon on the NetworkPolicy.

You can disable AAAA lookups for an FQDNNetworkPolicy by setting the fqdnnetworkpolicies.networking.gke.io/aaaa-lookups annotation to skip. The resulting NetworkPolicy will not contain any IPv6 addresses.

Limitations

There are a few functional limitations to FQDNNetworkPolicies:

Use case limitations

The current controller implementation polls all domains from a single controller instance in the Kubernetes cluster and repolls records after the TTL of the first record expires. This leads to the following use case limitations in the current implementation:

An upcoming controller implementation will optionally poll all domains on each node in the cluster, which together with NodeLocal DNSCache can improve stability for dynamic hosts.

Installation

Follow these instructions to install the FQDNNetworkPolicies controller in your GKE cluster.

  1. Install cert-manager.

    kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.11.0/cert-manager.yaml
  2. Install the FQDNNetworkPolicy controller.

    export VERSION=$(curl https://storage.googleapis.com/fqdnnetworkpolicies-manifests/latest)
    kubectl apply -f https://storage.googleapis.com/fqdnnetworkpolicies-manifests/${VERSION}.yaml

Upgrades

Upgrading in place from the v1alpha1 API (used in the 0.1 release) to the v1alpha2 (introduced in the 0.2 release) is not supported. You'll need to uninstall the controller, reinstall it, update your FQDNNetworkPolicies to the v1alpha2 API and recreate them.

In the same manner, upgrading in place from the v1alpha2 API (used in the 0.2 release) to the v1alpha3 (introduced in the 0.3 release) is not supported. You'll need to uninstall the controller, reinstall it, update your FQDNNetworkPolicies to the v1alpha3 API and recreate them.

Uninstall

To uninstall the FQDNNetworkPolicies controller from your GKE cluster, delete the FQDNNetworkPolicies first, and then remove the resources. Replace YOUR_VERSION by the version you are using.

export VERSION=YOUR_VERSION
kubectl delete fqdnnetworkpolicies.networking.gke.io -A --all
kubectl delete -f https://storage.googleapis.com/fqdnnetworkpolicies-manifests/${VERSION}.yaml

Development

This project is built with kubebuilder. We recommend using Kind for your development environment.

Prerequisites

You need the following tools installed on your development workstation.

Building and running locally

  1. Create your Kind cluster.

    make kind-cluster
  2. Deploy cert-manager (necessary for the webhooks).

    make deploy-cert-manager
  3. Build & deploy the controller. This will delete any previous controller pod running, even if it has the same tag.

    make force-deploy-manager
  4. Observe the controller logs and apply valid and invalid resources.

    # In one terminal
    make follow-manager-logs
    # In another terminal
    kubectl apply -f config/samples/networking_v1alpha3_fqdnnetworkpolicy_invalid.yaml
    kubectl apply -f config/samples/networking_v1alpha3_fqdnnetworkpolicy_valid.yaml
  5. Explore the Makefile for other available commands, and read the kubebuilder book.

Creating a release

  1. Tag the commit you want to mark as a release. We follow semantic versioning.
  2. Push the tag to GitHub.
  3. Create a release in GitHub.
  4. If you want that release to be the new default one, run:
    VERSION=$YOUR_TAG make latest