diff --git a/api/v1alpha1/serviceroute_admission_envtest_test.go b/api/v1alpha1/serviceroute_admission_envtest_test.go index 2929fc2..e6be2c0 100644 --- a/api/v1alpha1/serviceroute_admission_envtest_test.go +++ b/api/v1alpha1/serviceroute_admission_envtest_test.go @@ -94,6 +94,15 @@ func TestTranslatedAPIAdmission(t *testing.T) { p.Spec.Authorization = nil }, false}, {"translated", func(*networkv1alpha1.ServiceRoutePolicy) {}, false}, + {"persistent", func(p *networkv1alpha1.ServiceRoutePolicy) { + p.Spec.Authorization = &networkv1alpha1.ServiceRouteAuthorization{Persistent: true} + }, false}, + {"persistent-with-deadline", func(p *networkv1alpha1.ServiceRoutePolicy) { + p.Spec.Authorization.Persistent = true + }, true}, + {"missing-deadline", func(p *networkv1alpha1.ServiceRoutePolicy) { + p.Spec.Authorization = &networkv1alpha1.ServiceRouteAuthorization{} + }, true}, } { t.Run(tt.name, func(t *testing.T) { p := policy(tt.name) diff --git a/api/v1alpha1/serviceroute_types.go b/api/v1alpha1/serviceroute_types.go index 85451b5..7d40197 100644 --- a/api/v1alpha1/serviceroute_types.go +++ b/api/v1alpha1/serviceroute_types.go @@ -145,8 +145,7 @@ type ServiceRoutePolicySpec struct { // +optional Frontend *ServiceRouteFrontend `json:"frontend,omitempty"` - // Authorization bounds translated access independently of application leases. - // Only trusted networking integration may renew this deadline. + // Authorization defines the lifetime of translated service access. // +optional Authorization *ServiceRouteAuthorization `json:"authorization,omitempty"` @@ -168,11 +167,17 @@ type ServiceRoutePolicySpec struct { Region string `json:"region,omitempty"` } -// ServiceRouteAuthorization bounds one network authorization episode. +// ServiceRouteAuthorization defines persistent or time-bounded access. +// +kubebuilder:validation:XValidation:rule="has(self.persistent) && self.persistent ? !has(self.validUntil) : has(self.validUntil)",message="persistent access must omit validUntil; bounded access requires validUntil" type ServiceRouteAuthorization struct { + // Persistent retains access until policy withdrawal or VPC lifetime replacement. + // +optional + Persistent bool `json:"persistent,omitempty"` + // ValidUntil is the absolute UTC deadline for requests and existing replies. // Node controllers reject deadlines more than two minutes in the future. - ValidUntil metav1.Time `json:"validUntil"` + // +optional + ValidUntil metav1.Time `json:"validUntil,omitempty"` } // ServiceRouteVPCReference identifies one immutable Cloud API VPC lifetime. diff --git a/config/crd/network.datumapis.com_serviceroutepolicies.yaml b/config/crd/network.datumapis.com_serviceroutepolicies.yaml index 9ef3bdf..d07819e 100644 --- a/config/crd/network.datumapis.com_serviceroutepolicies.yaml +++ b/config/crd/network.datumapis.com_serviceroutepolicies.yaml @@ -105,19 +105,25 @@ spec: type: object x-kubernetes-map-type: atomic authorization: - description: |- - Authorization bounds translated access independently of application leases. - Only trusted networking integration may renew this deadline. + description: Authorization defines the lifetime of translated service + access. properties: + persistent: + description: Persistent retains access until policy withdrawal + or VPC lifetime replacement. + type: boolean validUntil: description: |- ValidUntil is the absolute UTC deadline for requests and existing replies. Node controllers reject deadlines more than two minutes in the future. format: date-time type: string - required: - - validUntil type: object + x-kubernetes-validations: + - message: persistent access must omit validUntil; bounded access + requires validUntil + rule: 'has(self.persistent) && self.persistent ? !has(self.validUntil) + : has(self.validUntil)' consumerVPCRef: description: |- ConsumerVPCRef pins authorization to the immutable lifetime of the VPC diff --git a/docs/api/gateway.md b/docs/api/gateway.md index 7e2818b..7e11f6d 100644 --- a/docs/api/gateway.md +++ b/docs/api/gateway.md @@ -558,7 +558,7 @@ _Appears in:_ -ServiceRouteAuthorization bounds one network authorization episode. +ServiceRouteAuthorization defines persistent or time-bounded access. @@ -567,6 +567,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | +| `persistent` _boolean_ | Persistent retains access until policy withdrawal or VPC lifetime replacement. | | | | `validUntil` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v/#time-v1-meta)_ | ValidUntil is the absolute UTC deadline for requests and existing replies.
Node controllers reject deadlines more than two minutes in the future. | | | @@ -646,7 +647,7 @@ _Appears in:_ | `serviceRef` _[ServiceEndpointReference](#serviceendpointreference)_ | ServiceRef identifies the ServiceEndpoint in this namespace. | | Required: \{\}
| | `consumerVPCRef` _[ServiceRouteVPCReference](#serviceroutevpcreference)_ | ConsumerVPCRef pins authorization to the immutable lifetime of the VPC
selected by AttachmentSelector. Galactic resolves the name through the
Cloud API and requires both the live name and UID to match. | | | | `frontend` _[ServiceRouteFrontend](#serviceroutefrontend)_ | Frontend is the address presented inside the consumer VPC. When set,
Galactic translates it to the ServiceEndpoint address and restores it on
replies. | | | -| `authorization` _[ServiceRouteAuthorization](#servicerouteauthorization)_ | Authorization bounds translated access independently of application leases.
Only trusted networking integration may renew this deadline. | | | +| `authorization` _[ServiceRouteAuthorization](#servicerouteauthorization)_ | Authorization defines the lifetime of translated service access. | | | | `attachmentSelector` _[LabelSelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v/#labelselector-v1-meta)_ | AttachmentSelector selects eligible VPC attachments by authoritative
labels. Labels that grant access to platform services must be assigned by
the network control plane, not by tenants. | | Required: \{\}
| | `protocolPorts` _[ServiceRouteProtocolPort](#servicerouteprotocolport) array_ | ProtocolPorts limits the traffic that the route is intended to carry.
An empty list means the endpoint's declared port and protocol are used. | | | | `region` _string_ | Region limits selected attachments to a region. An empty value means the
policy applies in every region where the endpoint is available. | | |