From ca39950940490f810333d1e84f4fa456ce5e8dce Mon Sep 17 00:00:00 2001 From: Surya Seetharaman Date: Sun, 5 Apr 2026 19:26:55 +0200 Subject: [PATCH] Update domain names API field Signed-off-by: Surya Seetharaman --- apis/v1alpha2/clusternetworkpolicy_types.go | 13 +++++++++++++ ...working.k8s.io_clusternetworkpolicies.yaml | 17 +++++++++++++++++ ...working.k8s.io_clusternetworkpolicies.yaml | 5 +++++ site-src/api-overview.md | 19 +++++++++++++++++++ 4 files changed, 54 insertions(+) diff --git a/apis/v1alpha2/clusternetworkpolicy_types.go b/apis/v1alpha2/clusternetworkpolicy_types.go index 6adf6530..42497e4d 100644 --- a/apis/v1alpha2/clusternetworkpolicy_types.go +++ b/apis/v1alpha2/clusternetworkpolicy_types.go @@ -58,6 +58,9 @@ type ClusterNetworkPolicyList struct { } // ClusterNetworkPolicySpec defines the desired state of ClusterNetworkPolicy. +// +// +// +kubebuilder:validation:XValidation:rule="self.tier == 'Baseline' ? !self.egress.exists(rule, rule.to.exists(peer, has(peer.domainNames))) : true",message="domainNames cannot be used in Baseline tier as NetworkPolicy cannot override FQDN rules" type ClusterNetworkPolicySpec struct { // Tier is used as the top-level grouping for network policy prioritization. // @@ -234,6 +237,7 @@ type ClusterNetworkPolicyIngressRule struct { // // // +kubebuilder:validation:XValidation:rule="!(self.to.exists(peer, has(peer.networks) || has(peer.nodes) || has(peer.domainNames)) && has(self.protocols) && self.protocols.exists(protocol, has(protocol.destinationNamedPort)))",message="networks/nodes/domainNames peer cannot be set with namedPorts since there are no namedPorts for networks/nodes/domainNames" +// +kubebuilder:validation:XValidation:rule="self.to.exists(peer, has(peer.domainNames)) ? self.action == 'Accept' : true",message="domainNames may only be used with Accept action" type ClusterNetworkPolicyEgressRule struct { // Name is an identifier for this rule, that may be no more than // 100 characters in length. This field should be used by the implementation @@ -393,6 +397,12 @@ type ClusterNetworkPolicyEgressPeer struct { // DomainNames provides a way to specify domain names as peers. // + // DomainNames is restricted to the Admin tier of ClusterNetworkPolicy only. + // Since Kubernetes NetworkPolicy does not have a FQDN selector, using + // domainNames in the Baseline tier would allow writing baseline rules that + // can't be replicated by an overriding NetworkPolicy, breaking the + // fundamental tier override model. + // // DomainNames is only supported for Accept rules. In order to control // access, DomainNames Accept rules should be used with a lower precedence // egress deny -- this allows the admin to maintain an explicit "allowlist" @@ -400,6 +410,9 @@ type ClusterNetworkPolicyEgressPeer struct { // // DomainNames can have up to 25 domain names specified in one rule. // + // See NPEP-133 for full details on expected behavior, DNS security model, + // and implementation guidelines. + // // // // +optional diff --git a/config/crd/experimental/policy.networking.k8s.io_clusternetworkpolicies.yaml b/config/crd/experimental/policy.networking.k8s.io_clusternetworkpolicies.yaml index c2f63e59..f9fb5336 100644 --- a/config/crd/experimental/policy.networking.k8s.io_clusternetworkpolicies.yaml +++ b/config/crd/experimental/policy.networking.k8s.io_clusternetworkpolicies.yaml @@ -281,6 +281,12 @@ spec: description: |- DomainNames provides a way to specify domain names as peers. + DomainNames is restricted to the Admin tier of ClusterNetworkPolicy only. + Since Kubernetes NetworkPolicy does not have a FQDN selector, using + domainNames in the Baseline tier would allow writing baseline rules that + can't be replicated by an overriding NetworkPolicy, breaking the + fundamental tier override model. + DomainNames is only supported for Accept rules. In order to control access, DomainNames Accept rules should be used with a lower precedence egress deny -- this allows the admin to maintain an explicit "allowlist" @@ -288,6 +294,9 @@ spec: DomainNames can have up to 25 domain names specified in one rule. + See NPEP-133 for full details on expected behavior, DNS security model, + and implementation guidelines. + items: description: |- @@ -565,6 +574,9 @@ spec: rule: '!(self.to.exists(peer, has(peer.networks) || has(peer.nodes) || has(peer.domainNames)) && has(self.protocols) && self.protocols.exists(protocol, has(protocol.destinationNamedPort)))' + - message: domainNames may only be used with Accept action + rule: 'self.to.exists(peer, has(peer.domainNames)) ? self.action + == ''Accept'' : true' maxItems: 25 type: array ingress: @@ -1174,6 +1186,11 @@ spec: - subject - tier type: object + x-kubernetes-validations: + - message: domainNames cannot be used in Baseline tier as NetworkPolicy + cannot override FQDN rules + rule: 'self.tier == ''Baseline'' ? !self.egress.exists(rule, rule.to.exists(peer, + has(peer.domainNames))) : true' status: description: Status is the status to be reported by the implementation. properties: diff --git a/config/crd/standard/policy.networking.k8s.io_clusternetworkpolicies.yaml b/config/crd/standard/policy.networking.k8s.io_clusternetworkpolicies.yaml index 173d5d32..fb281c47 100644 --- a/config/crd/standard/policy.networking.k8s.io_clusternetworkpolicies.yaml +++ b/config/crd/standard/policy.networking.k8s.io_clusternetworkpolicies.yaml @@ -1076,6 +1076,11 @@ spec: - subject - tier type: object + x-kubernetes-validations: + - message: domainNames cannot be used in Baseline tier as NetworkPolicy + cannot override FQDN rules + rule: 'self.tier == ''Baseline'' ? !self.egress.exists(rule, rule.to.exists(peer, + has(peer.domainNames))) : true' status: description: Status is the status to be reported by the implementation. properties: diff --git a/site-src/api-overview.md b/site-src/api-overview.md index cae9fac3..916f4f9b 100644 --- a/site-src/api-overview.md +++ b/site-src/api-overview.md @@ -108,6 +108,25 @@ will skip any lower precedence `Admin` tier rules and proceed to be evaluated by `Baseline` tier policies. When the `Pass` action is matched at the `Admin` tier, `NetworkPolicy` will apply next or if there is no `NetworkPolicy` match, `Baseline` policies will be evaluated. +### FQDN Selectors + +ClusterNetworkPolicy supports specifying egress peers by domain name using the +`domainNames` field. This allows administrators to create allowlist-style policies +for external services identified by FQDN rather than IP address. + +**Restrictions:** + +- **Admin tier only**: `domainNames` cannot be used in the Baseline tier. Since + Kubernetes NetworkPolicy has no FQDN selector, allowing `domainNames` in + Baseline would create rules that namespace admins cannot override with + NetworkPolicy, breaking the tier override model. +- **Accept action only**: `domainNames` may only be used with `Accept` rules. + To control access, combine a `domainNames` Accept rule with a lower-precedence + egress Deny rule to maintain an explicit allowlist of reachable domains. + +See [NPEP-133](npeps/npep-133-fqdn-egress-selector.md) for full details on +expected behavior, DNS security model, and implementation guidelines. + ### Priorities Integer priority values were added to the ClusterNetworkPolicy API to allow Cluster