diff --git a/apis/v1alpha1/authenticationfilter_types.go b/apis/v1alpha1/authenticationfilter_types.go new file mode 100644 index 0000000000..b441e0f721 --- /dev/null +++ b/apis/v1alpha1/authenticationfilter_types.go @@ -0,0 +1,109 @@ +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +kubebuilder:object:root=true +// +kubebuilder:storageversion +// +kubebuilder:subresource:status +// +kubebuilder:resource:categories=nginx-gateway-fabric,shortName=authfilter;authenticationfilter +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` + +// AuthenticationFilter configures request authentication and is +// referenced by HTTPRoute and GRPCRoute filters using ExtensionRef. +type AuthenticationFilter struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata"` + + // Spec defines the desired state of the AuthenticationFilter. + Spec AuthenticationFilterSpec `json:"spec"` + + // Status defines the state of the AuthenticationFilter. + Status AuthenticationFilterStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// AuthenticationFilterList contains a list of AuthenticationFilter resources. +type AuthenticationFilterList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + Items []AuthenticationFilter `json:"items"` +} + +// AuthenticationFilterSpec defines the desired configuration. +// +kubebuilder:validation:XValidation:message="for type=Basic, spec.basic must be set",rule="!(!has(self.basic) && self.type == 'Basic')" +// +//nolint:lll +type AuthenticationFilterSpec struct { + // Basic configures HTTP Basic Authentication. + // + // +optional + Basic *BasicAuth `json:"basic,omitempty"` + + // Type selects the authentication mechanism. + Type AuthType `json:"type"` +} + +// AuthType defines the authentication mechanism. +// +// +kubebuilder:validation:Enum=Basic; +type AuthType string + +const ( + // AuthTypeBasic is the HTTP Basic Authentication mechanism. + AuthTypeBasic AuthType = "Basic" +) + +// BasicAuth configures HTTP Basic Authentication. +type BasicAuth struct { + // SecretRef allows referencing a Secret in the same namespace. + SecretRef LocalObjectReference `json:"secretRef"` + + // Realm used by NGINX `auth_basic` directive. + // https://nginx.org/en/docs/http/ngx_http_auth_basic_module.html#auth_basic + // Also configures "realm="" in WWW-Authenticate header in error page location. + Realm string `json:"realm"` +} + +// LocalObjectReference specifies a local Kubernetes object. +type LocalObjectReference struct { + // Name is the referenced object. + Name string `json:"name"` +} + +// AuthenticationFilterStatus defines the state of AuthenticationFilter. +type AuthenticationFilterStatus struct { + // Controllers is a list of Gateway API controllers that processed the AuthenticationFilter + // and the status of the AuthenticationFilter with respect to each controller. + // + // +kubebuilder:validation:MaxItems=16 + Controllers []ControllerStatus `json:"controllers,omitempty"` +} + +// AuthenticationFilterConditionType is a type of condition associated with AuthenticationFilter. +type AuthenticationFilterConditionType string + +// AuthenticationFilterConditionReason is a reason for an AuthenticationFilter condition type. +type AuthenticationFilterConditionReason string + +const ( + // AuthenticationFilterConditionTypeAccepted indicates that the AuthenticationFilter is accepted. + // + // Possible reasons for this condition to be True: + // * Accepted + // + // Possible reasons for this condition to be False: + // * Invalid. + AuthenticationFilterConditionTypeAccepted AuthenticationFilterConditionType = "Accepted" + + // AuthenticationFilterConditionReasonAccepted is used with the Accepted condition type when + // the condition is true. + AuthenticationFilterConditionReasonAccepted AuthenticationFilterConditionReason = "Accepted" + + // AuthenticationFilterConditionReasonInvalid is used with the Accepted condition type when + // the filter is invalid. + AuthenticationFilterConditionReasonInvalid AuthenticationFilterConditionReason = "Invalid" +) diff --git a/apis/v1alpha1/zz_generated.deepcopy.go b/apis/v1alpha1/zz_generated.deepcopy.go index d07825de2d..21791c1dcd 100644 --- a/apis/v1alpha1/zz_generated.deepcopy.go +++ b/apis/v1alpha1/zz_generated.deepcopy.go @@ -10,6 +10,123 @@ 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 *AuthenticationFilter) DeepCopyInto(out *AuthenticationFilter) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthenticationFilter. +func (in *AuthenticationFilter) DeepCopy() *AuthenticationFilter { + if in == nil { + return nil + } + out := new(AuthenticationFilter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *AuthenticationFilter) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthenticationFilterList) DeepCopyInto(out *AuthenticationFilterList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]AuthenticationFilter, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthenticationFilterList. +func (in *AuthenticationFilterList) DeepCopy() *AuthenticationFilterList { + if in == nil { + return nil + } + out := new(AuthenticationFilterList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *AuthenticationFilterList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthenticationFilterSpec) DeepCopyInto(out *AuthenticationFilterSpec) { + *out = *in + if in.Basic != nil { + in, out := &in.Basic, &out.Basic + *out = new(BasicAuth) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthenticationFilterSpec. +func (in *AuthenticationFilterSpec) DeepCopy() *AuthenticationFilterSpec { + if in == nil { + return nil + } + out := new(AuthenticationFilterSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthenticationFilterStatus) DeepCopyInto(out *AuthenticationFilterStatus) { + *out = *in + if in.Controllers != nil { + in, out := &in.Controllers, &out.Controllers + *out = make([]ControllerStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthenticationFilterStatus. +func (in *AuthenticationFilterStatus) DeepCopy() *AuthenticationFilterStatus { + if in == nil { + return nil + } + out := new(AuthenticationFilterStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BasicAuth) DeepCopyInto(out *BasicAuth) { + *out = *in + out.SecretRef = in.SecretRef +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BasicAuth. +func (in *BasicAuth) DeepCopy() *BasicAuth { + if in == nil { + return nil + } + out := new(BasicAuth) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClientBody) DeepCopyInto(out *ClientBody) { *out = *in @@ -197,6 +314,21 @@ func (in *ControllerStatus) DeepCopy() *ControllerStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LocalObjectReference) DeepCopyInto(out *LocalObjectReference) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalObjectReference. +func (in *LocalObjectReference) DeepCopy() *LocalObjectReference { + if in == nil { + return nil + } + out := new(LocalObjectReference) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Logging) DeepCopyInto(out *Logging) { *out = *in diff --git a/config/crd/bases/gateway.nginx.org_authenticationfilters.yaml b/config/crd/bases/gateway.nginx.org_authenticationfilters.yaml new file mode 100644 index 0000000000..002197fd5b --- /dev/null +++ b/config/crd/bases/gateway.nginx.org_authenticationfilters.yaml @@ -0,0 +1,191 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.19.0 + name: authenticationfilters.gateway.nginx.org +spec: + group: gateway.nginx.org + names: + categories: + - nginx-gateway-fabric + kind: AuthenticationFilter + listKind: AuthenticationFilterList + plural: authenticationfilters + shortNames: + - authfilter + - authenticationfilter + singular: authenticationfilter + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + AuthenticationFilter configures request authentication and is + referenced by HTTPRoute and GRPCRoute filters using ExtensionRef. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of the AuthenticationFilter. + properties: + basic: + description: Basic configures HTTP Basic Authentication. + properties: + realm: + description: |- + Realm used by NGINX `auth_basic` directive. + https://nginx.org/en/docs/http/ngx_http_auth_basic_module.html#auth_basic + Also configures "realm="" in WWW-Authenticate header in error page location. + type: string + secretRef: + description: SecretRef allows referencing a Secret in the same + namespace. + properties: + name: + description: Name is the referenced object. + type: string + required: + - name + type: object + required: + - realm + - secretRef + type: object + type: + description: Type selects the authentication mechanism. + enum: + - Basic + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: for type=Basic, spec.basic must be set + rule: '!(!has(self.basic) && self.type == ''Basic'')' + status: + description: Status defines the state of the AuthenticationFilter. + properties: + controllers: + description: |- + Controllers is a list of Gateway API controllers that processed the AuthenticationFilter + and the status of the AuthenticationFilter with respect to each controller. + items: + properties: + conditions: + description: Conditions describe the status of the SnippetsFilter. + items: + description: Condition contains details for one aspect of + the current state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: |- + ControllerName is a domain/path string that indicates the name of the + controller that wrote this status. This corresponds with the + controllerName field on GatewayClass. + + Example: "example.net/gateway-controller". + + The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are + valid Kubernetes names + (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + + Controllers MUST populate this field when writing status. Controllers should ensure that + entries to status populated with their ControllerName are cleaned up when they are no + longer necessary. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + required: + - controllerName + type: object + maxItems: 16 + type: array + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index b067d64141..f203dec505 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -1,6 +1,7 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: + - bases/gateway.nginx.org_authenticationfilters.yaml - bases/gateway.nginx.org_clientsettingspolicies.yaml - bases/gateway.nginx.org_nginxgateways.yaml - bases/gateway.nginx.org_nginxproxies.yaml diff --git a/deploy/crds.yaml b/deploy/crds.yaml index 2a526a961f..569d530f0a 100644 --- a/deploy/crds.yaml +++ b/deploy/crds.yaml @@ -1,5 +1,196 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.19.0 + name: authenticationfilters.gateway.nginx.org +spec: + group: gateway.nginx.org + names: + categories: + - nginx-gateway-fabric + kind: AuthenticationFilter + listKind: AuthenticationFilterList + plural: authenticationfilters + shortNames: + - authfilter + - authenticationfilter + singular: authenticationfilter + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + AuthenticationFilter configures request authentication and is + referenced by HTTPRoute and GRPCRoute filters using ExtensionRef. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of the AuthenticationFilter. + properties: + basic: + description: Basic configures HTTP Basic Authentication. + properties: + realm: + description: |- + Realm used by NGINX `auth_basic` directive. + https://nginx.org/en/docs/http/ngx_http_auth_basic_module.html#auth_basic + Also configures "realm="" in WWW-Authenticate header in error page location. + type: string + secretRef: + description: SecretRef allows referencing a Secret in the same + namespace. + properties: + name: + description: Name is the referenced object. + type: string + required: + - name + type: object + required: + - realm + - secretRef + type: object + type: + description: Type selects the authentication mechanism. + enum: + - Basic + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: for type=Basic, spec.basic must be set + rule: '!(!has(self.basic) && self.type == ''Basic'')' + status: + description: Status defines the state of the AuthenticationFilter. + properties: + controllers: + description: |- + Controllers is a list of Gateway API controllers that processed the AuthenticationFilter + and the status of the AuthenticationFilter with respect to each controller. + items: + properties: + conditions: + description: Conditions describe the status of the SnippetsFilter. + items: + description: Condition contains details for one aspect of + the current state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: |- + ControllerName is a domain/path string that indicates the name of the + controller that wrote this status. This corresponds with the + controllerName field on GatewayClass. + + Example: "example.net/gateway-controller". + + The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are + valid Kubernetes names + (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + + Controllers MUST populate this field when writing status. Controllers should ensure that + entries to status populated with their ControllerName are cleaned up when they are no + longer necessary. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + required: + - controllerName + type: object + maxItems: 16 + type: array + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.19.0 diff --git a/examples/basic-authentication/basic-auth.yaml b/examples/basic-authentication/basic-auth.yaml index 39ffa48b21..993cb31fef 100644 --- a/examples/basic-authentication/basic-auth.yaml +++ b/examples/basic-authentication/basic-auth.yaml @@ -17,9 +17,7 @@ spec: secretRef: name: basic-auth1 realm: "Restricted basic-auth1" - onFailure: - statusCode: 401 - scheme: Basic + --- apiVersion: v1 kind: Secret @@ -40,6 +38,3 @@ spec: secretRef: name: basic-auth2 realm: "Restricted basic-auth2" - onFailure: - statusCode: 401 - scheme: Basic