photoncloud-monorepo/docs/architecture/api-gateway.md

3.2 KiB

API Gateway

Role in the topology

  • FiberLB sits in front of the API Gateway and handles inbound L4/L7 load balancing.
  • API Gateway performs HTTP routing, auth, and credit checks before proxying to upstreams.
  • FlashDNS can publish gateway endpoints, but DNS is not coupled to the gateway itself.

gRPC integrations

  • GatewayAuthService.Authorize for authentication and identity headers.
  • GatewayCreditService.Reserve/Commit/Rollback for credit enforcement.
  • IAM and CreditService ship adapters for these services, but any vendor can implement them.

IAM authorization mapping

  • Action: gateway:{route}:{verb} where verb is read|create|update|delete|list|execute derived from HTTP method.
  • Resource: kind gateway_route, id from route_name (fallback to sanitized path).
  • org/project: resolved from token claims or scope; if missing, falls back to x-org-id/x-project-id headers, then system.
  • AuthzContext: request.method, request.path, and metadata keys route, request_id, raw_query.

Builtin roles

  • GatewayAdmin: action gateway:*:*, resource org/${org}/project/${project}/gateway_route/*
  • GatewayReadOnly: actions gateway:*:read and gateway:*:list on the same resource pattern

Configuration (TOML)

http_addr = "0.0.0.0:8080"
log_level = "info"
max_body_bytes = 16777216

[[auth_providers]]
name = "iam"
type = "grpc"
endpoint = "http://127.0.0.1:3000"
timeout_ms = 500

[[credit_providers]]
name = "credit"
type = "grpc"
endpoint = "http://127.0.0.1:3010"
timeout_ms = 500

[[routes]]
name = "public"
path_prefix = "/v1"
upstream = "http://api-backend:8080"
strip_prefix = true

  [routes.auth]
  provider = "iam"
  mode = "required"   # disabled | optional | required
  fail_open = false

  [routes.credit]
  provider = "credit"
  mode = "optional"   # disabled | optional | required
  units = 1
  fail_open = false
  commit_on = "success" # success | always | never
  attributes = { resource_type = "api", ttl_seconds = "300" }

NixOS module example

services.apigateway = {
  enable = true;
  port = 8080;
  maxBodyBytes = 16 * 1024 * 1024;

  authProviders = [{
    name = "iam";
    providerType = "grpc";
    endpoint = "http://127.0.0.1:${toString config.services.iam.port}";
    timeoutMs = 500;
  }];

  creditProviders = [{
    name = "credit";
    providerType = "grpc";
    endpoint = "http://127.0.0.1:${toString config.services.creditservice.grpcPort}";
    timeoutMs = 500;
  }];

  routes = [{
    name = "public";
    pathPrefix = "/v1";
    upstream = "http://api-backend:8080";
    stripPrefix = true;
    auth = {
      provider = "iam";
      mode = "required";
      failOpen = false;
    };
    credit = {
      provider = "credit";
      mode = "optional";
      units = 1;
      failOpen = false;
      commitOn = "success";
      attributes = {
        resource_type = "api";
        ttl_seconds = "300";
      };
    };
  }];
};

Drop-in replacement guidance

  • Implement GatewayAuthService or GatewayCreditService in any language and point the gateway at the gRPC endpoint via auth_providers/credit_providers.
  • Use the headers map in auth responses to inject custom headers (e.g., session IDs).
  • Credit adapters can interpret attributes to map units to internal billing concepts.