Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding SectionName to PolicyTargetReference #2283

Merged
37 changes: 32 additions & 5 deletions apis/v1alpha2/policy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ limitations under the License.

package v1alpha2

// PolicyTargetReference identifies an API object to apply policy to. This
// should be used as part of Policy resources that can target Gateway API
// resources. For more information on how this policy attachment model works,
// and a sample Policy resource, refer to the policy attachment documentation
// for Gateway API.
// PolicyTargetReference identifies an API object to apply a direct or
// inherited policy to. This should be used as part of Policy resources
// that can target Gateway API resources. For more information on how this
// policy attachment model works, and a sample Policy resource, refer to
// the policy attachment documentation for Gateway API.
type PolicyTargetReference struct {
// Group is the group of the target resource.
Group Group `json:"group"`
Expand All @@ -40,6 +40,33 @@ type PolicyTargetReference struct {
Namespace *Namespace `json:"namespace,omitempty"`
}

// PolicyTargetReferenceWithSectionName identifies an API object to apply a direct
// policy to. This should be used as part of Policy resources that can target
// single resources. For more information on how this policy attachment mode
// works, and a sample Policy resource, refer to the policy attachment documentation
// for Gateway API.
//
// Note: This should only be used for direct policy attachment when references
// to SectionName are actually needed. In all other cases, PolicyTargetReference
// should be used.
type PolicyTargetReferenceWithSectionName struct {
PolicyTargetReference `json:",inline"`

// SectionName is the name of a section within the target resource. When
// unspecified, this targetRef targets the entire resource. In the following
// resources, SectionName is interpreted as the following:
//
// * Gateway: Listener Name
zhaohuabing marked this conversation as resolved.
Show resolved Hide resolved
// * Service: Port Name
//
zhaohuabing marked this conversation as resolved.
Show resolved Hide resolved
// If a SectionName is specified, but does not exist on the targeted object,
// the Policy must fail to attach, and the policy implementation should record
// a `ResolvedRefs` or similar Condition in the Policy's status.
//
// +optional
SectionName *SectionName `json:"sectionName,omitempty"`
}

// PolicyConditionType is a type of condition for a policy. This type should be
// used with a Policy resource Status.Conditions field.
type PolicyConditionType string
Expand Down
21 changes: 21 additions & 0 deletions apis/v1alpha2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

100 changes: 50 additions & 50 deletions geps/gep-713.md
Original file line number Diff line number Diff line change
Expand Up @@ -1244,20 +1244,44 @@ level. The implementations that support this policy attachment model will have
the same behavior and semantics, although they may not be able to support
attachment of all types of policy at all potential attachment points.

### Apply Policies to Sections of a Resource (Future Extension)
Although initially out of scope, it would be helpful to be able to target
specific matches within nested objects. For example, it may be useful to attach
policies to a specific Gateway listener or Route rule. This section explores
what that could look like.

Each Route rule or Gateway listener should be expanded with an optional name
field. The target ref would be expanded with an optional sectionName field that
could be used to refer to that specific section of the resource. It would refer
to the following concepts on these resources:

* Gateway.Listeners.Name
* xRoute.Rules.Name
### Apply Policies to Sections of a Resource
Policies can target specific matches within nested objects. For instance, rather than
applying a policy to the entire Gateway, we may want to attach it to a particular Gateway listener.

To achieve this, an optional `sectionName` field can be set in the `targetRef` of a policy
to refer to a specific listener within the target Gateway.

```yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: foo-gateway
spec:
gatewayClassName: foo-lb
listeners:
- name: bar
...
---
apiVersion: networking.acme.io/v1alpha2
kind: AuthenticationPolicy
metadata:
name: foo
spec:
provider:
issuer: "https://oidc.example.com"
targetRef:
name: foo-gateway
group: gateway.networking.k8s.io
kind: Gateway
zhaohuabing marked this conversation as resolved.
Show resolved Hide resolved
sectionName: bar
```

The `sectionName` field can also be used to target a specific section of other resources:

* Service.Ports.Name
* xRoute.Rules.Name

For example, the RetryPolicy below applies to a RouteRule inside an HTTPRoute.

```yaml
apiVersion: gateway.networking.k8s.io/v1alpha2
Expand Down Expand Up @@ -1292,43 +1316,8 @@ spec:
sectionName: bar
```

This would require adding a `SectionName` field to the PolicyTargetReference:
```go
type PolicyTargetReference struct {
// SectionName is the name of a section within the target resource. When
// unspecified, this targets the entire resource. In the following
// resources, SectionName is interpreted as the following:
// * Gateway: Listener Name
// * Route: Rule Name
// * Service: Port Name
//
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=253
// +optional
SectionName string `json:"sectionName,omitempty"`
// ...
}
```

This would also require adding a `Name` field to Gateway listeners and Route
rules:

```go
type Listener struct {
// Name is the name of the Listener. If more than one Listener is present
// each Listener MUST specify a name. The names of Listeners MUST be unique
// within a Gateway.
//
// Support: Core
//
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=253
// +optional
Name string `json:"name,omitempty"`
// ...
}
```

This would require adding a `name` field to those sub-resources that currently lack a name. For example,
a `name` field could be added to the `RouteRule` object:
```go
type RouteRule struct {
// Name is the name of the Route rule. If more than one Route Rule is
Expand All @@ -1345,6 +1334,17 @@ type RouteRule struct {
}
```

If a `sectionName` is specified, but does not exist on the targeted object, the Policy must fail to attach,
and the policy implementation should record a `resolvedRefs` or similar Condition in the Policy's status.

When multiple Policies of the same type target the same object, one with a `sectionName` specified, and one without,
the one with a `sectionName` is more specific, and so will have all its settings apply. The less-specific Policy will
not attach to the target.

Note that the `sectionName` is currently intended to be used only for Direct Policy Attachment when references to
SectionName are actually needed. Inherited Policies are always applied to the entire object.
The `PolicyTargetReferenceWithSectionName` API can be used to apply a direct Policy to a section of an object.

### Advantages
* Incredibly flexible approach that should work well for both ingress and mesh
* Conceptually similar to existing ServicePolicy proposal and BackendPolicy
Expand Down