Skip to content

AuthGateway

API Version: e6data.io/v1alpha1 Kind: AuthGateway Short Names: ag


1. Purpose

AuthGateway manages a Pomerium-based authentication gateway for protecting E6Data services. It provides:

  • Identity-aware access control via multiple identity providers (Google, Okta, Azure AD, GitHub, OIDC)
  • Passthrough mode for development/testing (routing without authentication)
  • Modular service routing with subdomain or path-based access
  • Per-service policy overrides for fine-grained access control

AuthGateway is separate from TrafficInfra: - TrafficInfra = xDS + Envoy (QueryService gRPC traffic routing) - AuthGateway = Pomerium (authentication gateway for any service)

This separation allows independent scaling, flexible deployment order, and protecting multiple services through a single gateway.

Note: Infrastructure settings (tolerations, nodeSelector, affinity, imagePullSecrets) are inherited from NamespaceConfig in the same namespace.


2. High-level Behavior

When you create an AuthGateway CR, the operator:

  1. Inherits infrastructure settings from NamespaceConfig
  2. Deploys Pomerium proxy for identity-aware routing
  3. Configures service routes based on spec.services
  4. Creates TLS certificates if cert-manager is enabled
  5. Exposes LoadBalancer service for external access

Architecture

                    ┌─────────────────────────────────────────┐
                    │           AuthGateway (Pomerium)        │
                    │                                         │
Internet ──────────▶│  ┌─────────┐ ┌─────────┐ ┌─────────┐  │
                    │  │ query.* │ │  api.*  │ │   /*    │  │
                    │  └────┬────┘ └────┬────┘ └────┬────┘  │
                    └───────┼───────────┼───────────┼───────┘
                            │           │           │
                            ▼           ▼           ▼
                    ┌───────────┐ ┌─────────┐ ┌─────────┐
                    │TrafficInfra│ │API Server│ │   UI    │
                    │  (Envoy)  │ │         │ │         │
                    └─────┬─────┘ └─────────┘ └─────────┘
                    ┌───────────┐
                    │QueryService│
                    │ (Planners) │
                    └───────────┘

Prerequisites

  • NamespaceConfig must exist in the same namespace
  • IDP credentials secret must exist (if authentication enabled)
  • Backend services should exist (can be deployed after AuthGateway)

Child Resources Created

Resource Type Name Pattern Purpose
ConfigMap {name}-pomerium-config Pomerium configuration
Deployment {name}-pomerium Pomerium proxy pods
Service {name}-pomerium External HTTPS endpoint
Certificate {name}-pomerium-cert TLS certificate (if cert-manager enabled)

3. Spec Reference

3.1 Top-level Fields

Field Type Required Default Description
domain string Yes - Base domain for all services
replicas int32 No 2 Number of Pomerium replicas
image ImageSpec No pomerium:v0.27.0 Pomerium image configuration
resources ResourceSpec No 500m/256Mi Resource requirements
authentication AuthenticationSpec No disabled Authentication configuration
tls TLSSpec No - TLS configuration
service ServiceSpec No LoadBalancer Service exposure
services []ServiceRouteSpec No [] Service routes to protect

3.2 Image

Field Type Required Default Description
repository string No pomerium Image registry
name string No pomerium Image name
tag string No v0.27.0 Image tag
pullPolicy string No IfNotPresent Pull policy

3.3 Resources

Field Type Required Default Description
cpu string No 500m CPU request/limit
memory string No 256Mi Memory request/limit

3.4 Authentication

Field Type Required Default Description
enabled bool No false Enable authentication (false = passthrough mode)
idp IDPSpec No - Identity provider configuration
policy PolicySpec No - Global access policy

3.4.1 IDP

Field Type Required Default Description
provider string No - Provider type: google, okta, azure, github, oidc
credentialsSecretRef.name string No - Secret with IDP_CLIENT_ID and IDP_CLIENT_SECRET
issuerURL string No - OIDC issuer URL (required for okta, oidc)

3.4.2 Policy

Field Type Required Default Description
allowedDomains []string No [] Allowed email domains
allowedEmails []string No [] Allowed email addresses
allowedGroups []string No [] Allowed groups (requires IDP group sync)

3.5 TLS

Field Type Required Default Description
certManager.enabled bool No false Use cert-manager
certManager.issuerRef.name string No - Issuer name
certManager.issuerRef.kind string No ClusterIssuer Issuer or ClusterIssuer
secretName string No - Pre-existing TLS secret

3.6 Service

Field Type Required Default Description
type string No LoadBalancer Service type
annotations map No {} Service annotations

3.7 Services

Each service route defines a backend to protect:

Field Type Required Default Description
name string Yes - Unique route identifier
enabled bool No true Enable this route
subdomain string No - Subdomain routing (e.g., query → query.domain.com)
pathPrefix string No - Path routing (e.g., /api → domain.com/api/*)
backend.serviceName string Yes - Backend Kubernetes service
backend.servicePort int32 Yes - Backend service port
backend.namespace string No same Backend namespace
timeout string No 30s Request timeout
allowWebsockets bool No false Enable WebSocket/gRPC-web
preserveHostHeader bool No false Preserve original Host header
policy PolicySpec No - Override global policy for this route

4. Status Reference

Field Type Description
phase string Current phase (Pending, Deploying, Ready, Degraded, Failed)
message string Human-readable status message
endpoint string External gateway URL
authenticationEnabled bool Whether authentication is active
pomeriumReady bool Pomerium deployment is ready
certificateReady bool TLS certificate is ready
services []ServiceRouteStatus Per-service status
conditions []Condition Detailed conditions
observedGeneration int64 Generation observed by controller
lastTransitionTime Time Last status transition

5. Example CRs

Minimal (Passthrough Mode)

For testing without authentication:

apiVersion: e6data.io/v1alpha1
kind: AuthGateway
metadata:
  name: auth
  namespace: workspace-dev
spec:
  domain: dev.internal.example.com

  authentication:
    enabled: false  # Passthrough mode

  service:
    type: ClusterIP

  services:
    - name: query
      subdomain: query
      backend:
        serviceName: envoy
        servicePort: 8080

Production (with Authentication)

apiVersion: e6data.io/v1alpha1
kind: AuthGateway
metadata:
  name: auth
  namespace: workspace-prod
spec:
  domain: e6data.example.com
  replicas: 2

  authentication:
    enabled: true
    idp:
      provider: google
      credentialsSecretRef:
        name: pomerium-idp-credentials
    policy:
      allowedDomains:
        - "yourcompany.com"

  tls:
    certManager:
      enabled: true
      issuerRef:
        name: letsencrypt-prod
        kind: ClusterIssuer

  service:
    type: LoadBalancer

  services:
    # Query Engine (via TrafficInfra Envoy)
    - name: query
      enabled: true
      subdomain: query
      backend:
        serviceName: envoy
        servicePort: 8080
      timeout: "300s"
      allowWebsockets: true

    # API Server
    - name: api
      enabled: true
      subdomain: api
      backend:
        serviceName: e6-apiserver
        servicePort: 8080

    # UI Dashboard
    - name: ui
      enabled: true
      pathPrefix: /
      backend:
        serviceName: e6-ui
        servicePort: 3000

Multi-IDP (Okta)

apiVersion: e6data.io/v1alpha1
kind: AuthGateway
metadata:
  name: auth
  namespace: workspace-prod
spec:
  domain: query.mycompany.com

  authentication:
    enabled: true
    idp:
      provider: okta
      credentialsSecretRef:
        name: okta-credentials
      issuerURL: "https://mycompany.okta.com"
    policy:
      allowedGroups:
        - "engineering"
        - "data-team"

  services:
    - name: query
      backend:
        serviceName: envoy
        servicePort: 8080

6. Identity Provider Configuration

Google Workspace

  1. Create OAuth 2.0 credentials in Google Cloud Console
  2. Set authorized redirect URI: https://authenticate.<domain>/oauth2/callback
  3. Create secret:
kubectl create secret generic pomerium-idp-credentials \
  --namespace=workspace-prod \
  --from-literal=IDP_CLIENT_ID="<client-id>.apps.googleusercontent.com" \
  --from-literal=IDP_CLIENT_SECRET="<client-secret>"

Okta

  1. Create OIDC application in Okta Admin Console
  2. Set redirect URI: https://authenticate.<domain>/oauth2/callback
  3. Create secret with credentials and set issuerURL

Azure AD

  1. Register application in Azure Portal
  2. Add redirect URI: https://authenticate.<domain>/oauth2/callback
  3. Create secret with Application (client) ID and client secret

7. Relationship with TrafficInfra

AuthGateway can route traffic to TrafficInfra's Envoy for authenticated query access:

services:
  - name: query
    subdomain: query
    backend:
      serviceName: envoy  # TrafficInfra's Envoy service
      servicePort: 8080
    timeout: "300s"
    allowWebsockets: true  # For gRPC-web
    preserveHostHeader: true

Deployment Order: AuthGateway does NOT require TrafficInfra to exist first. If the backend service isn't available, the route shows as "pending" until TrafficInfra is deployed.


8. Troubleshooting

Common Issues

Symptom Possible Cause Solution
401 Unauthorized IDP misconfigured Check credentials secret and redirect URI
403 Forbidden Policy mismatch Verify allowedDomains/allowedGroups
Certificate error TLS not ready Check cert-manager logs and Certificate CR
Backend unreachable Service not found Verify backend service exists

Debugging Commands

# Check AuthGateway status
kubectl get authgateways -n workspace-prod
kubectl describe authgateway auth -n workspace-prod

# Check Pomerium pods
kubectl get pods -n workspace-prod -l app=pomerium
kubectl logs -n workspace-prod -l app=pomerium

# Check TLS certificate (if using cert-manager)
kubectl get certificates -n workspace-prod

# Check IDP credentials secret
kubectl get secret pomerium-idp-credentials -n workspace-prod -o yaml

9. Cloud-Specific LoadBalancer Configuration

AWS Network Load Balancer (NLB)

For AWS with SSL termination at the NLB:

apiVersion: e6data.io/v1alpha1
kind: AuthGateway
metadata:
  name: auth
  namespace: workspace-prod
spec:
  domain: query.example.com
  replicas: 2

  service:
    type: LoadBalancer
    loadBalancerClass: service.k8s.aws/nlb
    annotations:
      # NLB configuration
      service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
      service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip

      # SSL/TLS termination at NLB
      service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "arn:aws:acm:<REGION>:<ACCOUNT_ID>:certificate/<CERTIFICATE_ID>"
      service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443"

      # HTTP/2 support for gRPC
      service.beta.kubernetes.io/aws-load-balancer-alpn-policy: HTTP2Only

  services:
    - name: query
      enabled: true
      isGRPC: true
      subdomain: query
      timeout: "30s"
      backend:
        serviceName: workspace-prod-traffic-envoy
        servicePort: 8080

AWS NLB Annotations Reference

Annotation Description Values
aws-load-balancer-scheme Internet or internal facing internet-facing, internal
aws-load-balancer-nlb-target-type Target type for NLB ip, instance
aws-load-balancer-ssl-cert ACM certificate ARN arn:aws:acm:...
aws-load-balancer-ssl-ports Ports for SSL termination 443
aws-load-balancer-alpn-policy ALPN policy for HTTP/2 HTTP2Only, HTTP2Optional, HTTP1Only, None

Internal NLB (Private Access)

For private/internal access only:

service:
  type: LoadBalancer
  loadBalancerClass: service.k8s.aws/nlb
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-scheme: internal
    service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
    service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "arn:aws:acm:..."
    service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443"

GCP Load Balancer

For GCP with managed SSL certificate:

service:
  type: LoadBalancer
  annotations:
    networking.gke.io/load-balancer-type: External
    cloud.google.com/neg: '{"ingress": true}'

Azure Load Balancer

For Azure with internal load balancer:

service:
  type: LoadBalancer
  annotations:
    service.beta.kubernetes.io/azure-load-balancer-internal: "true"

10. Singleton Constraint

Only one AuthGateway is allowed per namespace. The webhook validates this constraint on create.

If you need multiple authentication configurations, use separate namespaces.