diff --git a/README.md b/README.md index fb50ae0..81cab7a 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,41 @@ # dataplane-payments Layer 2 (Gateway infrastructure) for the **payments** bounded context -(domain team: payments). `DataPlane`, `KonnectExtension`, certs (cert-manager), -secrets (External Secrets Operator) — one Control Plane per environment, -referenced by ID (created by `../konnect-platform`, never recreated here). +(domain team: payments) — one Control Plane per environment, referenced by +ID (created manually in Konnect for now, never recreated here: +`dc3b2a36-e2ad-4da1-a142-022d0ce6d94e` for `dev`). -Content is generated and PR'd automatically when the matching Control -Plane is created via the self-service flow in `../konnect-platform` — -never hand-edited directly. +Same `gateway-kustomization.yaml` / `externalsecret.yaml` / +`policies-kustomization.yaml` three-file pattern as `dataplane-catalog` and +`dataplane-customers` — see `dataplane-catalog/README.md` for the full +explanation of each file's role, identical here, not repeated. Actual +resource template lives in `../k8s-platform/dataplane-template/` and +`../k8s-platform/dataplane-globalpolicy-template/`, this repo only holds +what's specific to `dev/api-gateway/`. + +**IdP**: `https://keycloak.sttlab.local/realms/classic-models` (local +in-cluster Keycloak), same platform-wide default as `catalog`/`customers` +— see `../STATUS.md` sections 15/16. `JWT_AUDIENCE_WHITELIST` is +`["payments-api"]` only so far; no `payments-api` Keycloak client/audience +scope exists yet either (Layer 3 not built) — that whitelist entry is +forward-looking, matches nothing real yet. + +**Only `dev/` is real.** `staging/api-gateway/` and `prod/api-gateway/` +still hold the original TODO placeholder files, not converted, not +deployed, no Control Plane created for them yet. + +**This is Layer 2 (Gateway infrastructure) only — no API is actually +reachable through it.** `Gateway payments-dev`: `Programmed: True`, +DataPlane pod running, TLS cert issued, DNS entry added to +`coredns-custom` (same manual per-domain step documented in +`../STATUS.md` section 17 — not automatic). Smoke-tested: `404` (Gateway +answers, nothing routed — correct, expected). No Layer 3 repo +(`../payments-api`) exists yet; when it does, follow `../customers-api`'s +structure as the reference, not `../catalog-api`'s (customers is the more +recently corrected/simpler pattern — REST-only until an MCP layer is +actually needed, single merged MCP route if one is added — see +`../STATUS.md` section 18 for why). + +Self-service pipeline (`../konnect-platform` generating this content +automatically) does not exist yet — still a stub per `../STATUS.md`. +Everything here is hand-maintained. diff --git a/dev/api-gateway/dataplane.yaml b/dev/api-gateway/dataplane.yaml deleted file mode 100644 index 13c429a..0000000 --- a/dev/api-gateway/dataplane.yaml +++ /dev/null @@ -1,5 +0,0 @@ -# TODO: DataPlane CRD for payments/dev/api-gateway -apiVersion: gateway-operator.konghq.com/v1beta1 -kind: DataPlane -metadata: - name: payments-dev diff --git a/dev/api-gateway/externalsecret.yaml b/dev/api-gateway/externalsecret.yaml new file mode 100644 index 0000000..bb10850 --- /dev/null +++ b/dev/api-gateway/externalsecret.yaml @@ -0,0 +1,27 @@ +# Real PAT lives only in Vault (secrets/kong-v2/payments/dev/konnect-pat), +# never in git, never manually kubectl-applied. refreshInterval controls how +# often ESO re-checks Vault and re-syncs the K8s Secret if the value +# changed there — rotation becomes "update Vault", nothing to touch in the +# cluster. +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: payments-dev-konnect-auth + namespace: payments +spec: + refreshInterval: 1h + secretStoreRef: + kind: ClusterSecretStore + name: vault-kong-v2 + target: + name: payments-dev-konnect-auth + template: + metadata: + labels: + konghq.com/credential: konnect + konghq.com/secret: "true" + data: + - secretKey: token + remoteRef: + key: kong-v2/payments/dev/konnect-pat + property: token diff --git a/dev/api-gateway/gateway-kustomization.yaml b/dev/api-gateway/gateway-kustomization.yaml new file mode 100644 index 0000000..45ecfdf --- /dev/null +++ b/dev/api-gateway/gateway-kustomization.yaml @@ -0,0 +1,37 @@ +# sourceRef points at the GitRepository "k8s-platform" (created once, +# flux-system) — any domain's Kustomization can reference this same +# object, no monorepo: k8s-platform and dataplane-payments stay two +# separate repos, `path` below is relative to the root of whichever repo +# `sourceRef` names. +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: payments-dev-api-gateway + namespace: flux-system +spec: + interval: 10m + sourceRef: + kind: GitRepository + name: k8s-platform + path: ./dataplane-template + prune: true + postBuild: + # Domain-specific non-sensitive values inline — no separate ConfigMap to + # forget to re-apply after an edit. Inline substitute always wins over + # substituteFrom regardless of order, so this still overrides + # dataplane-template-defaults where needed. + substitute: + NAME: payments-dev + NAMESPACE: payments + CONTROL_PLANE_ID: "dc3b2a36-e2ad-4da1-a142-022d0ce6d94e" + HOSTNAME: payments-dev.sttlab.local + # Cluster-wide defaults only — the Konnect PAT is NOT handled via + # substitute/substituteFrom at all: that mechanism requires the source + # Secret to sit in flux-system (same namespace as this Kustomization), + # which put a live copy of the real PAT in a shared, broadly-readable + # namespace. Rejected. The real konnect-auth Secret is materialized + # directly into the payments namespace instead (externalsecret.yaml, via + # External Secrets Operator + Vault) — never passes through flux-system. + substituteFrom: + - kind: ConfigMap + name: dataplane-template-defaults diff --git a/dev/api-gateway/konnectextension.yaml b/dev/api-gateway/konnectextension.yaml deleted file mode 100644 index 224827c..0000000 --- a/dev/api-gateway/konnectextension.yaml +++ /dev/null @@ -1,6 +0,0 @@ -# TODO: KonnectExtension referencing the Control Plane created by -# konnect-platform/domains/payments/dev/ (by ID, not created here) -apiVersion: konnect.konghq.com/v1alpha1 -kind: KonnectExtension -metadata: - name: payments-dev diff --git a/dev/api-gateway/kustomization.yaml b/dev/api-gateway/kustomization.yaml deleted file mode 100644 index 44ec993..0000000 --- a/dev/api-gateway/kustomization.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -resources: - - dataplane.yaml - - konnectextension.yaml diff --git a/dev/api-gateway/policies-kustomization.yaml b/dev/api-gateway/policies-kustomization.yaml new file mode 100644 index 0000000..f937459 --- /dev/null +++ b/dev/api-gateway/policies-kustomization.yaml @@ -0,0 +1,37 @@ +# Split from gateway-kustomization.yaml on purpose: different change +# cadence (policies get tuned far more often than the Gateway itself gets +# recreated) and different blast radius (a bad policy build/prune can't +# touch the Gateway/DataPlane, and vice versa). Same GitRepository, same +# domain namespace, different path. +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: payments-dev-api-gateway-policies + namespace: flux-system +spec: + interval: 10m + sourceRef: + kind: GitRepository + name: k8s-platform + path: ./dataplane-globalpolicy-template + prune: true + postBuild: + substitute: + NAME: payments-dev + NAMESPACE: payments + # Looked up manually after gateway-kustomization.yaml's + # Gateway/GatewayConfiguration first reconciled — the operator + # auto-names the mirrored KonnectGatewayControlPlane with a random + # suffix, not derivable from NAME. + CONTROL_PLANE_REF_NAME: payments-dev-bz6vs + # Every audience valid anywhere in the payments domain — grows as the + # domain gains APIs (e.g. mcp-payments, if an MCP layer is ever added). + JWT_AUDIENCE_WHITELIST: '["payments-api"]' + # Local in-cluster Keycloak is the platform-wide IdP now (see + # ../../../STATUS.md sections 15/16), not dataplane-template-defaults' + # stale VPS value — confirmed reachable in-cluster before wiring this + # in, same pattern as catalog/customers. + OIDC_ISSUER: https://keycloak.sttlab.local/realms/classic-models + substituteFrom: + - kind: ConfigMap + name: dataplane-template-defaults