diff --git a/api/v1alpha1/securitypolicy_types.go b/api/v1alpha1/securitypolicy_types.go index 6d90536ae918..d14ccd92db93 100644 --- a/api/v1alpha1/securitypolicy_types.go +++ b/api/v1alpha1/securitypolicy_types.go @@ -70,6 +70,11 @@ type SecurityPolicySpec struct { // // +optional ExtAuth *ExtAuth `json:"extAuth,omitempty"` + + // ACL defines the IP deny/allow configuration. + // + // +optional + ACL *ACL `json:"acl,omitempty"` } // SecurityPolicyStatus defines the state of SecurityPolicy diff --git a/api/v1alpha1/validation/securitypolicy_validate.go b/api/v1alpha1/validation/securitypolicy_validate.go index 628d3f801730..34b43da9788e 100644 --- a/api/v1alpha1/validation/securitypolicy_validate.go +++ b/api/v1alpha1/validation/securitypolicy_validate.go @@ -8,6 +8,7 @@ package validation import ( "errors" "fmt" + "net" "net/mail" "net/url" @@ -56,6 +57,34 @@ func validateSecurityPolicySpec(spec *egv1a1.SecurityPolicySpec) error { errs = append(errs, err) } + if err := ValidateACL(spec.ACL); err != nil { + errs = append(errs, err) + } + + return utilerrors.NewAggregate(errs) +} + +// ValidateACL validates the provided ACL configuration. +func ValidateACL(acl *egv1a1.ACL) error { + var errs []error + if acl == nil { + return nil + } + + for _, ipBlock := range acl.Allow { + _, _, err := net.ParseCIDR(ipBlock.CIDR) + if err != nil { + errs = append(errs, fmt.Errorf("invalid allow CIDR: %s", ipBlock.CIDR)) + } + } + + for _, ipBlock := range acl.Deny { + _, _, err := net.ParseCIDR(ipBlock.CIDR) + if err != nil { + errs = append(errs, fmt.Errorf("invalid deny CIDR: %s", ipBlock.CIDR)) + } + } + return utilerrors.NewAggregate(errs) } diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 0d1ba2bbecce..bda524671a2a 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -19,6 +19,31 @@ import ( apisv1 "sigs.k8s.io/gateway-api/apis/v1" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ACL) DeepCopyInto(out *ACL) { + *out = *in + if in.Allow != nil { + in, out := &in.Allow, &out.Allow + *out = make([]IPBlock, len(*in)) + copy(*out, *in) + } + if in.Deny != nil { + in, out := &in.Deny, &out.Deny + *out = make([]IPBlock, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ACL. +func (in *ACL) DeepCopy() *ACL { + if in == nil { + return nil + } + out := new(ACL) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ActiveHealthCheck) DeepCopyInto(out *ActiveHealthCheck) { *out = *in @@ -1838,6 +1863,21 @@ func (in *HealthCheck) DeepCopy() *HealthCheck { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IPBlock) DeepCopyInto(out *IPBlock) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPBlock. +func (in *IPBlock) DeepCopy() *IPBlock { + if in == nil { + return nil + } + out := new(IPBlock) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *JSONPatchOperation) DeepCopyInto(out *JSONPatchOperation) { *out = *in @@ -3056,6 +3096,11 @@ func (in *SecurityPolicySpec) DeepCopyInto(out *SecurityPolicySpec) { *out = new(ExtAuth) (*in).DeepCopyInto(*out) } + if in.ACL != nil { + in, out := &in.ACL, &out.ACL + *out = new(ACL) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityPolicySpec. diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml index 7feb835b9387..8fdc497237ce 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -44,6 +44,41 @@ spec: spec: description: Spec defines the desired state of SecurityPolicy. properties: + acl: + description: ACL defines the IP deny/allow configuration. + properties: + allow: + items: + description: IPSpec defines the configuration for IP. + properties: + length: + description: 'Length contains the length of the IP network + prefix. Example: 24' + format: int32 + type: integer + prefix: + description: 'Prefix contains the IP prefix. Example: 1.2.3.0' + type: string + type: object + type: array + deny: + items: + description: IPSpec defines the configuration for IP. + properties: + length: + description: 'Length contains the length of the IP network + prefix. Example: 24' + format: int32 + type: integer + prefix: + description: 'Prefix contains the IP prefix. Example: 1.2.3.0' + type: string + type: object + type: array + type: object + x-kubernetes-validations: + - message: one of allow or deny must be specified + rule: (has(self.allow) || has(self.deny)) basicAuth: description: BasicAuth defines the configuration for the HTTP Basic Authentication. diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index c8b4b4fa7c7e..4caed4039b4d 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -27,6 +27,21 @@ API group. +#### ACL + + + +ACL defines the IP deny/allow configuration. + +_Appears in:_ +- [SecurityPolicySpec](#securitypolicyspec) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `allow` | _[IPBlock](#ipblock) array_ | true | Allow specifies the list of IPBlocks that are allowed to access the service. Other cidrs are denied. | +| `deny` | _[IPBlock](#ipblock) array_ | true | Deny specifies the list of IPBlocks that are denied to access the service. | + + #### ALPNProtocol _Underlying type:_ _string_ @@ -1229,6 +1244,20 @@ _Appears in:_ | `passive` | _[PassiveHealthCheck](#passivehealthcheck)_ | false | Passive passive check configuration | +#### IPBlock + + + +IPBlock defines policy on a particular IPBlock. + +_Appears in:_ +- [ACL](#acl) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `cidr` | _string_ | true | cidr is a string representing the IPBlock Valid examples are "192.168.1.0/24" or "2001:db8::/64" | + + #### InfrastructureProviderType _Underlying type:_ _string_ @@ -2154,6 +2183,7 @@ _Appears in:_ | `jwt` | _[JWT](#jwt)_ | false | JWT defines the configuration for JSON Web Token (JWT) authentication. | | `oidc` | _[OIDC](#oidc)_ | false | OIDC defines the configuration for the OpenID Connect (OIDC) authentication. | | `extAuth` | _[ExtAuth](#extauth)_ | false | ExtAuth defines the configuration for External Authorization. | +| `acl` | _[ACL](#acl)_ | false | ACL defines the IP deny/allow configuration. |