Enforce HTTP Intent at a Destination Waypoint
Add method-and-path authorization at the destination waypoint while refusing to claim an HTTPRoute that the repository does not declare.
Run it in the public monorepo
This course is built around the public Zheta Kubernetes Lab monorepo. The excerpt below is runnable source, not pseudocode.
Source: gitops/apps/forge/mesh/ambient-l7/authorization.yaml
spec:
targetRefs: [{ group: "", kind: Service, name: generator }]
action: ALLOW
rules:
- from: [{ source: { principals: [cluster.local/ns/zheta-forge/sa/control-plane] } }]
to: [{ operation: { methods: [POST], paths: [/generate] } }]
Code to reality
- Declared intent
- Allow one authenticated control-plane HTTP operation at the generator destination waypoint.
- Interpreter
- Istiod attaches the targetRef policy to the destination waypoint, whose Envoy proxy parses method and path.
- Software effect
- POST /generate proceeds for the control-plane principal while other methods, paths, or principals do not match.
- Hardware effect
- The waypoint Pod spends node CPU and memory on HTTP parsing, authorization, telemetry, and forwarded network traffic.
- Observable evidence
- Gateway readiness, policy generation, allowed POST, wrong-method denial, and explicit HTTPRoute absence prove the claim.
Start with the people and the result they need
The source tables below remain the detailed contract. Begin with these customer paths:
- D33-UC-01
- Person: Enterprise builder
- Job: Generate, publish, inspect evidence, and manage runtime through approved Forge APIs
- Observable result: Control plane reaches only the declared Service methods and paths through the destination waypoint
- D33-UC-02
- Person: Delivery operator
- Job: Introduce destination HTTP policy without inventing traffic-management behavior
- Observable result: Gateway is Accepted and Programmed; source contains exact targetRefs policies and no HTTPRoute
Turn each customer job into a testable story
Now turn each customer job into a story with a result that an engineer can check:
- D33-US-01
- Story: As an enterprise builder, I want control-plane calls limited by method and path, so that service identity does not imply every API action
- Observable acceptance: Positive and denied traces identify source principal, target Service, method, path, policy generation, environment, and time
- D33-US-02
- Story: As a delivery operator, I want routing claims tied to checked-in HTTPRoute source, so that a waypoint Gateway is not mistaken for customer traffic…
- Observable acceptance: Review proves Gateway readiness, four L7 policies, zero HTTPRoute objects, source revision, and explicit routing veto
Add real state and observable proof
Finally trace each story through the system that owns its state and the evidence that proves the outcome:
- D33-FLOW-01
- Trigger: Builder requests POST /generate through the control plane
- Responsible systems: source ztunnel, forge-waypoint Gateway/Envoy, Istiod, generator/runtime/evidence/broker Services
- Authoritative state: Git targetRefs policy plus Kubernetes Gateway and AuthorizationPolicy status; Forge stores own product result
- Owned record: WaypointBinding
- Observable evidence: Principal, Gateway UID, policy generation, method/path, response, environment, timestamp, run, and trace
- Failure signal: Waypoint bypass, wrong targetRef, allowed forbidden method, or denied approved product request
- D33-FLOW-02
- Trigger: Approved identity sends a forbidden method or reviewer claims route behavior
- Responsible systems: Gateway API, Istiod Gateway controller, Argo/Kubernetes query, reviewer
- Authoritative state: Git is desired-state authority; Kubernetes API is observed-state authority
- Owned record: L7PolicyRevision
- Observable evidence: HTTP 403, zero HTTPRoute claim, unaffected artifact response, source revision, environment, time, and test ID
- Failure signal: Gateway not Accepted/Programmed, unexpected HTTPRoute, unsupported routing claim, or missing positive control
The enterprise problem and today’s slice
Enterprise problem: Connection-level permission cannot distinguish “generate an artifact” from “delete a runtime,” so an allowed caller may still perform an unsafe HTTP action. Whole-course context: The incoming ambient-l4-local gate authenticates direct ServiceAccount connections and has live positive/denied evidence, but it deliberately has no waypoint or HTTP policy. Today’s slice: Applying full ambient-local adds the destination waypoint, selects it on the namespace, rewrites all five L4 destinations to accept only the waypoint principal, and adds four exact targetRefs L7 policies. Gateway API supplies the waypoint Gateway, but this repository declares no HTTPRoute, so no traffic split or rewrite is claimed. End-of-day evidence: Accepted/Programmed waypoint, waypoint-only L4 rewrite, exact L7 policies, verifier-executed POST success, verifier-executed GET 403, no-HTTPRoute check, environment, time, run, and trace prove the boundary. Still unsolved: Migration, telemetry, failure recovery, rollback, and EKS ownership follow next.
Customer use cases
Identity-only access is too broad when one service exposes several actions with different customer consequences.
| Use case ID | Actor | Customer job | Success outcome | Denial or recovery evidence |
|---|---|---|---|---|
| D33-UC-01 | Enterprise builder | Generate, publish, inspect evidence, and manage runtime through approved Forge APIs | Control plane reaches only the declared Service methods and paths through the destination waypoint | Correct identity using a wrong HTTP method or path receives an authorization denial |
| D33-UC-02 | Delivery operator | Introduce destination HTTP policy without inventing traffic-management behavior | Gateway is Accepted and Programmed; source contains exact targetRefs policies and no HTTPRoute | Any routing, retry, split, or rewrite claim is vetoed until a reviewed HTTPRoute exists and is observed |
Actor-centred user stories
An L7 rule can look precise yet attach to the wrong resource, so acceptance must prove both the target Service and the HTTP operation.
| Story ID | Use case IDs | User story | Observable acceptance conditions |
|---|---|---|---|
| D33-US-01 | D33-UC-01 | As an enterprise builder, I want control-plane calls limited by method and path, so that service identity does not imply every API action | Positive and denied traces identify source principal, target Service, method, path, policy generation, environment, and time |
| D33-US-02 | D33-UC-02 | As a delivery operator, I want routing claims tied to checked-in HTTPRoute source, so that a waypoint Gateway is not mistaken for customer traffic policy | Review proves Gateway readiness, four L7 policies, zero HTTPRoute objects, source revision, and explicit routing veto |
End-to-end product flows
The customer-visible flow must survive policy, while a nearby unsafe action must fail for the intended L7 reason.
| Flow ID | Use case IDs | Path | Trigger | Numbered steps | Terminal evidence |
|---|---|---|---|---|---|
| D33-FLOW-01 | D33-UC-01 | Happy | Builder requests POST /generate through the control plane | 1. Authenticate control-plane ServiceAccount. 2. Tunnel to destination waypoint. 3. Match generator Service targetRef. 4. Match POST and /generate. 5. Forward to generator. 6. Return artifact response. | Principal, Gateway UID, policy generation, method/path, response, environment, timestamp, run, and trace |
| D33-FLOW-02 | D33-UC-01, D33-UC-02 | Denied | Approved identity sends a forbidden method or reviewer claims route behavior | 1. Record approved precondition. 2. Send one wrong-method request. 3. Require HTTP 403 from waypoint policy. 4. Query HTTPRoute objects and source. 5. Record zero-route result. 6. Replay approved call. | HTTP 403, zero HTTPRoute claim, unaffected artifact response, source revision, environment, time, and test ID |
The smallest path names the customer action precisely. That precision is what L7 policy must preserve.
System design derived from the flows
Ztunnel does not parse HTTP headers or methods, so the destination waypoint becomes the explicit L7 enforcement point.
| Use case ID | Entry point | Responsible services | Authoritative store | Failure evidence |
|---|---|---|---|---|
| D33-UC-01 | Forge control-plane API | source ztunnel, forge-waypoint Gateway/Envoy, Istiod, generator/runtime/evidence/broker Services | Git targetRefs policy plus Kubernetes Gateway and AuthorizationPolicy status; Forge stores own product result | Waypoint bypass, wrong targetRef, allowed forbidden method, or denied approved product request |
| D33-UC-02 | Gateway and route review | Gateway API, Istiod Gateway controller, Argo/Kubernetes query, reviewer | Git is desired-state authority; Kubernetes API is observed-state authority | Gateway not Accepted/Programmed, unexpected HTTPRoute, unsupported routing claim, or missing positive control |
The destination waypoint adds HTTP interpretation to the existing identity path. The separate route veto prevents a Gateway object from being misread as routing desired state.
Istio states that waypoints are destination-side proxies for L7 policy and telemetry and are unused until a namespace, Service, or Pod selects them (Istio waypoint configuration). Ambient L7 authorization must use targetRefs to attach policy to the waypoint’s parent Service (Istio policy migration).
Data model and ownership
HTTP authorization and routing are different desired-state records, so absence of an HTTPRoute is meaningful and must remain visible.
Generated-application database: Not created in this slice — existing generated-app data remains application-owned while mesh policy and evidence records govern only hosted-runtime traffic.
| Record or entity | Store and owner | Primary key | Foreign key or opaque reference | Tenant key | Material constraint | Lifecycle and deletion | Use case IDs |
|---|---|---|---|---|---|---|---|
| WaypointBinding | Kubernetes API, owned by Runtime Networking | namespace plus Gateway name | Local namespace label and GatewayClass refs | environment_id | Namespace selects exactly forge-waypoint; Gateway must be Accepted and Programmed | Apply, observe, upgrade, unenroll before deletion, retain audit | D33-UC-01, D33-UC-02 |
| L7PolicyRevision | Git and Kubernetes API, owned by Runtime Security | policy name plus generation | Local Service targetRef and source principal refs | environment_id | Method/path rule attaches to one destination Service; principal remains exact | Review, reconcile, supersede, remove after Service retirement | D33-UC-01 |
| RouteAbsenceEvidence | Evidence store, owned by Delivery/SRE | review_id plus source_revision | Opaque Gateway query and repository-search refs | environment_id | Zero HTTPRoute desired/live objects; no routing outcome claim | Append on review, replace only with reviewed route evidence, retain with release | D33-UC-02 |
The policy and binding records now have explicit lifecycles. Route absence evidence makes the boundary falsifiable without inventing an HTTP routing feature.
Declare the destination waypoint and L7 policy
A waypoint name alone does nothing, so the exact Gateway, namespace selection, and Service-targeted policy must agree.
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: forge-waypoint
namespace: zheta-forge
labels:
istio.io/waypoint-for: service
spec:
gatewayClassName: istio-waypoint
listeners:
- name: mesh
port: 15008
protocol: HBONE
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: generator-from-control-plane
namespace: zheta-forge
spec:
targetRefs: [{ group: "", kind: Service, name: generator }]
action: ALLOW
rules:
- from: [{ source: { principals: [cluster.local/ns/zheta-forge/sa/control-plane] } }]
to: [{ operation: { methods: [POST], paths: [/generate] } }]
These excerpts are byte-exact from gitops/apps/forge/mesh/ambient-l7/waypoint.yaml and authorization.yaml. The component also patches all five L4 boundaries to the forge-waypoint principal and defines destination policies for runtime, evidence, and broker; it defines no HTTPRoute.
| Effect field | What happens |
|---|---|
| Declared intent | Create a Service waypoint and allow only control-plane POST /generate at the generator destination |
| Interpreter | Gateway API validates the Gateway; Istiod creates/configures waypoint Envoy and distributes targetRef policy |
| Software effect | Namespace-selected service traffic traverses the waypoint; matching HTTP request proceeds and wrong operations are denied |
| Hardware effect | Waypoint Pod consumes node CPU/memory and adds network processing; application Pods receive no sidecar container |
| Evidence | Gateway Accepted/Programmed, policy generation, waypoint Pod, allowed POST, denied method, zero HTTPRoute query, trace |
Verify policy and the route veto
Gateway readiness does not prove HTTP authorization or routing, so inspect all three claims independently.
: "${MESH_CONTEXT:?set the exact kubectl context}"
kubectl --context "$MESH_CONTEXT" apply -k gitops/apps/forge/overlays/ambient-local
MESH_CONTEXT="$MESH_CONTEXT" ./scripts/verify-istio-ambient.sh l7
kubectl --context "$MESH_CONTEXT" -n zheta-forge wait gateway/forge-waypoint --for=condition=Programmed --timeout=180s
kubectl --context "$MESH_CONTEXT" -n zheta-forge get authorizationpolicy generator-from-control-plane runtime-from-control-plane evidence-from-control-plane broker-from-publishers
if kubectl --context "$MESH_CONTEXT" -n zheta-forge get httproute -o name | grep -q .; then
echo "route veto: implementation unexpectedly contains HTTPRoute desired state" >&2
exit 1
fi
The scoped repository verifier is executable evidence, not an instruction comment: it checks enrollment and L4 prerequisites, requires the namespace waypoint label, waits for Gateway Accepted/Programmed and waypoint rollout, verifies all four targetRef policies, then sends authenticated POST /generate and requires a generated artifact. It immediately sends GET /generate from the same control-plane workload and accepts only HTTP 403. A successful kubectl get without these requests is not L7 proof.
Gateway API’s HTTPRoute resource models HTTP routing rules, but installing its CRD or creating a Gateway does not create a route (Gateway API HTTPRoute).
Before and after, side by side
L4 identity previously answered only whether the control plane could connect, leaving every HTTP operation equally reachable. The waypoint now permits specific destination methods and paths while routing remains explicitly undeclared.
Key takeaways
The waypoint is an L7 enforcement point; it is not itself an HTTP routing policy.
- Attach ambient L7 policy to destination Services with
targetRefs. - Prove both allowed and denied HTTP operations using the same authenticated caller.
- Claim route behavior only when an HTTPRoute exists in Git, is Accepted, and changes observed requests.
Checklist
L7 policy is ready only when attachment, behavior, and absence claims are independently verified.
- [ ] Gateway Accepted and Programmed with namespace selection recorded
- [ ] Full
ambient-localreplaces the Day 32 direct L4 principals with waypoint-only L4 principals - [ ] Four exact Service-targeted policies reconciled
- [ ] Repository L7 verifier executes allowed POST and requires wrong-method GET
403 - [ ] Zero HTTPRoute desired/live state recorded; no routing outcome claimed