Skip to content

Commit 684faeb

Browse files
committed
remove l7 and deny language from the gep
1 parent d66cd91 commit 684faeb

File tree

1 file changed

+32
-221
lines changed

1 file changed

+32
-221
lines changed

geps/gep-3779/index.md

Lines changed: 32 additions & 221 deletions
Original file line numberDiff line numberDiff line change
@@ -289,17 +289,12 @@ type AuthorizationPolicy struct {
289289
}
290290

291291
// AuthorizationPolicyAction specifies the action to take.
292-
// +kubebuilder:validation:Enum=ALLOW;DENY
292+
// +kubebuilder:validation:Enum=ALLOW
293293
type AuthorizationPolicyAction string
294294

295295
const (
296296
// ActionAllow allows requests that match the policy rules.
297297
ActionAllow AuthorizationPolicyAction = "ALLOW"
298-
299-
// NOTE FOR REVIEWERS AGAIN: GAMMA leads met on 24th July and DENY action is likely going to be pushed to 1.5 and will potentially be extended conformance.
300-
301-
// ActionDeny denies requests that match the policy rules.
302-
ActionDeny AuthorizationPolicyAction = "DENY"
303298
)
304299

305300
// AuthorizationPolicySpec defines the desired state of AuthorizationPolicy.
@@ -333,23 +328,6 @@ type AuthorizationRule struct {
333328
// If omitted, matches any TCP traffic.
334329
// +optional
335330
NetworkAttributes *AuthorizationNetworkAttributes `json:"networkAttributes,omitempty"`
336-
337-
// FOR FUTURE ENHANCEMENT!!
338-
339-
// ApplicationAttributes defines optional application-layer (L7) matching criteria
340-
// used to authorize requests when enforcement is at the APPLICATION level.
341-
//
342-
// All specified fields must match for the rule to apply (logical AND). If omitted,
343-
// the rule matches all application-layer traffic.
344-
//
345-
// Typical use cases include protocol-aware authorization for HTTP, gRPC, or other L7 traffic.
346-
// Fields may vary in applicability based on the protocol and implementation support.
347-
//
348-
// NOTE: ApplicationAttributes are only meaningful when `enforcementLevel` is set to
349-
// Application. Implementations MUST ignore or reject these fields if used at Network level.
350-
351-
// +optional
352-
ApplicationAttributes *AuthorizationApplicationAttributes `json:"applicationAttributes,omitempty"`
353331
}
354332

355333

@@ -445,206 +423,13 @@ Note: Existing AuthorizationAPIs recognized the need to support negation fields
445423

446424
## Future Enhancements
447425

448-
### ALLOW and Deny Policies
449-
450-
#### ALLOW Policy
451-
452-
* An **ALLOW** policy is permissive.
453-
* A request is allowed if:
454-
* It matches at least one rule in any ALLOW policy targeting the workload **and**
455-
* It is not explicitly denied by any DENY policy.
456-
457-
* If no ALLOW policy exists for a workload, traffic is permitted by default.
458-
459-
#### DENY Policies
460-
461-
* A **DENY** policy is restrictive and takes precedence over ALLOW.
462-
* If a request matches any rule in a DENY policy, it is immediately rejected, regardless of matching ALLOW rules elsewhere.
463-
* DENY policies enable to define global blocks or exceptions (for example: “block all traffic from Namespace X”).
464-
465-
#### ALLOW vs. DENY Semantics
426+
### DENY Policies
466427

467-
* **DENY always wins.** If both an ALLOW and a DENY policy match a request, the DENY policy blocks it.
468-
* The presence of any authorization policy causes the system to default to **deny-by-default** for matching workloads.
469-
* Another bullet to re-clarify the one above - the default behavior when no policies select a target workload is to allow all traffic. However, **as soon as at least one `AuthorizationPolicy` targets a workload, the model becomes implicitly deny-if-not-allowed**.
428+
We start without DENY policies in scope, DENY policies _may_ be added in future iterations.
470429

471430
### Future L7 Support
472431

473-
There a few options are available for `targetRef`. This GEP starts by specifying the recommendation, but you will **highly** benefit from going over the alternatives a few times and the detailed comparison at [https://docs.google.com/document/d/1CeagBnHDPbzpYAxBmtJqTshxAW8l-aRPwvwgAGbnv2I/edit?tab=t.0](https://docs.google.com/document/d/1CeagBnHDPbzpYAxBmtJqTshxAW8l-aRPwvwgAGbnv2I/edit?tab=t.0) to understand how we got to this recommendation.
474-
475-
#### Recommended Option - Hybrid TargetRef and VAP
476-
477-
One unified authorization policy API with implementation-specific validation using Validating Admission Policies (VAP). Additionally introducing a new `enforcementLevel` enum to simplify validation and enable the user to clarify intent.
478-
479-
```go
480-
481-
// EnforcementLevel defines the scope at which an AuthorizationPolicy is enforced.
482-
//
483-
// There are two enforcement levels:
484-
//
485-
// - Network: Enforces the policy at the network layer (L4), typically at
486-
// network proxies or gateway dataplanes. Only supports attributes available
487-
// at connection time (e.g., source identity, port). Recommended for broad,
488-
// coarse-grained access controls.
489-
//
490-
// - Application: Enforces the policy at the application layer (L7), typically at
491-
// HTTP/gRPC-aware sidecars or L7 proxies. Enables fine-grained authorization
492-
// using protocol-specific attributes (e.g., HTTP paths, methods).
493-
//
494-
// This field clarifies policy intent and informs where enforcement is expected
495-
// to happen. It also enables implementation-specific validation and behavior.
496-
//
497-
// +kubebuilder:validation:Enum=Network;Application
498-
type EnforcementLevel string
499-
500-
```
501-
502-
```yaml
503-
# Network-scoped policy (L4 enforcement points)
504-
kind: AuthorizationPolicy
505-
metadata:
506-
name: network-authz
507-
spec:
508-
enforcementLevel: "Network" # Enforced at L4 proxies
509-
targetRef:
510-
kind: Pod
511-
selector: {}
512-
rules:
513-
- authorizationSource:
514-
serviceAccount: ["default/productpage"]
515-
networkAttributes:
516-
ports: [9080]
517-
518-
# Application-scoped policy (L7-only enforcement points and sidecars)
519-
kind: AuthorizationPolicy
520-
metadata:
521-
name: app-authz
522-
spec:
523-
enforcementLevel: "Application" # Enforced at L7 proxies
524-
targetRef: # Service for Ambient implementations, label-selector for sidecar implementations.
525-
rules:
526-
- authorizationSource:
527-
serviceAccount: ["default/productpage"]
528-
networkAttributes:
529-
ports: [9080]
530-
applicationAttributes:
531-
paths: ["/api/*"]
532-
methods: ["GET", "POST"]
533-
534-
535-
```
536-
537-
##### Mesh Implementation Behavior
538-
539-
Sidecar Meshes
540-
541-
* **Network Level**: Sidecar enforces policy but only uses L4 attributes
542-
* **Application Level**: Sidecar enforces policy with full L4+L7 capabilities
543-
544-
Ambient Meshes
545-
546-
* **Network Level**: Node-L4-proxy enforces policy using labelSelector targeting
547-
* **Application Level**: Waypoint proxy enforces policy using Service targetRef targeting
548-
549-
**VAP Validation**:
550-
551-
* **Sidecar mesh**: Ensures application-level policies don't use targetRef: Service (since sidecars use labelSelector)
552-
* **Ambient**: Ensures application-level policies don't use label-selectors.
553-
* **Both sidecar and ambient:** ensures network level policies **do** use label selectors
554-
555-
Advantages
556-
557-
* **Clear Intent**: Users explicitly state where they want enforcement
558-
* **Flexible Targeting**: Different targetRef types for different enforcement points
559-
* **Migration Path**: Users can start with network-level and upgrade to application-level easily
560-
* **Implementation Alignment**: supporting different meshes architectures
561-
* **Single API**: No duplication of schemas or concepts
562-
* **Validation Clarity**: Clear rules about what's allowed at each level
563-
564-
Disadvantages
565-
566-
* **Complexity**: Users must understand enforcement levels
567-
* **VAP Dependency**: Requires validation rules
568-
569-
570-
#### Alternative 1: Targeting a Service
571-
572-
The `targetRef` can point to a Kubernetes `Service`.
573-
574-
Two implementation options when targeting a Service:
575-
576-
1. Apply authorization policy to all traffic addressed to this Service.
577-
578-
1. Apply authorization policy to all workloads (pods) selected by the Service.
579-
580-
##### Benefits
581-
582-
* **No API Extension Required:** Works with the current PolicyAttachment model in Gateway API without modification.
583-
* **Simplicity:** Intuitive for users familiar with Kubernetes networking concepts.
584-
585-
##### Downsides and Open Questions
586-
587-
However, targeting a `Service` introduces several challenges;
588-
589-
###### Loss Of Service Context
590-
591-
If we go with option 1, apply authorization policy to all traffic addressed to a Service;
592-
593-
This option is very tricky to implement for sidecar-based meshes where the destination sidecar has no knowledge of which Service the request came through.
594-
595-
Here is the very high-level traffic flow for sidecar-based meshes:
596-
597-
```sh
598-
Client → Request to backend-service:8080
599-
→ Source sidecar resolves service → backend-pod-1 (<ip>>:8080)
600-
→ Destination sidecar receives traffic on pod IP
601-
→ Destination sidecar has NO context that this came via "backend-service"
602-
```
603-
604-
Solving this problem either introduces security concern (e.g adding request metadata to indicate which Service was dialed), or unnecessarily complex or in-efficient to solve.
605-
606-
##### A Workload is Part of Multiple Services
607-
608-
Assuming we go with option 2, apply authorization policy to all workloads (pods) selected by the Service.
609-
610-
If a Pod belongs to multiple Services targeted by different authorization policies, precedence rules, may become unclear, leading to unpredictable or insecure outcomes. Even if such rules are explicitly defined, UX could potentially be confusing for users. For example we _could_ apply the following algorithm:
611-
612-
```sh
613-
## Algorithm
614-
For traffic to workload W:
615-
1. Collect all Service-targeted AuthorizationPolicies where Service.selector matches W.labels
616-
2. If no policies collected → Allow (default behavior)
617-
3. If policies collected → Evaluate using union semantics
618-
619-
620-
## Union semantics:
621-
1. For each DENY policy: if request matches → DENY immediately
622-
2. For each ALLOW policy: collect matching rules
623-
3. If any ALLOW rule matches → ALLOW
624-
4. Otherwise → DENY
625-
```
626-
627-
##### Enforcement & Consistency
628-
629-
Assuming we go with option 2, apply authorization policy to all workloads (pods) selected by the Service.
630-
631-
The UX becomes very confusing. Are we going to enforce only if the traffic arrived through the specific Service? Probably not, cause then we are back to the first problem of Service context.
632-
633-
The UX gets weird because even though you target a Service, you essentially get a **workload** policy, thats enforced regardless.
634-
635-
> Note: with Service as a targetRef, of course we are going to need a Service in order to enforce Authorization -- meaning pods/jobs without a Service are completely out of scope.
636-
637-
#### Alternative 2: Targeting xRoutes
638-
639-
The main benefit of this option is that we can more easily scope the authorization enforcement only for "GAMMA" traffic. Whether its more or less confusing is still unclear.
640-
641-
We can target xRoutes (TCPRoute, HTTPRoute, GRPCRoute). However we are back to [Loss Of Service Context](#loss-of-service-context). In sidecar mode, same as we don't have the context of which Service was dialed, we don't have the route information that was responsible for the routing.
642-
643-
> Note: Linkerd solved this with [Reusing HTTPRoute Schema](https://linkerd.io/2.15/features/httproute/) to distinguish between Inbound and Outbound HTTPRoute. However, I doubt we want that as a community feature. (sorry @kflynn)
644-
645-
Another (perhaps, easier-to-address) concern is that if we target xRoutes, it is likely that users would expect this Authorization to work for N/S traffic. Documentation and guidance are nice, but I think this still ends up more confusing for no real value.
646-
647-
#### Alternative 3: Targeting Pods via Label Selectors
432+
It is very likely that graduation of this API will also require adding L7 support to it. However, after numerous conversations on this topic, the decision is to start with L4 only and leave L7 for future iterations. The details of how L7 support could look like is not in scope for this GEP.
648433

649434
Alternatively, the `targetRef` can specify a set of pods using a `LabelSelector` for a more flexible and direct approach.
650435

@@ -669,6 +454,7 @@ If we were to target Label Selectors, the waypoint proxy would get the request,
669454
The additional (and main) downside of `LabelSelector` is the huge increase to the complexity of policy discoverability. See more in [#Enhanced Discoverability with `gwctl`](#enhanced-discoverability-with-gwctl) for more info.
670455

671456

457+
672458
## Graduation Criteria and Guardrails
673459

674460
This GEP is starting as Experimental with X-prefix. We would like to define some guardrails to avoid being stuck with experimental api in the project forever.
@@ -692,8 +478,6 @@ TBD exact FeatureNames.
692478

693479
### Conformance tests
694480

695-
## Appendix
696-
697481
### State of the World
698482

699483
| Aspect | Istio | Linkerd | Cilium |
@@ -888,3 +672,30 @@ spec:
888672
Cilium has the concept of CiliumIdentity. Pods are assigned identities derived from their Kubernetes labels (namespace, app labels, etc.). Cilium’s policy matches based on these label-derived identities. The CiliumIdentity implementation maps an integer to a group of IP addresses (the pod IPs associated with a group of pods). This “integer” and its mapping to pod IP addresses represents the core identity primitive in Cilium.
889673
890674
More on https://docs.cilium.io/en/stable/internals/security-identities/ & https://docs.cilium.io/en/stable/security/network/identity/
675+
676+
## Appendix
677+
678+
### Loss Of Service Context
679+
680+
When applying authorization policy to all traffic addressed to a Service;
681+
682+
This option is very tricky to implement for sidecar-based meshes where the destination sidecar has no knowledge of which Service the request came through.
683+
684+
Here is the very high-level traffic flow for sidecar-based meshes:
685+
686+
```sh
687+
Client → Request to backend-service:8080
688+
→ Source sidecar resolves service → backend-pod-1 (<ip>>:8080)
689+
→ Destination sidecar receives traffic on pod IP
690+
→ Destination sidecar has NO context that this came via "backend-service"
691+
```
692+
693+
Solving this problem either introduces security concern (e.g adding request metadata to indicate which Service was dialed), or unnecessarily complex or in-efficient to solve.
694+
695+
### Label-Selectors aren't Good for Ambient L7
696+
697+
In L7 Ambient, AuthorizationPolicy targets a Service. This Service has to have a waypoint proxy. The policy enforcement point is the waypoint, but it is also the point where the Service VIP resolution happens.
698+
699+
If we were to target Label Selectors, the waypoint proxy would get the request, do VIP resolution and select an endpoint, and then it would require round-tripping to itself for doing policy enforcement.
700+
701+
@howardjohn has actually added that this was actually the first way ambient had implemented authorization, but it has proved to be much less performant.

0 commit comments

Comments
 (0)