httproute-controller

module
v0.3.9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 26, 2025 License: MIT

README

HTTPRoute Controller

Go Report Card Release Docker Pulls OpenSSF Scorecard SLSA 3

Kubernetes controller that automatically generates Gateway API HTTPRoutes from Service annotations.

Overview

Convenience controller for creating HTTPRoutes. Watches Services with specific annotations and auto-generates HTTPRoute + ReferenceGrant resources, eliminating manual YAML creation for each exposed service.

Built with:

  • Kubebuilder v4.5.1
  • Gateway API v1.2.1
  • Controller-runtime v0.20.2

Architecture

Controller Name: httproute.controller/service-controller

Reconciliation:

  • Level-based triggers (reconciles full state)
  • Idempotent operations
  • OwnerReferences for same-namespace resources
  • Finalizers for cross-namespace cleanup

Constraints:

  • HTTPRoute must be in gateway namespace (Kubernetes blocks cross-namespace OwnerReferences)
  • ReferenceGrant must be in service namespace
  • Targets single gateway listener section (default: https)
  • Single service per HTTPRoute (no aggregation)

Gateway API Compatibility:

  • Works with any Gateway API compliant implementation
  • Tested with: Envoy Gateway
  • Should work with: Istio, Kong Gateway, Contour, NGINX Gateway Fabric, Traefik, and others
  • Requires Gateway API CRDs v1.0+ (HTTPRoute v1, ReferenceGrant v1beta1)

Features

Annotation-driven automation:

  • Watches Services with httproute.controller/expose: "true" (configurable prefix)
  • Auto-generates HTTPRoute + ReferenceGrant from annotations
  • No manual resource creation required

Cross-namespace security:

  • HTTPRoute deployed in gateway namespace (e.g., envoy-gateway-system)
  • Service remains in application namespace (e.g., default)
  • ReferenceGrant enables secure cross-namespace backend references
  • Prevents unauthorized Service access from other namespaces
  • ReferenceGrant creation can be opted out via annotation (for manual management)

Observability:

  • Kubernetes Events emitted for HTTPRoute/ReferenceGrant creation and deletion
  • Events appear on the Service resource (kubectl describe svc <name>)
  • Detailed logging for all ReferenceGrant operations (security-relevant)

Lifecycle management:

  • Finalizers ensure HTTPRoute cleanup when Service is deleted
  • OwnerReferences auto-delete ReferenceGrant with Service
  • Removing expose: "true" triggers resource cleanup
  • Idempotent reconciliation (safe to run multiple times)

Configuration:

  • Gateway name/namespace configurable per Service via annotations
  • Defaults: main-gateway in gateway-system (configurable via CLI flags)
  • Port selection: explicit annotation or first Service port
  • Listener section: configurable (default: https)
Controller Lifecycle
sequenceDiagram
    participant User
    participant Service
    participant Controller
    participant GatewayNS as Gateway Namespace
    participant ServiceNS as Service Namespace

    User->>Service: Add annotations<br/>(expose=true, hostname)
    Service->>Controller: Reconcile triggered

    Controller->>Controller: Validate annotations
    Controller->>GatewayNS: Create/Update HTTPRoute
    Note over GatewayNS: HTTPRoute: myapp.example.com<br/>Backend: Service in app namespace

    Controller->>ServiceNS: Create/Update ReferenceGrant
    Note over ServiceNS: Allows HTTPRoute to reference Service

    Controller->>Service: Add finalizer
    Note over Service: Ensures cleanup on deletion

    rect rgba(255, 100, 100, 0.1)
        Note over User,ServiceNS: Service Deletion
        User->>Service: Delete Service
        Service->>Controller: Finalizer triggers cleanup
        Controller->>GatewayNS: Delete HTTPRoute
        Controller->>ServiceNS: Delete ReferenceGrant<br/>(via OwnerReference)
        Controller->>Service: Remove finalizer
        Service->>Service: Deletion completes
    end

Usage

Annotations

All annotations use the fixed prefix httproute.controller.

Annotation Required Default Description
httproute.controller/expose Yes - Set to "true" to enable
httproute.controller/hostname Yes - DNS hostname (e.g., myapp.example.com)
httproute.controller/gateway No From controller flag Gateway name override
httproute.controller/gateway-namespace No From controller flag Gateway namespace override
httproute.controller/section-name No https Gateway listener section override
httproute.controller/port No First port Service port
httproute.controller/skip-reference-grant No false Set to "true" to skip ReferenceGrant creation
Example
apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: default
  annotations:
    httproute.controller/expose: "true"
    httproute.controller/hostname: "myapp.example.com"
spec:
  selector:
    app: myapp
  ports:
  - port: 80
    targetPort: 8080

Controller automatically creates:

  1. HTTPRoute (in gateway namespace):

    • Name: default-myapp
    • Hostname: myapp.example.com
    • Backend: Service myapp in namespace default
    • Cleanup via Service finalizer (cross-namespace OwnerRefs not supported)
  2. ReferenceGrant (in service namespace):

    • Name: myapp-backend
    • Allows HTTPRoute from gateway namespace to reference Service
    • OwnerReference to Service (automatic garbage collection)
Controller Configuration

The controller requires gateway configuration at startup:

Flag Helm Value Required Description
--default-gateway controller.defaultGateway Yes Default gateway name
--default-gateway-namespace controller.defaultGatewayNamespace Yes Default gateway namespace
--default-section-name controller.defaultSectionName No (default: https) Gateway listener section

Note: Annotation prefix is fixed to httproute.controller and not configurable.

Installation

From Helm repository:

helm repo add httproute-controller https://piotr1215.github.io/httproute-controller
helm repo update
helm install httproute-controller httproute-controller/httproute-controller \
  --namespace httproute-system \
  --create-namespace \
  --set controller.defaultGateway="my-gateway" \
  --set controller.defaultGatewayNamespace="envoy-gateway-system"

Required: You must set controller.defaultGateway and controller.defaultGatewayNamespace.

From GitHub release:

# Replace v0.3.5 with the desired version
helm install httproute-controller \
  https://github.com/Piotr1215/httproute-controller/releases/download/v0.3.5/httproute-controller-0.3.5.tgz \
  --namespace httproute-system \
  --create-namespace

From source:

helm install httproute-controller ./helm/httproute-controller \
  --namespace httproute-system \
  --create-namespace
Using kubectl
kubectl apply -f https://raw.githubusercontent.com/Piotr1215/httproute-controller/main/dist/install.yaml

Development

Prerequisites
  • go v1.23.0+
  • kubectl v1.11.3+
  • Access to a Kubernetes cluster
  • Gateway API CRDs installed
Local Development

Install Gateway API CRDs:

make install

Run controller locally:

make run

Run tests:

make test

Build and test in cluster:

# Create KIND cluster
kind create cluster --name httproute-test

# Install Gateway API CRDs
kubectl apply -f config/crd/gateway-api/gateway-api-crds.yaml

# Build image
make docker-build IMG=httproute-controller:local

# Load image to KIND
kind load docker-image httproute-controller:local --name httproute-test

# Deploy controller
make deploy IMG=httproute-controller:local

# Run integration tests
make test-e2e

# Cleanup
kind delete cluster --name httproute-test

Uninstall:

make undeploy
make uninstall

Release

Releases are automated via GitHub Actions. To create a new release:

git tag -a v0.2.0 -m "Release v0.2.0"
git push origin v0.2.0

The release pipeline automatically:

  1. Builds and pushes multi-platform Docker images to piotrzan/httproute-controller
  2. Packages the Helm chart with correct version metadata
  3. Generates install.yaml bundle
  4. Creates GitHub release with artifacts
  5. Updates Helm repository index on GitHub Pages

Release artifacts:

  • Docker image: piotrzan/httproute-controller:<version>
  • Helm chart: Available from GitHub releases and Helm repository
  • Install bundle: dist/install.yaml

Security

Image Verification

All container images are signed with Cosign using keyless signing (GitHub OIDC).

Verify image signature:

cosign verify \
  --certificate-identity-regexp="https://github.com/Piotr1215/httproute-controller/.*" \
  --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
  piotrzan/httproute-controller:0.3.5

View SBOM:

docker scout sbom piotrzan/httproute-controller:0.3.5

View provenance attestation:

cosign verify-attestation \
  --type slsaprovenance \
  --certificate-identity-regexp="https://github.com/Piotr1215/httproute-controller/.*" \
  --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
  piotrzan/httproute-controller:0.3.5 | jq .
Release Artifact Verification

GitHub release artifacts (Helm charts, install.yaml) are also signed with Cosign.

Verify Helm chart signature:

# Download release artifacts
VERSION=v0.3.5
wget https://github.com/Piotr1215/httproute-controller/releases/download/${VERSION}/httproute-controller-${VERSION#v}.tgz
wget https://github.com/Piotr1215/httproute-controller/releases/download/${VERSION}/helm-chart.sig

# Verify signature
cosign verify-blob \
  --certificate-identity-regexp="https://github.com/Piotr1215/httproute-controller/.*" \
  --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
  --signature helm-chart.sig \
  httproute-controller-${VERSION#v}.tgz

Verify install.yaml signature:

# Download artifacts
wget https://github.com/Piotr1215/httproute-controller/releases/download/${VERSION}/install.yaml
wget https://github.com/Piotr1215/httproute-controller/releases/download/${VERSION}/install.yaml.sig

# Verify signature
cosign verify-blob \
  --certificate-identity-regexp="https://github.com/Piotr1215/httproute-controller/.*" \
  --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
  --signature install.yaml.sig \
  install.yaml

License

MIT License - see LICENSE file for details.

Directories

Path Synopsis
internal
test

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL